实验目的:
1. 了解BMP图像文件格式;
2. 了解图像显示的方法;
实验内容:
1. 用MFC构建图像显示和操作的界面;
2. 掌握图像显示的方法并实现它;
3. 编写读入BMP图像文件的程序;
4. 编写把图像写入BMP图像文件的程序。
实验环境:
1. 机器:PC机
2. OS:WindowsXP Professional +SP2
3. 开发平台:MS Visual Studio 2005+SP1
4. 编程语言:C\C++\VC++
几张截图:
我的代码是从之前的工作中剪裁拼接,加以修改而成,对于这一次实验来说,代码有些冗余。
*********************************************************
/*
ClassImageZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 ImageZ ,标准图像类,所有算法都在此图像上进行。
*/
#ifndef __CLASSIMAGE_Z_H_INCLUDED__
#define __CLASSIMAGE_Z_H_INCLUDED__
/*
ImageZ 图像数据格式(参见 FormatImageZ.h):
真彩色图像:
像素数据:FORMAT_COLOR_B8G8R8A8_Z
调色板图像:
调色板数据:FORMAT_COLOR_B8G8R8A8_Z
像素数据:FORMAT_INDEX_I8_Z
*/
#include "TypeZ.h"
#include "FormatImageZ.h"
/* ImageZ 图像数据格式中的一些常数,使用这些常数来访问图像数据 */
/* ImageZ 图像数据格式中 颜色的格式 */
#define IMAGEZ_FORMAT_COLOR_Z FORMAT_COLOR_B8G8R8A8_Z
/* ImageZ 图像数据格式中 颜色索引的格式 */
#define IMAGEZ_FORMAT_INDEX_Z FORMAT_INDEX_I8_Z
/* ImageZ 图像数据格式中 颜色的大小,单位 字节 */
#define IMAGEZ_COLOR_SIZE_Z 4
/* ImageZ 图像数据格式中 颜色中各分量的偏移,单位 字节 */
#define IMAGEZ_OFFSET_BLUE_Z 0
#define IMAGEZ_OFFSET_GREEN_Z 1
#define IMAGEZ_OFFSET_RED_Z 2
#define IMAGEZ_OFFSET_ALPHA_Z 3
/* ImageZ 图像数据格式中 索引的大小,单位 字节 */
#define IMAGEZ_INDEX_SIZE_Z 1
/* 图像信息头 */
struct _ImageInfoZ
{
U32 width, height; /* 图像宽高,单位 像素 */
U32 linePitch; /* 对齐后的宽度,用于定位像素,单位 字节 */
U08 *pPixel; /* 像素数据,需要对齐 */
U32 colorNum; /* 调色板颜色数量,== 0 真彩色图像,> 0 调色板图像。判断是否真彩的唯一指标 */
U08 *pPalette; /* 调色板数据,无需对齐,== NULL 真彩色图像 */
};
typedef struct _ImageInfoZ ImageInfoZ;
typedef ImageInfoZ* ImageZ;
typedef const ImageInfoZ* cImageZ;
/* 判断 ImageZ 数据结构是否合法 */
PublicFuncZ B32 isImageValidZ( cImageZ img );
/* 创建新图像 */
/* 失败返回 NULL */
PublicFuncZ ImageZ createImageZ( U32 width, U32 height, U32 colorNum );
/* 创建相同图像,只是不复制图像调色板数据和像素数据 */
/* 失败返回 NULL */
PublicFuncZ ImageZ createImageFromImageInfoZ( cImageZ src );
/* 复制图像 */
/* 失败返回 NULL */
PublicFuncZ ImageZ createImageFromImageZ( cImageZ src );
/* 销毁图像 */
PublicFuncZ R32 destroyImageZ( ImageZ img );
/* 判断点是否在图像内 */
PublicFuncZ B32 isInImageZ( cImageZ img, U32 x, U32 y );
/* 宽高 */
PublicFuncZ U32 getImageWidthZ( cImageZ img );
PublicFuncZ U32 getImageHeightZ( cImageZ img );
PublicFuncZ U32 getImageLinePitchZ( cImageZ img );
/* 像素 颜色 */
PublicFuncZ R32 getImageColorZ( cImageZ img, U32 x, U32 y, ColorZ *pColor );
PublicFuncZ R32 putImageColorZ( ImageZ img, U32 x, U32 y, const ColorZ *pColor );
/* 像素 调色板索引,只对调色板图像有效 */
PublicFuncZ R32 getImageIndexZ( cImageZ img, U32 x, U32 y, U08 *pIndex );
PublicFuncZ R32 putImageIndexZ( cImageZ img, U32 x, U32 y, U08 index );
/* 像素 根据图像格式判断是颜色还是调色板索引 */
PublicFuncZ R32 getImagePixelZ( cImageZ img, U32 x, U32 y, PixelZ *pPixel );
PublicFuncZ R32 putImagePixelZ( cImageZ img, U32 x, U32 y, const PixelZ *pPixel );
/* 调色板 */
PublicFuncZ B32 isImagePaletteUsedZ( cImageZ img );
PublicFuncZ U32 getImageColorNumZ( cImageZ img );
/* 获取调色板中某颜色 */
PublicFuncZ R32 getImagePaletteColorZ( cImageZ img, U08 index, ColorZ *pColor );
/* 设置调色板中某颜色 */
PublicFuncZ R32 putImagePaletteColorZ( ImageZ img, U08 index, const ColorZ *pColor );
/* 调色板颜色数量相同,则复制调色板;都无调色板,也算执行成功 */
PublicFuncZ R32 copyImagePaletteZ( ImageZ dest, cImageZ src );
/* 交换图像数据 */
PublicFuncZ R32 swapImageZ( ImageZ imgA, ImageZ imgB );
#endif /* __CLASSIMAGE_Z_H_INCLUDED__ */
*********************************************************
/*
ClassImageZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 ImageZ ,标准图像类,所有算法都在此图像上进行。
*/
#include "stdafx.h"
#include "ClassImageZ.h"
#include <malloc.h>
#include <string.h>
PublicFuncZ B32 isImageValidZ( cImageZ img ) {
return ( (NULL != img) &&
(0 < img->width) && (0 < img->height) &&
(NULL != img->pPixel) &&
( ( (0 == img->colorNum) &&
(NULL == img->pPalette) &&
(getFormatLinePitchZ(img->width, IMAGEZ_FORMAT_COLOR_Z) == img->linePitch)
) ||
( (0x2 <= img->colorNum) && (0x100 >= img->colorNum) &&
(NULL != img->pPalette) &&
(getFormatLinePitchZ(img->width, IMAGEZ_FORMAT_INDEX_Z) == img->linePitch)
)
)
);
}
PublicFuncZ ImageZ createImageZ( U32 width, U32 height, U32 colorNum ) {
ImageZ img;
if ( (0 >= width) || (0 >= height) || (0x100 < colorNum) || (0x1 == colorNum) ) {
return NULL;
}
img = (ImageZ)malloc( sizeof(ImageInfoZ) );
if ( NULL == img ) {
return NULL;
}
img->width = width;
img->height = height;
img->linePitch = getFormatLinePitchZ( img->width, ((0 == colorNum) ? IMAGEZ_FORMAT_COLOR_Z : IMAGEZ_FORMAT_INDEX_Z) );
img->pPixel = (U08*)malloc( img->linePitch * img->height );
if ( NULL == img->pPixel ) {
free( img );
return NULL;
}
img->colorNum = colorNum;
img->pPalette = NULL;
if ( 0 < colorNum ) {
img->pPalette = (U08*)malloc( IMAGEZ_COLOR_SIZE_Z * img->colorNum );
if ( NULL == img->pPalette ) {
free( img->pPixel );
free( img );
return NULL;
}
}
return img;
}
PublicFuncZ ImageZ createImageFromImageInfoZ( cImageZ src ) {
if ( !isImageValidZ(src) ) {
return NULL;
}
return createImageZ( src->width, src->height, src->colorNum );
}
PublicFuncZ ImageZ createImageFromImageZ( cImageZ src ) {
ImageZ img = createImageFromImageInfoZ( src );
if ( NULL == img ) {
return NULL;
}
if ( 0 < img->colorNum ) {
memcpy( img->pPalette, src->pPalette, IMAGEZ_COLOR_SIZE_Z * img->colorNum );
}
memcpy( img->pPixel, src->pPixel, img->linePitch * img->height );
return img;
}
PublicFuncZ R32 destroyImageZ( ImageZ img ) {
if ( !isImageValidZ(img) ) {
return RERR;
}
if ( NULL != img->pPalette ) {
free( img->pPalette );
}
free( img->pPixel );
free( img );
return ROK;
}
PublicFuncZ B32 isInImageZ( cImageZ img, U32 x, U32 y ) {
return ( isImageValidZ(img) && (x < img->width) && (y < img->height) );
}
PublicFuncZ U32 getImageWidthZ( cImageZ img ) {
return ( isImageValidZ(img) ? img->width : 0 );
}
PublicFuncZ U32 getImageHeightZ( cImageZ img ) {
return ( isImageValidZ(img) ? img->height : 0 );
}
PublicFuncZ U32 getImageLinePitchZ( cImageZ img ) {
return ( isImageValidZ(img) ? img->linePitch : 0 );
}
PublicFuncZ R32 getImageColorZ( cImageZ img, U32 x, U32 y, ColorZ *pColor ) {
U08 *p;
if ( isInImageZ(img, x, y) && (NULL != pColor) ) {
if ( 0 == img->colorNum ) {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_COLOR_SIZE_Z;
}
else {
p = img->pPalette + IMAGEZ_COLOR_SIZE_Z * ((img->pPixel)[ y * img->linePitch + x * IMAGEZ_INDEX_SIZE_Z
]);
}
pColor->b = p[ IMAGEZ_OFFSET_BLUE_Z ];
pColor->g = p[ IMAGEZ_OFFSET_GREEN_Z ];
pColor->r = p[ IMAGEZ_OFFSET_RED_Z ];
pColor->a = p[ IMAGEZ_OFFSET_ALPHA_Z ];
return ROK;
}
return RERR;
}
PublicFuncZ R32 putImageColorZ( ImageZ img, U32 x, U32 y, const ColorZ *pColor ) {
U08 *p;
if ( isInImageZ(img, x, y) && (NULL != pColor) ) {
if ( 0 == img->colorNum ) {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_COLOR_SIZE_Z;
p[ IMAGEZ_OFFSET_BLUE_Z ] = pColor->b;
p[ IMAGEZ_OFFSET_GREEN_Z ] = pColor->g;
p[ IMAGEZ_OFFSET_RED_Z ] = pColor->r;
p[ IMAGEZ_OFFSET_ALPHA_Z ] = pColor->a;
}
else {
/* 不支持调色板图像 */
return RERR;
}
return ROK;
}
return RERR;
}
PublicFuncZ R32 getImageIndexZ( cImageZ img, U32 x, U32 y, U08 *pIndex ) {
if ( isInImageZ(img, x, y) && (NULL != pIndex) && (0 < img->colorNum) ) {
*pIndex = (img->pPixel)[ y * img->linePitch + x ];
return ROK;
}
return RERR;
}
PublicFuncZ R32 putImageIndexZ( cImageZ img, U32 x, U32 y, U08 index ) {
if ( isInImageZ(img, x, y) && (index < img->colorNum) ) {
(img->pPixel)[ y * img->linePitch + x ] = index;
return ROK;
}
return RERR;
}
PublicFuncZ R32 getImagePixelZ( cImageZ img, U32 x, U32 y, PixelZ *pPixel ) {
U08 *p;
if ( isInImageZ(img, x, y) && (NULL != pPixel) ) {
if ( 0 == img->colorNum ) {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_COLOR_SIZE_Z;
pPixel->color.b = p[ IMAGEZ_OFFSET_BLUE_Z ];
pPixel->color.g = p[ IMAGEZ_OFFSET_GREEN_Z ];
pPixel->color.r = p[ IMAGEZ_OFFSET_RED_Z ];
pPixel->color.a = p[ IMAGEZ_OFFSET_ALPHA_Z ];
}
else {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_INDEX_SIZE_Z;
pPixel->index = p[ 0 ];
}
return ROK;
}
return RERR;
}
PublicFuncZ R32 putImagePixelZ( cImageZ img, U32 x, U32 y, const PixelZ *pPixel ) {
U08 *p;
if ( isInImageZ(img, x, y) && (NULL != pPixel) ) {
if ( 0 == img->colorNum ) {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_COLOR_SIZE_Z;
p[ IMAGEZ_OFFSET_BLUE_Z ] = pPixel->color.b;
p[ IMAGEZ_OFFSET_GREEN_Z ] = pPixel->color.g;
p[ IMAGEZ_OFFSET_RED_Z ] = pPixel->color.r;
p[ IMAGEZ_OFFSET_ALPHA_Z ] = pPixel->color.a;
}
else {
p = img->pPixel + y * img->linePitch + x * IMAGEZ_INDEX_SIZE_Z;
p[ 0 ] = pPixel->index;
}
return ROK;
}
return RERR;
}
PublicFuncZ B32 isImagePaletteUsedZ( cImageZ img ) {
return ( isImageValidZ(img) && (0 < img->colorNum) );
}
PublicFuncZ U32 getImageColorNumZ( cImageZ img ) {
return ( isImageValidZ(img) ? img->colorNum : 0 );
}
PublicFuncZ R32 getImagePaletteColorZ( cImageZ img, U08 index, ColorZ *pColor ) {
U08 *p;
if ( isImageValidZ(img) && (index < img->colorNum) && (NULL != pColor) ) {
p = img->pPalette + IMAGEZ_COLOR_SIZE_Z * index;
pColor->b = p[ IMAGEZ_OFFSET_BLUE_Z ];
pColor->g = p[ IMAGEZ_OFFSET_GREEN_Z ];
pColor->r = p[ IMAGEZ_OFFSET_RED_Z ];
pColor->a = p[ IMAGEZ_OFFSET_ALPHA_Z ];
return ROK;
}
return RERR;
}
PublicFuncZ R32 putImagePaletteColorZ( ImageZ img, U08 index, const ColorZ *pColor ) {
U08 *p;
if ( isImageValidZ(img) && (index < img->colorNum) && (NULL != pColor) ) {
p = img->pPalette + IMAGEZ_COLOR_SIZE_Z * index;
p[ IMAGEZ_OFFSET_BLUE_Z ] = pColor->b;
p[ IMAGEZ_OFFSET_GREEN_Z ] = pColor->g;
p[ IMAGEZ_OFFSET_RED_Z ] = pColor->r;
p[ IMAGEZ_OFFSET_ALPHA_Z ] = pColor->a;
return ROK;
}
return RERR;
}
PublicFuncZ R32 copyImagePaletteZ( ImageZ dest, cImageZ src ) {
if ( isImageValidZ(dest) && isImageValidZ(src) && (dest->colorNum == src->colorNum) ) {
if ( 0 < src->colorNum ) {
memcpy( dest->pPalette, src->pPalette, IMAGEZ_COLOR_SIZE_Z * src->colorNum );
}
return ROK;
}
return RERR;
}
PublicFuncZ R32 swapImageZ( ImageZ imgA, ImageZ imgB ) {
U08 *p;
U32 u;
if ( (!isImageValidZ(imgA)) || (!isImageValidZ(imgB)) ) {
return RERR;
}
#define SW(a,b,t) t = a; a = b; b = t
SW( imgA->width, imgB->width, u );
SW( imgA->height, imgB->height, u );
SW( imgA->linePitch, imgB->linePitch, u );
SW( imgA->pPixel, imgB->pPixel, p );
SW( imgA->colorNum, imgB->colorNum, u );
SW( imgA->pPalette, imgB->pPalette, p );
#undef SW
return ROK;
}
*********************************************************
/*
ClassStreamZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 StreamZ ,数据流类。封装对 文件 或 内存 的处理。
*/
#ifndef __CLASSSTREAM_Z_H_INCLUDED__
#define __CLASSSTREAM_Z_H_INCLUDED__
#include "TypeZ.h"
#include <stdio.h>
/* 使用模式 */
/* 读文件 */
#define STREAM_MODE_FILE_IN_Z 0x01
/* 写文件 */
#define STREAM_MODE_FILE_OUT_Z 0x02
/* 读内存 */
#define STREAM_MODE_MEMORY_IN_Z 0x03
/* 写内存 */
#define STREAM_MODE_MEMORY_OUT_Z 0x04
struct _StreamInfoZ
{
U32 mode; /* 使用模式 */
FILE *file; /* 关联的文件 */
U08 *memory; /* 关联的内存 或 读写文件的缓存 */
U32 memSize; /* memory 所占内存大小 */
U32 memEnd; /* memory 中的实际数据的边界 */
U32 memPos; /* 当前在 memory 中的读写位置 */
};
typedef struct _StreamInfoZ StreamInfoZ;
typedef StreamInfoZ * StreamZ;
typedef const StreamInfoZ * cStreamZ;
/* 判断 StreamZ 数据结构是否合法 */
PublicFuncZ B32 isStreamValidZ( cStreamZ srm );
/* 新建流,并与文件关联 */
/* 失败返回 NULL */
PublicFuncZ StreamZ createStreamFromFileZ( cSz08 fileName, U32 modeFile );
/* 新建流,并与内存关联 */
/* 失败返回 NULL */
PublicFuncZ StreamZ createStreamFromMemoryZ( U08 *memory, U32 memSize, U32 modeMemory );
/* 销毁流,并释放资源 */
PublicFuncZ R32 destroyStreamZ( StreamZ srm );
/* 输入 */
PublicFuncZ R32 getStreamU08Z( StreamZ srm, U08 *pU );
PublicFuncZ R32 getStreamU08ArrayZ( StreamZ srm, U08 *arr, U32 len );
/* Lbf 低位字节先,Mbf 高位字节先 */
PublicFuncZ R32 getStreamU16LbfZ( StreamZ srm, U16 *pU );
PublicFuncZ R32 getStreamU16MbfZ( StreamZ srm, U16 *pU );
PublicFuncZ R32 getStreamU32LbfZ( StreamZ srm, U32 *pU );
PublicFuncZ R32 getStreamU32MbfZ( StreamZ srm, U32 *pU );
PublicFuncZ R32 getStreamI32LbfZ( StreamZ srm, I32 *pI );
PublicFuncZ R32 getStreamI32MbfZ( StreamZ srm, I32 *pI );
/* 跳过若干字节 */
PublicFuncZ R32 getStreamSkipZ( StreamZ srm, U32 n );
/* 输出 */
PublicFuncZ R32 putStreamU08Z( StreamZ srm, U08 u );
PublicFuncZ R32 putStreamU08ArrayZ( StreamZ srm, const U08 *arr, U32 len );
/* Lbf 低位字节先,Mbf 高位字节先 */
PublicFuncZ R32 putStreamU16LbfZ( StreamZ srm, U16 u );
PublicFuncZ R32 putStreamU16MbfZ( StreamZ srm, U16 u );
PublicFuncZ R32 putStreamU32LbfZ( StreamZ srm, U32 u );
PublicFuncZ R32 putStreamU32MbfZ( StreamZ srm, U32 u );
PublicFuncZ R32 putStreamI32LbfZ( StreamZ srm, I32 i );
PublicFuncZ R32 putStreamI32MbfZ( StreamZ srm, I32 i );
/* 将写文件缓存清空,缓存数据写入文件,只对写文件模式有效 */
PublicFuncZ R32 putStreamFlushZ( StreamZ srm );
#endif /* __CLASSSTREAM_Z_H_INCLUDED__ */
*********************************************************
/*
ClassStreamZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 StreamZ ,数据流类。封装对 文件 或 内存 的处理。
未使用位运算。
*/
#include "stdafx.h"
#include "ClassStreamZ.h"
#include <malloc.h>
#include <string.h>
/* 读写文件时,缓存大小 */
#define STREAM_BUFFER_SIZE_Z 1024
PublicFuncZ B32 isStreamValidZ( cStreamZ srm ) {
if ( NULL == srm ) {
return FALSE;
}
switch ( srm->mode ) {
case STREAM_MODE_FILE_IN_Z :
case STREAM_MODE_FILE_OUT_Z :
return ( (NULL != srm->file) && (NULL != srm->memory) &&
(STREAM_BUFFER_SIZE_Z == srm->memSize) &&
(srm->memPos <= srm->memEnd) && (srm->memEnd <= srm->memSize)
);
case STREAM_MODE_MEMORY_IN_Z :
case STREAM_MODE_MEMORY_OUT_Z :
return ( (NULL == srm->file) && (NULL != srm->memory) &&
(0 < srm->memSize) &&
(srm->memPos <= srm->memEnd) && (srm->memEnd <= srm->memSize)
);
}
return FALSE;
}
PublicFuncZ StreamZ createStreamFromFileZ( cSz08 fileName, U32 modeFile ) {
StreamZ srm = (StreamZ)malloc( sizeof(StreamInfoZ) );
if ( NULL == srm ) {
return NULL;
}
srm->file = NULL;
switch ( modeFile ) {
case STREAM_MODE_FILE_IN_Z :
srm->file = fopen( fileName, "rb" );
break;
case STREAM_MODE_FILE_OUT_Z :
srm->file = fopen( fileName, "wb" );
break;
}
if ( NULL == srm->file ) {
free( srm );
return NULL;
}
srm->mode = modeFile;
srm->memory = (U08*)malloc( STREAM_BUFFER_SIZE_Z );
if ( NULL == srm->memory ) {
fclose( srm->file );
free( srm );
return NULL;
}
srm->memSize = STREAM_BUFFER_SIZE_Z;
srm->memPos = 0;
srm->memEnd = 0;
return srm;
}
PublicFuncZ StreamZ createStreamFromMemoryZ( U08 *memory, U32 memSize, U32 modeMemory ) {
StreamZ srm;
if ( (NULL == memory) || (0 >= memSize) ||
((STREAM_MODE_MEMORY_IN_Z != modeMemory) && (STREAM_MODE_MEMORY_OUT_Z != modeMemory))
) {
return NULL;
}
srm = (StreamZ)malloc( sizeof(StreamInfoZ) );
if ( NULL == srm ) {
return NULL;
}
srm->mode = modeMemory;
srm->file = NULL;
srm->memory = memory;
srm->memSize = memSize;
srm->memPos = 0;
srm->memEnd = ((STREAM_MODE_MEMORY_IN_Z == srm->mode) ? memSize : 0 );
return srm;
}
PublicFuncZ R32 destroyStreamZ( StreamZ srm ) {
if ( !isStreamValidZ(srm) ) {
return RERR;
}
switch ( srm->mode ) {
case STREAM_MODE_FILE_OUT_Z :
putStreamFlushZ( srm );
case STREAM_MODE_FILE_IN_Z :
fclose( srm->file );
free( srm->memory );
break;
case STREAM_MODE_MEMORY_IN_Z :
case STREAM_MODE_MEMORY_OUT_Z :
break;
default :
return RERR;
}
free( srm );
return ROK;
}
/****************************************************************************************/
PublicFuncZ R32 getStreamU08Z( StreamZ srm, U08 *pU ) {
return getStreamU08ArrayZ( srm, pU, 1 );
}
PublicFuncZ R32 getStreamU08ArrayZ( StreamZ srm, U08 *arr, U32 len ) {
U32 i = 0, t;
if ( (!isStreamValidZ(srm)) || (NULL == arr) || (0 >= len) ||
((STREAM_MODE_FILE_IN_Z != srm->mode) && (STREAM_MODE_MEMORY_IN_Z != srm->mode))
) {
return RERR;
}
while ( i < len ) {
if ( srm->memPos >= srm->memEnd ) {
if ( STREAM_MODE_FILE_IN_Z != srm->mode ) {
return RERR;
}
srm->memEnd = fread( srm->memory, 1, srm->memSize, srm->file );
srm->memPos = 0;
if ( 0 >= srm->memEnd ) {
return RERR;
}
}
t = (((len - i) < (srm->memEnd - srm->memPos)) ? (len - i) : (srm->memEnd - srm->memPos));
memcpy( arr + i, srm->memory + srm->memPos, t );
i += t;
srm->memPos += t;
}
return ROK;
}
PublicFuncZ R32 getStreamU16LbfZ( StreamZ srm, U16 *pU ) {
if ( ROK != getStreamU08ArrayZ( srm, (U08*)pU, 2 ) ) {
return RERR;
}
*pU = (U16)( ((U16)0x100) * (((U08*)pU)[1]) + (((U08*)pU)[0]) );
return ROK;
}
PublicFuncZ R32 getStreamU16MbfZ( StreamZ srm, U16 *pU ) {
if ( ROK != getStreamU08ArrayZ( srm, (U08*)pU, 2 ) ) {
return RERR;
}
*pU = (U16)( ((U16)0x100) * (((U08*)pU)[0]) + (((U08*)pU)[1]) );
return ROK;
}
PublicFuncZ R32 getStreamU32LbfZ( StreamZ srm, U32 *pU ) {
if ( ROK != getStreamU08ArrayZ( srm, (U08*)pU, 4 ) ) {
return RERR;
}
*pU = (U32)( ((U32)0x1000000) * (((U08*)pU)[3]) +
((U32)0x10000 ) * (((U08*)pU)[2]) +
((U32)0x100 ) * (((U08*)pU)[1]) +
(((U08*)pU)[0]) );
return ROK;
}
PublicFuncZ R32 getStreamU32MbfZ( StreamZ srm, U32 *pU ) {
if ( ROK != getStreamU08ArrayZ( srm, (U08*)pU, 4 ) ) {
return RERR;
}
*pU = (U32)( ((U32)0x1000000) * (((U08*)pU)[0]) +
((U32)0x10000 ) * (((U08*)pU)[1]) +
((U32)0x100 ) * (((U08*)pU)[2]) +
(((U08*)pU)[3]) );
return ROK;
}
PublicFuncZ R32 getStreamI32LbfZ( StreamZ srm, I32 *pI ) {
return getStreamU32LbfZ( srm, (U32*)pI );
}
PublicFuncZ R32 getStreamI32MbfZ( StreamZ srm, I32 *pI ) {
return getStreamU32MbfZ( srm, (U32*)pI );
}
PublicFuncZ R32 getStreamSkipZ( StreamZ srm, U32 n ) {
if ( (!isStreamValidZ(srm)) || (0 >= n) ||
((STREAM_MODE_FILE_IN_Z != srm->mode) && (STREAM_MODE_MEMORY_IN_Z != srm->mode))
) {
return RERR;
}
if ( srm->memPos + n <= srm->memEnd ) {
srm->memPos += n;
return ROK;
}
n -= srm->memEnd - srm->memPos;
srm->memPos = 0;
srm->memEnd = 0;
if ( (STREAM_MODE_FILE_IN_Z != srm->mode) ||
(0 != fseek( srm->file, n, SEEK_CUR ))
) {
return RERR;
}
return ROK;
}
/****************************************************************************************/
PublicFuncZ R32 putStreamU08Z( StreamZ srm, U08 u ) {
return putStreamU08ArrayZ( srm, &u, 1 );
}
PublicFuncZ R32 putStreamU08ArrayZ( StreamZ srm, const U08 *arr, U32 len ) {
U32 i = 0, t;
if ( (!isStreamValidZ(srm)) || (NULL == arr) || (0 >= len) ||
((STREAM_MODE_FILE_OUT_Z != srm->mode) && (STREAM_MODE_MEMORY_OUT_Z != srm->mode))
) {
return RERR;
}
while ( i < len ) {
if ( srm->memPos >= srm->memSize ) {
if ( (STREAM_MODE_FILE_OUT_Z != srm->mode) ||
(fwrite( srm->memory, 1, srm->memSize, srm->file ) != srm->memSize)
){
return RERR;
}
srm->memPos = 0;
srm->memEnd = 0;
}
t = (((len - i) < (srm->memSize - srm->memPos)) ? (len - i) : (srm->memSize - srm->memPos));
memcpy( srm->memory + srm->memPos, arr + i, t );
i += t;
srm->memPos += t;
srm->memEnd = srm->memPos;
}
return ROK;
}
PublicFuncZ R32 putStreamU16LbfZ( StreamZ srm, U16 u ) {
U08 b[ 2 ];
b[ 0 ] = (U08)( u % 0x100 );
b[ 1 ] = (U08)( u / 0x100 );
return putStreamU08ArrayZ( srm, b, 2 );
}
PublicFuncZ R32 putStreamU16MbfZ( StreamZ srm, U16 u ) {
U08 b[ 2 ];
b[ 1 ] = (U08)( u % 0x100 );
b[ 0 ] = (U08)( u / 0x100 );
return putStreamU08ArrayZ( srm, b, 2 );
}
PublicFuncZ R32 putStreamU32LbfZ( StreamZ srm, U32 u ) {
U08 b[ 4 ];
b[ 0 ] = (U08)( u % 0x100 );
u /= 0x100;
b[ 1 ] = (U08)( u % 0x100 );
u /= 0x100;
b[ 2 ] = (U08)( u % 0x100 );
b[ 3 ] = (U08)( u / 0x100 );
return putStreamU08ArrayZ( srm, b, 4 );
}
PublicFuncZ R32 putStreamU32MbfZ( StreamZ srm, U32 u ) {
U08 b[ 4 ];
b[ 3 ] = (U08)( u % 0x100 );
u /= 0x100;
b[ 2 ] = (U08)( u % 0x100 );
u /= 0x100;
b[ 1 ] = (U08)( u % 0x100 );
b[ 0 ] = (U08)( u / 0x100 );
return putStreamU08ArrayZ( srm, b, 4 );
}
PublicFuncZ R32 putStreamI32LbfZ( StreamZ srm, I32 i ) {
return putStreamU32LbfZ( srm, (U32)i );
}
PublicFuncZ R32 putStreamI32MbfZ( StreamZ srm, I32 i ) {
return putStreamU32MbfZ( srm, (U32)i );
}
PublicFuncZ R32 putStreamFlushZ( StreamZ srm ) {
if ( (!isStreamValidZ(srm)) || (STREAM_MODE_FILE_OUT_Z != srm->mode) ) {
return RERR;
}
if ( srm->memPos > 0 ) {
if ( fwrite( srm->memory, 1, srm->memPos, srm->file ) != srm->memPos ) {
return RERR;
}
srm->memPos = 0;
srm->memEnd = 0;
}
return ROK;
}
*********************************************************
/*
DisplayWin32Z.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
Win32 平台下函数声明。
*/
#ifndef __DISPLAYWIN32_Z_H_INCLUDED__
#define __DISPLAYWIN32_Z_H_INCLUDED__
#include "TypeZ.h"
#include "ClassImageZ.h"
#include <Windows.h>
/* 无缩放将图像某区域显示在 DC 中指定位置 */
PublicFuncZ R32 displayImageZ( HDC hdcDest, I32 leftDest, I32 topDest,
U32 width, U32 height,
cImageZ imgSrc, U32 leftSrc, U32 topSrc );
#endif /* __DISPLAYWIN32_Z_H_INCLUDED__ */
*********************************************************
/*
DisplayWin32Z.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
平台相关但接口一致函数定义,Win32 平台下函数定义。
*/
#include "stdafx.h"
#include "DisplayZ.h"
#include <malloc.h>
#include <string.h>
/* 平台相关但接口一致函数定义 ============================= */
/* def */
/* Win32 平台下函数定义 =================================== */
PublicFuncZ R32 displayImageZ( HDC hdcDest, I32 leftDest, I32 topDest,
U32 width, U32 height,
cImageZ imgSrc, U32 leftSrc, U32 topSrc ) {
/* 将真彩色图像转化为 32 位位图,将调色板图像转化为 8 位位图,再显示。*/
/* 依赖 ImageZ 图像数据格式 与 windows 位图格式的匹配 */
BITMAPINFO *pinfo;
U32 imgWidth, imgHeight, linePitch;
B32 colorNum, hasPal;
if ( !isImageValidZ(imgSrc) ) {
return RERR;
}
imgWidth = getImageWidthZ( imgSrc );
linePitch = getImageLinePitchZ( imgSrc );
imgHeight = getImageHeightZ( imgSrc );
hasPal = isImagePaletteUsedZ( imgSrc );
colorNum = getImageColorNumZ( imgSrc );
if ( (width < 1) || (height < 1) ||
(leftSrc >= imgWidth) || (topSrc >= imgHeight)
) {
return ROK;
}
if ( leftSrc + width > imgWidth ) {
width = imgWidth - leftSrc;
}
if ( topSrc + height > imgHeight ) {
height = imgHeight - topSrc;
}
pinfo = (BITMAPINFO*)malloc( sizeof(BITMAPINFOHEADER) + colorNum * 4 + 16 );
if ( NULL == pinfo ) {
return RERR;
}
pinfo->bmiHeader.biBitCount = ( hasPal ? 8 : 32 );
pinfo->bmiHeader.biClrImportant = 0;
pinfo->bmiHeader.biClrUsed = ( hasPal ? colorNum : 0 );
pinfo->bmiHeader.biCompression = BI_RGB;
pinfo->bmiHeader.biHeight = 0 - imgHeight;
pinfo->bmiHeader.biPlanes = 1;
pinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pinfo->bmiHeader.biSizeImage = linePitch * imgHeight;
pinfo->bmiHeader.biWidth = imgWidth;
pinfo->bmiHeader.biXPelsPerMeter = 0;
pinfo->bmiHeader.biYPelsPerMeter = 0;
if ( hasPal ) {
memcpy( ((U08*)pinfo) + sizeof(BITMAPINFOHEADER), imgSrc->pPalette, IMAGEZ_COLOR_SIZE_Z * colorNum );
}
SetDIBitsToDevice( hdcDest, leftDest, topDest,
width, height,
leftSrc, topSrc,
0, imgHeight,
(void*)(imgSrc->pPixel),
pinfo,
DIB_RGB_COLORS );
free( pinfo );
return ROK;
}
*********************************************************
/*
DisplayZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
显示图像(依平台划分模块)(平台无关函数声明,平台相关但接口一致函数声明,包含平台相关文件)。
*/
#ifndef __DISPLAY_Z_H_INCLUDED__
#define __DISPLAY_Z_H_INCLUDED__
/* #include "" */
/* 平台无关函数声明 ==================================== */
/* decl */
/* 平台相关但接口一致函数声明 ========================== */
/* decl */
/* 包含平台相关文件 ==================================== */
#include "DisplayWin32Z.h"
#endif /* __DISPLAY_Z_H_INCLUDED__ */
*********************************************************
/*
FormatBmpZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
BMP 文件格式常量。
*/
#ifndef __FORMATBMP_Z_H_INCLUDED__
#define __FORMATBMP_Z_H_INCLUDED__
/* BMP 文件头大小 */
#define BMP_FILEHEADER_SIZE_Z 0x0E
/* BMP 文件压缩方案 */
/* 不压缩 */
#define BMP_CODE_RGB_Z 0
/* BMP 信息头大小 */
#define BMP_COREHEADER_SIZE_Z 0x0C
#define BMP_INFOHEADER_SIZE_Z 0x28
#define BMP_V4HEADER_SIZE_Z 0x6C
#define BMP_V5HEADER_SIZE_Z 0x7C
#endif /* __FORMATBMP_Z_H_INCLUDED__ */
*********************************************************
/*
FormatImageZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
图像数据格式(非图像文件格式) 及 相关工具。
*/
#ifndef __FORMATIMAGE_Z_H_INCLUDED__
#define __FORMATIMAGE_Z_H_INCLUDED__
#include "TypeZ.h"
/* 颜色格式(调色板图像的调色板数据,真彩色图像的像素数据) */
/* 32 位真彩色,内存低地址到高地址依次为 BlueGreenRedAlpha,各 8 位 */
#define FORMAT_COLOR_B8G8R8A8_Z 100
/* 24 位 */
#define FORMAT_COLOR_B8G8R8_Z 110
/* 调色板索引格式(调色板图像的像素数据) */
/* 8 位调色板,内存为 8 位调色板索引 */
#define FORMAT_INDEX_I8_Z 10
/* 4 位 */
#define FORMAT_INDEX_I4_Z 20
/* 1 位 */
#define FORMAT_INDEX_I1_Z 30
/* 判断格式是否合法 */
PublicFuncZ B32 isFormatValidZ( U32 colorNum, U32 fmtPalette, U32 fmtPixel );
/* 判断像素数据格式是否合法 */
PublicFuncZ B32 isPixelFormatValidZ( U32 fmtPixel );
/* 判断调色板数据格式是否合法 */
PublicFuncZ B32 isPaletteFormatValidZ( U32 fmtPalette );
/* 获取颜色大小,单位 字节,失败返回 0 */
PublicFuncZ U32 getFormatColorSizeZ( U32 fmtColor );
/* 转换颜色格式 */
PublicFuncZ R32 convertFormatColorZ( U32 fmtDest, U08 *pColorDest, U32 fmtSrc, U08 *pColorSrc );
/* 由像素宽度,计算 4 字节对齐后的字节宽度,失败返回 0 */
PublicFuncZ U32 getFormatLinePitchZ( U32 width, U32 fmtPixel );
#endif /* __FORMATIMAGE_Z_H_INCLUDED__ */
*********************************************************
/*
FormatImageZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
图像数据格式(非图像文件格式) 及 相关工具。
*/
#include "stdafx.h"
#include "FormatImageZ.h"
PublicFuncZ B32 isFormatValidZ( U32 colorNum, U32 fmtPalette, U32 fmtPixel ) {
switch ( fmtPixel ) {
case FORMAT_COLOR_B8G8R8A8_Z :
case FORMAT_COLOR_B8G8R8_Z :
return (0x0 == colorNum);
case FORMAT_INDEX_I8_Z :
return ( (0x2 <= colorNum) && (0x100 >= colorNum) && (isPaletteFormatValidZ(fmtPalette)) );
case FORMAT_INDEX_I4_Z :
return ( (0x2 <= colorNum) && (0x10 >= colorNum) && (isPaletteFormatValidZ(fmtPalette)) );
case FORMAT_INDEX_I1_Z :
return ( (0x2 == colorNum) && (isPaletteFormatValidZ(fmtPalette)) );
}
return FALSE;
}
PublicFuncZ B32 isPixelFormatValidZ( U32 fmtPixel ) {
switch ( fmtPixel ) {
case FORMAT_COLOR_B8G8R8A8_Z :
case FORMAT_COLOR_B8G8R8_Z :
case FORMAT_INDEX_I8_Z :
case FORMAT_INDEX_I4_Z :
case FORMAT_INDEX_I1_Z :
return TRUE;
}
return FALSE;
}
PublicFuncZ B32 isPaletteFormatValidZ( U32 fmtPalette ) {
switch ( fmtPalette ) {
case FORMAT_COLOR_B8G8R8A8_Z :
case FORMAT_COLOR_B8G8R8_Z :
return TRUE;
}
return FALSE;
}
PublicFuncZ U32 getFormatColorSizeZ( U32 fmtColor ) {
switch ( fmtColor ) {
case FORMAT_COLOR_B8G8R8A8_Z :
return 4;
case FORMAT_COLOR_B8G8R8_Z :
return 3;
}
return 0;
}
PublicFuncZ R32 convertFormatColorZ( U32 fmtDest, U08 *pColorDest, U32 fmtSrc, U08 *pColorSrc ) {
U08 color[ 8 ];
switch ( fmtSrc ) {
case FORMAT_COLOR_B8G8R8A8_Z :
color[ 0 ] = pColorSrc[ 0 ];
color[ 1 ] = pColorSrc[ 1 ];
color[ 2 ] = pColorSrc[ 2 ];
color[ 3 ] = pColorSrc[ 3 ];
break;
case FORMAT_COLOR_B8G8R8_Z :
color[ 0 ] = pColorSrc[ 0 ];
color[ 1 ] = pColorSrc[ 1 ];
color[ 2 ] = pColorSrc[ 2 ];
color[ 3 ] = 0;
break;
default :
return RERR;
}
switch ( fmtSrc ) {
case FORMAT_COLOR_B8G8R8A8_Z :
pColorDest[ 0 ] = color[ 0 ];
pColorDest[ 1 ] = color[ 1 ];
pColorDest[ 2 ] = color[ 2 ];
pColorDest[ 3 ] = color[ 3 ];
break;
case FORMAT_COLOR_B8G8R8_Z :
pColorDest[ 0 ] = color[ 0 ];
pColorDest[ 1 ] = color[ 1 ];
pColorDest[ 2 ] = color[ 2 ];
break;
default :
return RERR;
}
return ROK;
}
PublicFuncZ U32 getFormatLinePitchZ( U32 width, U32 fmtPixel ) {
U32 bpp = 0;
switch ( fmtPixel ) {
case FORMAT_COLOR_B8G8R8A8_Z :
bpp = 32;
break;
case FORMAT_COLOR_B8G8R8_Z :
bpp = 24;
break;
case FORMAT_INDEX_I8_Z :
bpp = 8;
break;
case FORMAT_INDEX_I4_Z :
bpp = 4;
break;
case FORMAT_INDEX_I1_Z :
bpp = 1;
break;
default :
return 0;
}
return ( ( ( ( ( width * bpp ) + 7 ) / 8 ) + 3 ) / 4 ) * 4;
}
*********************************************************
/*
FormatZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
图像格式。
*/
#ifndef __FORMAT_Z_H_INCLUDED__
#define __FORMAT_Z_H_INCLUDED__
/* ImageZ */
#include "FormatImageZ.h"
/* BMP */
#define FORMAT_BMP_CORE_Z 10
#define FORMAT_BMP_INFO_Z 20
#define FORMAT_BMP_V4_Z 30
#define FORMAT_BMP_V5_Z 40
#include "FormatBmpZ.h"
#define FORMAT_BMP_Z FORMAT_BMP_INFO_Z
#endif /* __FORMAT_Z_H_INCLUDED__ */
*********************************************************
/*
ImageZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
图形库 ImageZ 的总头文件,使用图形库(直接使用源码 或 使用动态链接库等)时包含此头文件即可。
*/
#ifndef __IMAGE_Z_H_INCLUDED__
#define __IMAGE_Z_H_INCLUDED__
#include "TypeZ.h"
#include "TypeFileInfoZ.h"
#include "ClassImageZ.h"
#include "ClassStreamZ.h"
#include "FormatZ.h"
#include "InputZ.h"
#include "DisplayZ.h"
#include "OutputZ.h"
#endif /* __IMAGE_Z_H_INCLUDED__ */
*********************************************************
/*
InputZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
读入图像。
*/
#ifndef __INPUT_Z_H_INCLUDED__
#define __INPUT_Z_H_INCLUDED__
#include "TypeZ.h"
#include "ClassImageZ.h"
#include "ClassStreamZ.h"
PublicFuncZ ImageZ createImageFromStreamBmpZ( StreamZ srm );
PublicFuncZ ImageZ createImageFromFileBmpZ( cSz08 fileName );
#endif /* __INPUT_Z_H_INCLUDED__ */
*********************************************************
/*
InputZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
读入图像。
*/
#include "stdafx.h"
#include "InputZ.h"
#include "FormatBmpZ.h"
#include "FormatImageZ.h"
#include <malloc.h>
/* 目前支持无压缩的 1 位,4 位,8 位,24 位,32 位 的位图 */
/* 认为 32 位位图不使用 Alpha */
PublicFuncZ ImageZ createImageFromStreamBmpZ( StreamZ srm ) {
ImageZ img = NULL; /* 图像 */
U08 bfType0, bfType1; /* BMP 文件类型标识 */
U32 bfOffBits; /* 像素数据在文件中的偏移 */
/* FORMAT_BMP_INFO_Z, FORMAT_BMP_V4_Z, FORMAT_BMP_V5_Z 统一处理 */
U32 hdrSize; /* 图像信息头大小,识别不同版本 BMP 文件 */
U32 bpp, code; /* 每像素数据位数,压缩方案 */
U32 width, height; /* 图像宽高,单位 像素 */
U32 linePitch; /* 4 字节对齐后的欲读文件中图像宽度,单位 字节 */
U32 imgLinePitch; /* 4 字节对齐后的 ImageZ 图像宽度,单位字节 */
/* 过滤与图像数据无关的调色板 */
U32 hdrColor; /* 真彩色图像的调色板颜色数 */
/* 不同格式调色板统一处理 */
U32 colorNum; /* 调色板颜色数量 */
U32 palColorSize; /* 调色板中每个颜色大小,单位 字节 */
U32 i; /* 读入调色板,像素数据 循环变量 */
U32 x, y; /* 读入像素数据 循环变量 */
U08 *p; /* 读入调色板,像素数据 临时变量 */
/* 读入调色板数据,一行图像数据 缓存 */
U32 bufLen; /* 缓存 大小 */
U08 *buf = NULL;
/* 24 位,32 位 未压缩图像 统一处理 */
U32 pixelSize; /* 像素大小,单位 字节 */
/* 8 位,4 位,1 位 未压缩图像 统一处理 */
U32 indexMod; /* 从字节中分离出调色板索引 */
U32 pixelPerByte; /* 每字节像素数量 */
/* 自顶向下,自底向上 统一处理 */
B32 topDown; /* 是否自顶向下 */
I32 step; /* 读入像素时的行增量,单位 字节 */
U08 *pPixel; /* 读入像素时,每行的起始 */
/* 2 的 n 次方,不使用位运算 */
U32 n2n[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 };
#define EXIT_ERR do { destroyImageZ( img ); free( buf ); return NULL; } while ( 0 )
if ( !isStreamValidZ(srm) ) {
return NULL;
}
if ( (ROK != getStreamU08Z( srm, &bfType0 )) ||
(ROK != getStreamU08Z( srm, &bfType1 )) ||
('B' != bfType0) || ('M' != bfType1) ||
(ROK != getStreamSkipZ( srm, 8 )) ||
(ROK != getStreamU32LbfZ( srm, &bfOffBits )) ||
(ROK != getStreamU32LbfZ( srm, &hdrSize ))
) EXIT_ERR;
switch ( hdrSize ) {
case BMP_V5HEADER_SIZE_Z :
/* FORMAT_BMP_INFO_Z, FORMAT_BMP_V4_Z, FORMAT_BMP_V5_Z 统一处理 */
case BMP_V4HEADER_SIZE_Z :
/* FORMAT_BMP_INFO_Z, FORMAT_BMP_V4_Z, FORMAT_BMP_V5_Z 统一处理 */
case BMP_INFOHEADER_SIZE_Z :
/* FORMAT_BMP_INFO_Z, FORMAT_BMP_V4_Z, FORMAT_BMP_V5_Z 统一处理 */
/* FORMAT_BMP_INFO_Z */
{
I32 biWidth, biHeight;
U16 biBitCount;
U32 biCompression, biClrUsed;
if ( (ROK != getStreamI32LbfZ( srm, &biWidth )) ||
(ROK != getStreamI32LbfZ( srm, &biHeight )) ||
(biWidth < 1) || (biHeight == 0) ||
(ROK != getStreamSkipZ( srm, 2 )) ||
(ROK != getStreamU16LbfZ( srm, &biBitCount )) ||
(ROK != getStreamU32LbfZ( srm, &biCompression )) ||
(ROK != getStreamSkipZ( srm, 12 )) ||
(ROK != getStreamU32LbfZ( srm, &biClrUsed )) ||
(ROK != getStreamSkipZ( srm, 4 + hdrSize - BMP_INFOHEADER_SIZE_Z ))
) EXIT_ERR;
bpp = biBitCount;
code = biCompression;
topDown = ( biHeight < 0 );
width = biWidth;
height = ( topDown ? (-biHeight) : biHeight );
colorNum = ( (bpp > 8) ? 0 : ( (biClrUsed == 0) ? n2n[bpp] : biClrUsed ) );
palColorSize = 4;
hdrColor = biClrUsed;
if (!( ( ( (bpp == 1) || (bpp == 4) ||
(bpp == 8) || (bpp == 24) ||
(bpp == 32)
) &&
(code == BMP_CODE_RGB_Z)
) /* ||
( (bpp == 16) && (code == )
) */
)
) EXIT_ERR;
} /* FORMAT_BMP_INFO_Z */
break;
case BMP_COREHEADER_SIZE_Z :
/* FORMAT_BMP_CORE_Z */
{
U16 bcWidth, bcHeight, bcBitCount;
if ( (ROK != getStreamU16LbfZ( srm, &bcWidth )) ||
(ROK != getStreamU16LbfZ( srm, &bcHeight )) ||
(bcWidth < 1) || (bcHeight < 1) ||
(ROK != getStreamSkipZ( srm, 2 )) ||
(ROK != getStreamU16LbfZ( srm, &bcBitCount ))
) EXIT_ERR;
bpp = bcBitCount;
code = BMP_CODE_RGB_Z;
topDown = FALSE;
width = bcWidth;
height = bcHeight;
colorNum = ( (bpp > 8) ? 0 : n2n[bpp] );
palColorSize = 3;
hdrColor = 0;
if (!( (bpp == 1) || (bpp == 4) ||
(bpp == 8) || (bpp == 24)
)
) EXIT_ERR;
} /* FORMAT_BMP_CORE_Z */
break;
default :
EXIT_ERR;
}
/* 真彩色图像使用调色板优化基于调色板的显示设备的显示效果,这里忽略之 */
if ( (0 == colorNum) && (0 < hdrColor) ) {
if ( ROK != getStreamSkipZ( srm, hdrColor * palColorSize ) )
EXIT_ERR;
}
img = createImageZ( width, height, colorNum );
if ( !isImageValidZ(img) )
EXIT_ERR;
pixelPerByte = 8 / bpp;
pixelSize = bpp / 8;
indexMod = ( (bpp <= 8) ? n2n[bpp] : 0 );
linePitch = ( ( ( width * bpp + 7 ) / 8 + 3 ) / 4 ) * 4;
imgLinePitch = img->linePitch;
step = ( topDown ? imgLinePitch : (0-imgLinePitch) );
pPixel = img->pPixel + ( topDown ? 0 : (height * imgLinePitch - imgLinePitch) );
bufLen = 16 + ( (colorNum * palColorSize < linePitch) ? linePitch : (colorNum * palColorSize) );
buf = (U08*)malloc( bufLen );
if ( NULL == buf )
EXIT_ERR;
/* 不同格式调色板 统一处理 */
if ( 0 < colorNum ) {
if ( ROK != getStreamU08ArrayZ( srm, buf, colorNum * palColorSize ) )
EXIT_ERR;
for ( i = 0; i < colorNum; ++i ) {
p = img->pPalette + i * IMAGEZ_COLOR_SIZE_Z;
p[ IMAGEZ_OFFSET_BLUE_Z ] = buf[ i * palColorSize + 0 ];
p[ IMAGEZ_OFFSET_GREEN_Z ] = buf[ i * palColorSize + 1 ];
p[ IMAGEZ_OFFSET_RED_Z ] = buf[ i * palColorSize + 2 ];
p[ IMAGEZ_OFFSET_ALPHA_Z ] = 255;
}
}
switch ( bpp ) {
case 32 :
/* 未压缩的 32 位位图,未压缩的 24 位位图 统一处理 */
case 24 :
/* 未压缩的 32 位位图,未压缩的 24 位位图 统一处理 */
if ( code == BMP_CODE_RGB_Z ) {
for ( y = 0; y < height; ++y ) {
if ( ROK != getStreamU08ArrayZ( srm, buf, linePitch ) ) {
EXIT_ERR;
}
for ( x = 0; x < width; ++x ) {
p = pPixel + x * IMAGEZ_COLOR_SIZE_Z;
p[ IMAGEZ_OFFSET_BLUE_Z ] = buf[ x * pixelSize + 0 ];
p[ IMAGEZ_OFFSET_GREEN_Z ] = buf[ x * pixelSize + 1 ];
p[ IMAGEZ_OFFSET_RED_Z ] = buf[ x * pixelSize + 2 ];
p[ IMAGEZ_OFFSET_ALPHA_Z ] = 255;
}
pPixel += step;
}
}
else {
EXIT_ERR;
}
break;
case 16 :
EXIT_ERR;
break;
case 8 :
/* 未压缩的 8 位位图,未压缩的 4 位位图,未压缩的 1 位位图 统一处理 */
case 4 :
/* 未压缩的 8 位位图,未压缩的 4 位位图,未压缩的 1 位位图 统一处理 */
case 1 :
/* 未压缩的 8 位位图,未压缩的 4 位位图,未压缩的 1 位位图 统一处理 */
if ( code == BMP_CODE_RGB_Z ) {
for ( y = 0; y < height; ++y ) {
if ( ROK != getStreamU08ArrayZ( srm, buf, linePitch ) )
EXIT_ERR;
i = 0;
for ( x = 0; x < width; ++x ) {
p = pPixel + x * IMAGEZ_INDEX_SIZE_Z;
*p = ( buf[x/pixelPerByte] / n2n[8-bpp-i*bpp] ) % indexMod;
if ( (*p) >= colorNum )
EXIT_ERR;
++i;
if ( i >= pixelPerByte ) {
i = 0;
}
}
pPixel += step;
}
}
else {
EXIT_ERR;
}
break;
default :
EXIT_ERR;
}
free( buf );
return img;
#undef EXIT_ERR
}
PublicFuncZ ImageZ createImageFromFileBmpZ( cSz08 fileName ) {
ImageZ img;
StreamZ srm = createStreamFromFileZ( fileName, STREAM_MODE_FILE_IN_Z );
if ( !isStreamValidZ(srm) ) {
return NULL;
}
img = createImageFromStreamBmpZ( srm );
destroyStreamZ( srm );
if ( !isImageValidZ(img) ) {
return NULL;
}
return img;
}
*********************************************************
/*
OutputZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
保存图像。
*/
#ifndef __OUTPUT_Z_H_INCLUDED__
#define __OUTPUT_Z_H_INCLUDED__
#include "TypeZ.h"
#include "TypeFileInfoZ.h"
#include "ClassImageZ.h"
#include "ClassStreamZ.h"
PublicFuncZ R32 saveImageToStreamZ( cImageZ img, StreamZ srm, cPtrFileInfoZ pfi );
PublicFuncZ R32 saveImageToFileZ( cImageZ img, cSz08 fileName, cPtrFileInfoZ pfi );
/* 计算图像保存后的文件大小,单位 字节;失败返回 0 */
PublicFuncZ U32 getImageFileSizeZ( cImageZ img, cPtrFileInfoZ pfi );
#endif /* __OUTPUT_Z_H_INCLUDED__ */
*********************************************************
/*
OutputZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
保存图像。
*/
#include "stdafx.h"
#include "OutputZ.h"
#include "FormatZ.h"
PrivateFuncZ R32 saveImageToStreamBmpZ( cImageZ img, StreamZ srm, cPtrFileInfoZ pfi );
PublicFuncZ R32 saveImageToStreamZ( cImageZ img, StreamZ srm, cPtrFileInfoZ pfi ) {
if ( !isFileInfoValidZ(pfi) ) {
return RERR;
}
switch ( pfi->fmt ) {
case FORMAT_BMP_Z :
return saveImageToStreamBmpZ( img, srm, pfi );
}
return RERR;
}
PublicFuncZ R32 saveImageToFileZ( cImageZ img, cSz08 fileName, cPtrFileInfoZ pfi ) {
R32 res;
StreamZ srm = createStreamFromFileZ( fileName, STREAM_MODE_FILE_OUT_Z );
if ( NULL == srm ) {
return RERR;
}
res = saveImageToStreamZ( img, srm, pfi );
destroyStreamZ( srm );
return res;
}
PublicFuncZ U32 getImageFileSizeZ( cImageZ img, cPtrFileInfoZ pfi ) {
if ( (!isImageValidZ(img)) || (!isFileInfoValidZ(pfi)) ) {
return 0;
}
switch ( pfi->fmt ) {
case FORMAT_BMP_Z :
return getImageLinePitchZ(img) * getImageHeightZ(img) +
getImageColorNumZ(img) * IMAGEZ_COLOR_SIZE_Z +
BMP_FILEHEADER_SIZE_Z + BMP_INFOHEADER_SIZE_Z;
}
return 0;
}
PrivateFuncZ R32 saveImageToStreamBmpZ( cImageZ img, StreamZ srm, cPtrFileInfoZ pfi ) {
U32 width; /* 图像宽,单位 像素 */
I32 iwidth; /* 图像宽,考虑方向,单位 像素 */
U32 linePitch; /* 图像宽,对齐后,单位 字节 */
U32 height; /* 图像高,单位 像素 */
I32 iheight; /* 图像高,考虑方向,单位 像素 */
U32 colorNum; /* 调色板颜色数 */
U32 offbits; /* 图像像素数据在文件中的偏移,单位 字节 */
U32 imgSize; /* 图像像素数据量,单位 字节 */
U32 fileSize; /* 文件大小,单位 字节 */
if ( (!isImageValidZ(img)) || (!isStreamValidZ(srm)) ||
(!isFileInfoValidZ(pfi)) || (FORMAT_BMP_Z != pfi->fmt)
) {
return RERR;
}
width = getImageWidthZ( img );
iwidth = width;
linePitch = getImageLinePitchZ( img );
height = getImageHeightZ( img );
iheight = 0 - height;
colorNum = getImageColorNumZ(img);
offbits = colorNum * IMAGEZ_COLOR_SIZE_Z + BMP_FILEHEADER_SIZE_Z + BMP_INFOHEADER_SIZE_Z;
imgSize = linePitch * height;
fileSize = offbits + imgSize;
/* FILEHEADER */
if ( (ROK != putStreamU08Z(srm, (U08)('B'))) ||
(ROK != putStreamU08Z(srm, (U08)('M'))) ||
(ROK != putStreamU32LbfZ(srm, fileSize)) ||
(ROK != putStreamU32LbfZ(srm, 0)) ||
(ROK != putStreamU32LbfZ(srm, offbits))
) {
return RERR;
}
/* INFOHEADER */
if ( (ROK != putStreamU32LbfZ(srm, BMP_INFOHEADER_SIZE_Z)) ||
(ROK != putStreamI32LbfZ(srm, iwidth)) ||
(ROK != putStreamI32LbfZ(srm, iheight)) ||
(ROK != putStreamU16LbfZ(srm, 1)) ||
(ROK != putStreamU16LbfZ(srm, ((0==colorNum)?32:8))) ||
(ROK != putStreamU32LbfZ(srm, BMP_CODE_RGB_Z)) ||
(ROK != putStreamU32LbfZ(srm, imgSize)) ||
(ROK != putStreamI32LbfZ(srm, 0)) ||
(ROK != putStreamI32LbfZ(srm, 0)) ||
(ROK != putStreamU32LbfZ(srm, colorNum)) ||
(ROK != putStreamU32LbfZ(srm, 0))
) {
return RERR;
}
/* PALETTE */
if ( 0 < colorNum ) {
if ( ROK != putStreamU08ArrayZ(srm, img->pPalette, colorNum*IMAGEZ_COLOR_SIZE_Z) ) {
return RERR;
}
}
/* PIXEL */
if ( ROK != putStreamU08ArrayZ(srm, img->pPixel, imgSize) ) {
return RERR;
}
return ROK;
}
*********************************************************
/*
TypeFileInfoZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 FileInfoZ ,图像文件信息(如 图像格式,jpeg属性,BMP 位深度 等)。
*/
#ifndef __TYPEFILEINFO_Z_H_INCLUDED__
#define __TYPEFILEINFO_Z_H_INCLUDED__
#include "TypeZ.h"
struct _FileInfoZ
{
U32 fmt; /* 文件格式,FORMAT_BMP_Z ... */
struct /* BMP 文件 */
{
U32 subfmt; /* 子格式,FORMAT_BMP_INFO_Z, FORMAT_BMP_CORE_Z ... */
U32 bpp; /* 每像素位数,1,4,8,16,24,32 */
U32 code; /* 编码方案 */
} bmp;
};
typedef struct _FileInfoZ FileInfoZ;
typedef FileInfoZ *PtrFileInfoZ;
typedef const FileInfoZ *cPtrFileInfoZ;
PublicFuncZ B32 isFileInfoValidZ( cPtrFileInfoZ pfi );
#endif /* __TYPEFILEINFO_Z_H_INCLUDED__ */
*********************************************************
/*
TypeFileInfoZ.c
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义 FileInfoZ ,图像文件信息(如 图像格式,jpeg属性,BMP 位深度 等)。
*/
#include "stdafx.h"
#include "TypeFileInfoZ.h"
#include "FormatZ.h"
PublicFuncZ B32 isFileInfoValidZ( cPtrFileInfoZ pfi ) {
if ( NULL == pfi ) {
return FALSE;
}
switch ( pfi->fmt ) {
case FORMAT_BMP_Z :
return ( (BMP_CODE_RGB_Z == pfi->bmp.code) &&
( (FORMAT_BMP_INFO_Z == pfi->bmp.subfmt) ||
(FORMAT_BMP_CORE_Z == pfi->bmp.subfmt) ||
(FORMAT_BMP_V4_Z == pfi->bmp.subfmt) ||
(FORMAT_BMP_V5_Z == pfi->bmp.subfmt)
) &&
( (32==pfi->bmp.bpp) || (24==pfi->bmp.bpp) ||
/* (16==pfi->bmp.bpp) || */
(8==pfi->bmp.bpp)||(4==pfi->bmp.bpp)||(1==pfi->bmp.bpp)
)
);
}
return FALSE;
}
*********************************************************
/*
TypeZ.h
Copyright (C) 2011, coreBugZJ, all rights reserved.
定义无需构造析构的数据类型及部分常量,宏。
*/
#ifndef __TYPE_Z_H_INCLUDED__
#define __TYPE_Z_H_INCLUDED__
/* 带符号整数 */
typedef char I08;
typedef short I16;
typedef int I32;
/* 无符号整数 */
typedef unsigned char U08;
typedef unsigned short U16;
typedef unsigned int U32;
/* 函数返回状态类型和常量 */
typedef U32 R32;
#define ROK 10
#define RERR 20
/* 布尔类型和常量 */
typedef U32 B32;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* ANSI 字符和字符串 */
typedef char C08;
typedef C08* Sz08;
typedef const C08 * cSz08;
/* NULL */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif
#endif
/* 颜色 */
struct _ColorZ
{
U08 b, g, r, a;
};
typedef struct _ColorZ ColorZ;
/* 像素 */
union _PixelZ
{
ColorZ color;
U08 index;
};
typedef union _PixelZ PixelZ;
/* 函数 */
#define PrivateFuncZ static
#define PublicFuncZ
#endif /* __TYPE_Z_H_INCLUDED__ */
*********************************************************
// ImageADoc.cpp : implementation of the CImageADoc class
//
#include "stdafx.h"
#include "ImageA.h"
#include "ImageADoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CImageADoc
IMPLEMENT_DYNCREATE(CImageADoc, CDocument)
BEGIN_MESSAGE_MAP(CImageADoc, CDocument)
END_MESSAGE_MAP()
// CImageADoc construction/destruction
CImageADoc::CImageADoc()
{
// TODO: add one-time construction code here
/* coreBugZJ */
this->image = NULL;
}
CImageADoc::~CImageADoc()
{
}
BOOL CImageADoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// CImageADoc serialization
void CImageADoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
/* coreBugZJ */
FileInfoZ fi;
U32 len;
U08 *buffer;
StreamZ srm;
fi.fmt = FORMAT_BMP_Z;
fi.bmp.subfmt = FORMAT_BMP_INFO_Z;
fi.bmp.code = BMP_CODE_RGB_Z;
fi.bmp.bpp = 32;
len = getImageFileSizeZ( this->image, &fi );
buffer = (U08*)malloc( len );
if ( NULL != buffer ) {
srm = createStreamFromMemoryZ( buffer, len, STREAM_MODE_MEMORY_OUT_Z );
if ( NULL != srm ) {
if ( ROK != saveImageToStreamZ( this->image, srm, &fi ) ) {
::AfxMessageBox( TEXT("save Failed") );
}
else {
ar.Write( buffer, len );
}
destroyStreamZ( srm );
}
free( buffer );
}
}
else
{
/* coreBugZJ */
destroyImageZ( this->image );
this->image = NULL;
U32 len = (U32)(ar.GetFile()->GetLength());
U08 *buffer = (U08*)malloc( len );
if ( NULL != buffer ) {
if ( ar.Read( buffer, len ) == len ) {
StreamZ srm = createStreamFromMemoryZ( buffer, len, STREAM_MODE_MEMORY_IN_Z );
if ( NULL != srm ) {
this->image = createImageFromStreamBmpZ( srm );
destroyStreamZ(srm );
}
}
free( buffer );
}
}
}
// CImageADoc diagnostics
#ifdef _DEBUG
void CImageADoc::AssertValid() const
{
CDocument::AssertValid();
}
void CImageADoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CImageADoc commands
*********************************************************
void CImageAView::OnDraw(CDC* pDC)
{
CImageADoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
/* coreBugZJ */
displayImageZ( pDC->GetSafeHdc(), 0, 0,
getImageWidthZ(pDoc->image), getImageHeightZ(pDoc->image),
pDoc->image, 0, 0 );
}
*********************************************************