coreBugZJ

此 blog 已弃。

数字图像处理上机之一:BMP图像文件读写和图像显示

 

实验目的:
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 );
}

*********************************************************

 

posted on 2011-09-22 22:00 coreBugZJ 阅读(5315) 评论(3)  编辑 收藏 引用 所属分类: VideoImage课内作业

Feedback

# re: 数字图像处理上机之一:BMP图像文件读写和图像显示 2011-09-23 19:35 cheap lace front wigs

好高深哦,学习了。。  回复  更多评论   

# re: 数字图像处理上机之一:BMP图像文件读写和图像显示[未登录] 2014-12-11 19:39 Jack

@cheap lace front wigs

能不能给发分源代码啊? 多谢大神!  回复  更多评论   

# re: 数字图像处理上机之一:BMP图像文件读写和图像显示 2014-12-12 09:29 coreBugZJ

@Jack
几年前学习图像处理的时候试图写一个库的,但没设计好,且许多算法实现起来工作量太大且效果不如已有的库好,所以现在做图像处理还是使用的第三方库。这些代码我自己觉得写得不好,你想要读写BMP的话,可以参考MSDN的资料、 CxImage、OpenCV等的读写BMP的代码(我当时是这么做的)。现在许多VC++图像处理的书也都附有BMP读写代码的,或者找找hdibapi.h/.c,cdib.h/.c之类的文件。  回复  更多评论   



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理