www.pudn.com > isee_code01231.zip > BmpModule.cpp
/********************************************************************
BmpModule.cpp - ISee图像浏览器—BMP图像读写模块实现文件
版权所有(C) 2000 VCHelp-coPathway-ISee workgroup member
这一程序是自由软件,你可以遵照自由软件基金会出版的GNU 通用公共许
可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根
据你的选择)用任何更新的版本。
发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定
目地的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果还没有,
写信给:
The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
MA02139, USA
如果你在使用本软件时有什么问题或建议,用以下地址可以与我们取得联
系:
http://isee.126.com
http://www.vchelp.net
或:
iseesoft@china.com
编写人:YZ
E-Mail:yzfree@sina.com
文件版本:
Beta 1.5
Build 01209
Date 2000-12-9
********************************************************************/
#include "stdafx.h"
#include "..\public\gol_isee.h" // 此文件定义了接口数据包
#include "BmpModule.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static char ModuleProcessImgType[]="BMP,DIB,RLE"; // 本模块能处理的图像类型
static char WriterList[]="YZ"; // 本模块的作者列表
static char WriterMess[]="没想到做好BMP模块还真挺复杂^_^"; // 作者留言
static int RWPROGRESSSIZE;
static const int RWPROGRESSSTEP = 10;
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
// 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
// ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
// 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
//
//
/////////////////////////////////////////////////////////////////////////////
// CBmpModuleApp
BEGIN_MESSAGE_MAP(CBmpModuleApp, CWinApp)
//{{AFX_MSG_MAP(CBmpModuleApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBmpModuleApp construction
CBmpModuleApp::CBmpModuleApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CBmpModuleApp object
CBmpModuleApp theApp;
// 接口函数声明 — 第一层,唯一与外界联系的接口
int WINAPI AccessBMPModule(INFOSTR *pInfo)
{
// 这个函数可以不作修改的使用,除非你的返回值多于两种。
switch(pInfo->comm)
{
case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
_fnCMD_GETPROCTYPE(pInfo);
break;
case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
_fnCMD_GETWRITERS(pInfo);
break;
case CMD_GETWRITERMESS: // 获取作者们的留言
_fnCMD_GETWRITERMESS(pInfo);
break;
case CMD_GETBUILDID: // 获取图像模块内部版本号
_fnCMD_GETBUILDID(pInfo);
break;
case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的BMP文件
_fnCMD_IS_VALID_FILE(pInfo);
break;
case CMD_GET_FILE_INFO: // 获取指定文件的信息
_fnCMD_GET_FILE_INFO(pInfo);
break;
case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
_fnCMD_LOAD_FROM_FILE(pInfo);
break;
case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
_fnCMD_SAVE_TO_FILE(pInfo);
break;
case CMD_IS_SUPPORT: // 查询某个命令是否被支持
_fnCMD_IS_SUPPORT(pInfo);
break;
case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
_fnCMD_RESIZE(pInfo);
break;
default:
pInfo->result = ER_ILLCOMM; // 非法命令
ASSERT(FALSE); // 调用者的程序设计有问题 :-)
break;
}
// 执行命令成功返回1, 失败返回0
return (pInfo->result==ER_SUCCESS)? 1:0;
}
// 命令解释函数 — 第二层解释函数
//********************************************************************//
// 操作命令解释函数---解释:CMD_IS_SUPPORT命令
// 查询某个命令是否被支持
void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
{
// 这个函数是为客户程序查询时使用,如果你实现了对某个命令的
// 解释,可修改相应的case中的设置,使其返回ER_SUCCESS,这就
// 表示你的模块已经支持该命令了。同时,现在的这个文件中已包
// 含了对前四个命令的解释,你只需向还未支持的命令函数中添加
// 代码即可。
ASSERT(pInfo->result == ER_EMPTY);
switch(pInfo->annexdata.cmAnnData)
{
case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
pInfo->result = ER_SUCCESS;
break;
case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
pInfo->result = ER_SUCCESS;
break;
case CMD_GETWRITERMESS: // 获取作者们的留言
pInfo->result = ER_SUCCESS;
break;
case CMD_GETBUILDID: // 获取图像模块内部版本号
pInfo->result = ER_SUCCESS;
break;
case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
pInfo->result = ER_SUCCESS;
break;
case CMD_GET_FILE_INFO: // 获取指定文件的信息
pInfo->result = ER_SUCCESS;
break;
case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
pInfo->result = ER_SUCCESS;
break;
case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
pInfo->result = ER_SUCCESS;
break;
case CMD_IS_SUPPORT: // 查询某个命令是否被支持
pInfo->result = ER_SUCCESS;
break;
case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
pInfo->result = ER_NOTSUPPORT;
break;
default:
pInfo->result = ER_NOTSUPPORT;
break;
}
}
// 操作命令解释函数---解释:CMD_GETPROCTYPE命令
// 获取本模块能处理的图像类型,如:BMP,PCX等等
void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
{
// 这是预定义的函数代码,你可以不必修改的使用。
// 根据接口定义,此时附加数据应被清空为0,所以下此断言
ASSERT(pInfo->annexdata.scAnnData[0] == 0);
ASSERT(pInfo->result == ER_EMPTY);
// 复制能处理的类型字符串
::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType,
sizeof(ModuleProcessImgType));
pInfo->result = ER_SUCCESS;
}
// 操作命令解释函数---解释:CMD_GETWRITER命令
// 获取本模块的作者列表,多人时用逗号分隔
void _fnCMD_GETWRITERS(INFOSTR *pInfo)
{
// 这是预定义的函数代码,你可以不必修改的使用。
// 根据接口定义,此时附加数据应被清空为0,所以下此断言
ASSERT(pInfo->annexdata.scAnnData[0] == 0);
ASSERT(pInfo->result == ER_EMPTY);
// 复制开发者名单串
::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList,
sizeof(WriterList));
pInfo->result = ER_SUCCESS;
}
// 操作命令解释函数---解释:CMD_GETWRITERMESS命令
// 获取作者们的留言
void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
{
// 这是预定义的函数代码,你可以不必修改的使用。
// 根据接口定义,此时附加数据应被清空为0,所以下此断言
ASSERT(pInfo->annexdata.scAnnData[0] == 0);
ASSERT(pInfo->result == ER_EMPTY);
// 复制开发者们的留言字符串
::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess,
sizeof(WriterMess));
pInfo->result = ER_SUCCESS;
}
// 操作命令解释函数---解释:CMD_GETBUILDID命令
// 获取图像模块内部版本号
void _fnCMD_GETBUILDID(INFOSTR *pInfo)
{
// 这是预定义的函数代码,你可以不必修改的使用。
// 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
ASSERT(pInfo->annexdata.dwAnnData == 0);
ASSERT(pInfo->result == ER_EMPTY);
// 填写内部版本号码
pInfo->annexdata.dwAnnData = MODULE_BUILDID;
pInfo->result = ER_SUCCESS;
}
// 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
// 判断指定文件是否是有效的BMP文件
void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
{
CFile file;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
DWORD dwSize;
UINT uRet, uRet2;
ASSERT(pInfo);
// 检验入口参数是否符合接口定义
ASSERT(pInfo->result == ER_EMPTY);
ASSERT(pInfo->annexdata.iAnnData == 0);
ASSERT(::strlen(pInfo->filename));
ASSERT(pInfo->state == PKST_NOTVER);
// 设初值
pInfo->result = ER_SUCCESS;
pInfo->annexdata.iAnnData = 0;
// 先判断指定的文件是否存在
if (!IsFileExist(pInfo->filename))
pInfo->result = ER_COMMINFOERR;
else
{
// 打开指定文件
if (!file.Open(pInfo->filename, CFile::modeRead))
{
pInfo->result = ER_FILERWERR; // 打开文件时出错
return;
}
// 获取BMP文件的长度(以字节为单位)
dwSize = file.GetLength();
// 用长度判断
if (dwSize < (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
{
// 这不是一个BMP文件,BMP文件的长度起码大于文件头
// 加信息头结构的长度
file.Close();
return;
}
// 读取BMP的文件头及信息头结构,并检查它们的有效性
file.SeekToBegin();
uRet = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
uRet2 = file.Read((LPSTR)&bmiHeader, sizeof(BITMAPINFOHEADER));
if ((uRet != sizeof(BITMAPFILEHEADER))||(uRet2 != sizeof(BITMAPINFOHEADER)))
{
pInfo->result = ER_FILERWERR; // 读文件时出错
file.Close();
return;
}
// 判断文件头部的位图标志(‘BM’)
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
file.Close();
return;
}
// 判断信息结构的尺寸
switch(bmiHeader.biSize)
{
case sizeof(BITMAPINFOHEADER):
break;
default:
//case sizeof(BITMAPCOREHEADER): // 不支持OS/2格式的位图
//case sizeof(BITMAPV5HEADER): // 不支持NT5以上系统产生的位图
//case sizeof(BITMAPV4HEADER): // 不支持Windows4.0系统产生的位图,以后支持
file.Close();
return;
}
// 检验位数据偏移地址
if ((bmfHeader.bfOffBits > dwSize)||
(bmfHeader.bfOffBits < (bmiHeader.biSize+sizeof(BITMAPFILEHEADER))))
{
file.Close();
return;
}
// 到此,大致可以表明该文件是一个有效的BMP文件,iAnnData变量设为1
pInfo->annexdata.iAnnData = 1;
pInfo->state = PKST_PASSVER; // 表示通过校验
file.Close();
}
}
// 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
// 获取指定文件的信息
void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
{
CFile file;
CFileStatus status;
LPBITMAPINFO pDIB;
BITMAPFILEHEADER bmfHeader;
UINT uRet, uDibInfoSize;
// 检验入口参数是否符合接口定义
ASSERT(pInfo->result == ER_EMPTY);
ASSERT(::strlen(pInfo->filename));
// 此时,该文件必需是一个已存在的、并且是有效的BMP文件
ASSERT(pInfo->state == PKST_PASSVER);
// 客户模块必需要先将imginfo清空为0
ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
// 打开指定文件
if (!file.Open(pInfo->filename, CFile::modeRead))
{
pInfo->result = ER_FILERWERR;
return;
}
// 读取BMP的文件头结构
file.SeekToBegin();
uRet = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
if (uRet != sizeof(BITMAPFILEHEADER))
{
file.Close();
pInfo->result = ER_FILERWERR;
return;
}
uDibInfoSize = bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
// 分配内存,用于存放信息头及颜色表(如果有)
pDIB = (LPBITMAPINFO)::GlobalAlloc(GPTR, uDibInfoSize);
if (!pDIB)
{
file.Close();
pInfo->result = ER_MEMORYERR;
return;
}
// 读取图像信息数据
file.Seek((LONG)sizeof(BITMAPFILEHEADER), CFile::begin);
uRet = file.Read((void *)pDIB, uDibInfoSize);
if (uRet != uDibInfoSize)
{
::GlobalFree((void*)pDIB);
file.Close();
pInfo->result = ER_FILERWERR;
return;
}
LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
// 获取文件的长度、图像的宽度、高度等信息
lpImgInfoStr->imgtype = IMT_RESSTATIC;
lpImgInfoStr->imgformat = IMF_BMP;
lpImgInfoStr->filesize = file.GetLength();
lpImgInfoStr->width = pDIB->bmiHeader.biWidth;
// 图像的高度值有时可能是负值,所以使用了abs()函数
lpImgInfoStr->height = (DWORD)::abs(pDIB->bmiHeader.biHeight);
lpImgInfoStr->bitcount = (DWORD)pDIB->bmiHeader.biBitCount;
switch(pDIB->bmiHeader.biCompression)
{
case BI_RGB: //0L
lpImgInfoStr->compression = ICS_RGB; break;
case BI_RLE8: //1L
lpImgInfoStr->compression = ICS_RLE8; break;
case BI_RLE4: //2L
lpImgInfoStr->compression = ICS_RLE4; break;
case BI_BITFIELDS://3L
lpImgInfoStr->compression = ICS_BITFIELDS; break;
default:
//case BI_PNG: // 以后的版本将支持这两种位格式
//case BI_JPEG:
ASSERT(FALSE);
}
// 每一图像行所占的字节数(DWORD对齐,并且只对非压缩位图有效)
lpImgInfoStr->linesize = DIBSCANLINE_WIDTHBYTES(pDIB->bmiHeader.biWidth*pDIB->bmiHeader.biBitCount);
lpImgInfoStr->imgnumbers = 1; // BMP文件中只有一个图像
lpImgInfoStr->imgchang = 0; // 表示可以被编辑
// 获取文件最后的修改日期(月在高字节,日在低字节)
file.GetStatus(status);
lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
lpImgInfoStr->monday <<= 8;
lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
// 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
lpImgInfoStr->time = status.m_mtime.GetHour();
lpImgInfoStr->time <<= 8;
lpImgInfoStr->time |= status.m_mtime.GetMinute();
lpImgInfoStr->time <<= 8;
lpImgInfoStr->time |= status.m_mtime.GetSecond();
lpImgInfoStr->time &= 0xffffff;
::GlobalFree((void*)pDIB);
file.Close();
// 设置出口数据
pInfo->state = PKST_PASSINFO;
pInfo->result = ER_SUCCESS;
}
// 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
// 从指定图像文件中读取数据
void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
{
// 检验入口参数是否符合接口定义
ASSERT(pInfo->result == ER_EMPTY);
ASSERT(::strlen(pInfo->filename));
// 此时,该文件必需是一个已存在的、有效的BMP文件,并且数据包中
// 含有该文件的信息(imginfo结构中)
ASSERT(pInfo->state == PKST_PASSINFO);
ASSERT(pInfo->imginfo.imgformat == IMF_BMP);
ASSERT(pInfo->pImgInfo == NULL);
// 必需设置标准图像格式信息
ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
ASSERT(pInfo->pLineAddr != NULL);
ASSERT(pInfo->_pbdata != NULL);
CFile file;
// 以图像的高度值作为进度总值
RWPROGRESSSIZE = (int)pInfo->imginfo.height;
if (pInfo->fpProgress)
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return;
}
}
// 打开指定文件
if (!file.Open(pInfo->filename, CFile::modeRead))
{
pInfo->result = ER_FILERWERR;
return;
}
file.Seek(0, CFile::begin);
if (pInfo->fpProgress)
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
file.Close();
pInfo->result = ER_USERBREAK;
return;
}
}
// 读取并转换图像到数据包中
if (_Read(file, pInfo) == 0)
{
// 成功
pInfo->state = PKST_INFOANDBITS;
pInfo->modify = 0;
pInfo->result = ER_SUCCESS;
}
file.Close();
if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
(*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
}
// 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
// 将数据保存到指定文件中
// pInfo所指向的数据包中,annexdata.siAnnData[]变量的含意解释:
// [0] — 位深度,可以是1、4、8、16(555)、24、32(888)这六个值
// 中的一个,不能是其他值。另:不能存储为RLE格式
// [1] — 是否使用原始调色板。0 — 表示使用,1 — 表示使用当前
// 计算机缺省调色板
void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
{
// 检验入口参数是否符合接口定义
ASSERT(pInfo->result == ER_EMPTY);
// 该文件名可以是一个已存在的文件,也可以是不存在的文件(本函数将创建)。
ASSERT(::strlen(pInfo->filename));
ASSERT(pInfo->state == PKST_INFOANDBITS);
// 必需设置标准图像格式信息
ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
ASSERT(pInfo->pLineAddr != NULL);
ASSERT(pInfo->_pbdata != NULL);
CFile file;
CFileStatus status;
BITMAPFILEHEADER bmf;
int uDibInfoSize;
LPBITMAPINFO pDIB;
int uRet;
// 此时imginfo中的数据可能与sDIBInfo不一样,以sDIBInfo为准
RWPROGRESSSIZE = (int)::abs(pInfo->sDIBInfo.bmi.biHeight);
if (pInfo->fpProgress)
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
{ // 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return;
}
}
// 打开指定文件(如果不存在就创建,如果存在,不截断为0长度),不
// 允许其它进程写该文件
if (!file.Open(pInfo->filename, CFile::modeCreate|CFile::modeNoTruncate|
CFile::modeReadWrite|CFile::shareDenyWrite))
{
pInfo->result = ER_FILERWERR;
return;
}
file.Seek(0, CFile::begin);
LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
// 读取并转换图像到数据包中
if (_Save(file, pInfo) == 0)
{
file.Flush(); // 刷新文件的内容、尺寸、最后修改日期
file.Seek(0, CFile::begin);
if (file.Read((void*)&bmf, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
{
file.Close();
pInfo->result = ER_FILERWERR;
return;
}
uDibInfoSize = bmf.bfOffBits-sizeof(BITMAPFILEHEADER);
// 分配内存,用于存放信息头及颜色表(如果有)
pDIB = (LPBITMAPINFO)::GlobalAlloc(GPTR, uDibInfoSize);
if (!pDIB)
{
file.Close();
pInfo->result = ER_MEMORYERR;
return;
}
// 读取图像信息数据
file.Seek((LONG)sizeof(BITMAPFILEHEADER), CFile::begin);
uRet = file.Read((void *)pDIB, uDibInfoSize);
if (uRet != uDibInfoSize)
{
::GlobalFree((void*)pDIB);
file.Close();
pInfo->result = ER_FILERWERR;
return;
}
if (pInfo->pImgInfo) // 释放图像的原始信息块
::GlobalFree((void*)pInfo->pImgInfo);
pInfo->pImgInfo = (void*)pDIB; // 设置原始信息块
// 获取文件的长度、图像的宽度、高度等信息
lpImgInfoStr->imgtype = IMT_RESSTATIC;
lpImgInfoStr->imgformat = IMF_BMP;
lpImgInfoStr->filesize = file.GetLength();
lpImgInfoStr->width = pInfo->sDIBInfo.bmi.biWidth;
// 图像的高度值有时可能是负值,所以使用了abs()函数
lpImgInfoStr->height = (DWORD)::abs(pInfo->sDIBInfo.bmi.biHeight);
lpImgInfoStr->bitcount = (DWORD)pInfo->annexdata.siAnnData[0]; // 新的位深度值
lpImgInfoStr->compression = ICS_RGB; // 写函数当前只支持BI_RGB格式
// 每一图像行所占的字节数(DWORD对齐,并且只对非压缩位图有效)
lpImgInfoStr->linesize = DIBSCANLINE_WIDTHBYTES(lpImgInfoStr->width*lpImgInfoStr->bitcount);
lpImgInfoStr->imgnumbers = 1; // BMP文件中只有一个图像
lpImgInfoStr->imgchang = 0; // 表示可以被编辑
// 获取文件最后的修改日期(月在高字节,日在低字节)
file.GetStatus(status);
lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
lpImgInfoStr->monday <<= 8;
lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
// 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
lpImgInfoStr->time = status.m_mtime.GetHour();
lpImgInfoStr->time <<= 8;
lpImgInfoStr->time |= status.m_mtime.GetMinute();
lpImgInfoStr->time <<= 8;
lpImgInfoStr->time |= status.m_mtime.GetSecond();
lpImgInfoStr->time &= 0xffffff;
// 成功
pInfo->result = ER_SUCCESS;
}
file.Close();
if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
(*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
}
// 操作命令解释函数---解释:CMD_RESIZE命令
// 重新获取指定尺寸的图像位数据(只适用于矢量图像)
void _fnCMD_RESIZE(INFOSTR *pInfo)
{
// 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像,
// 比如WMF、EMF之类。
// 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
// ----------------------------------------------------------------->
pInfo->result = ER_NOTSUPPORT;
}
/*************************************************************************
*
* IsFileExist()
*
* 参数说明:
*
* char *lpFileName - 待判断的文件路径和名称(文件名)
*
* 返回值:
*
* BOOL - 如果指定的文件存在返回TRUE,否则返回FALSE。
*
* 描述:
*
* 判断指定的文件是否存在
*
* 该文件必需可以被读和写
*
************************************************************************/
BOOL IsFileExist(char *lpFileName)
{
CFile file;
BOOL bExist = FALSE; // 文件存在是TRUE,不存在是FALSE
CFileException e;
// 确定指定的文件是否存在
if (file.Open(lpFileName, CFile::modeReadWrite|CFile::shareDenyNone, &e))
{
bExist = TRUE;
file.Close();
}
else
{
// 可能有其他程序正在处理此文件
switch(e.m_cause)
{
case CFileException::tooManyOpenFiles:
case CFileException::accessDenied:
case CFileException::sharingViolation:
case CFileException::lockViolation:
return TRUE;
case CFileException::fileNotFound:
case CFileException::badPath:
case CFileException::invalidFile:
case CFileException::hardIO:
default:
return FALSE;
}
}
return bExist;
}
// 将指定文件读入目标缓冲区
int _Read(CFile& file, LPINFOSTR pInfo)
{
RGBQUAD *pPalette;
int imgorg;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
PBYTE pBits;
PBYTE pImgInfo;
DWORD dwSize, dwRet;
UINT uRet;
/* 读取DIB的文件头结构 */
file.SeekToBegin();
uRet = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
uRet += file.Read((LPSTR)&bmiHeader, sizeof(BITMAPINFOHEADER));
if (uRet != (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
{
pInfo->result = ER_FILERWERR;
return 1; // 读文件时出错
}
// pImgInfo将包含位图信息结构及调色板信息(如果有的话)
pImgInfo = (PBYTE)::GlobalAlloc(GPTR, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER));
if (pImgInfo == NULL)
{
pInfo->result = ER_MEMORYERR;
return 2; // 内存不足
}
// 读取位图文件的原始信息
file.Seek(sizeof(BITMAPFILEHEADER), CFile::begin);
uRet = file.Read((void*)pImgInfo, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER));
if (uRet != (bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
{
::GlobalFree(pImgInfo);
pInfo->result = ER_FILERWERR;
return 1;
}
// 正常情况下,高度值不会是负值或0
ASSERT(RWPROGRESSSIZE > 0);
if (pInfo->fpProgress)
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
::GlobalFree(pImgInfo);
pInfo->result = ER_USERBREAK;
return 4; // 用户中断操作
}
}
// 获取文件长度
dwSize = file.GetLength();
// 分配内存,用于存放位数据
pBits = (PBYTE)::GlobalAlloc(GPTR, dwSize-bmfHeader.bfOffBits);
if (!pBits)
{
::GlobalFree(pImgInfo);
pInfo->result = ER_MEMORYERR;
return 2; // 内存不足
}
// 读取位数据
file.Seek(bmfHeader.bfOffBits, CFile::begin);
dwRet = file.ReadHuge((void*)pBits, (dwSize-bmfHeader.bfOffBits));
if (dwRet != (dwSize-bmfHeader.bfOffBits))
{
::GlobalFree(pImgInfo);
::GlobalFree(pBits);
pInfo->result = ER_FILERWERR;
return 1;
}
if (pInfo->fpProgress)
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
::GlobalFree(pImgInfo);
::GlobalFree(pBits);
pInfo->result = ER_USERBREAK;
return 4; // 用户中断操作
}
}
// 下面的读取函数需要该指针,所以在此处赋值
pInfo->pImgInfo = pImgInfo;
pPalette = (RGBQUAD*)(pImgInfo+bmiHeader.biSize);
imgorg = (bmiHeader.biHeight > 0) ? 0:1; // 0-为倒向位图 1-为正向
int result = 0; // 接收各函数的返回值
// 根据位图文件的位深度的不同而调用相应的读取函数
switch(_get_souformat((LPBITMAPINFO)pImgInfo))
{
case SF_1:
result = _from_1_read(pInfo, pBits, imgorg, pPalette);
break;
case SF_4:
result = _from_4_read(pInfo, pBits, imgorg, pPalette);
break;
case SF_4_RLE:
result = _from_4_RLE_read(pInfo, pBits, imgorg, pPalette);
break;
case SF_8:
result = _from_8_read(pInfo, pBits, imgorg, pPalette);
break;
case SF_8_RLE:
result = _from_8_RLE_read(pInfo, pBits, imgorg, pPalette);
break;
case SF_16_555:
result = _from_16_555_read(pInfo, pBits, imgorg);
break;
case SF_16_565:
result = _from_16_565_read(pInfo, pBits, imgorg);
break;
case SF_24:
result = _from_24_read(pInfo, pBits, imgorg);
break;
case SF_32:
result = _from_32_read(pInfo, pBits, imgorg);
break;
default:
::GlobalFree(pImgInfo);
::GlobalFree(pBits);
pInfo->pImgInfo = NULL;
pInfo->result = ER_SYSERR;
return 3; // 图像文件格式异常
}
// 释放从文件中读取的位数据(此数据已被转换并保存到了数据包中)
::GlobalFree(pBits);
if (result == 0) // 执行成功
{
pInfo->result = ER_SUCCESS;
}
else
{
::GlobalFree(pImgInfo);
pInfo->pImgInfo = NULL;
return 4; // 执行过程中产生的错误,详见pInfo->result
}
return 0;
}
// 将1位(即单色)位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_1_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg, RGBQUAD *lpPalette)
{
ASSERT(pInfo);
ASSERT(lpPalette); // 单色位图应有两个调色板项
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSou);
int sImgOrg = imgorg; // 源图像扫描行次序的标志:0-为倒向 1-为正向
// 源图像的次序由调用者传入
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, i, j, isou;
ASSERT(pInfo->pImgInfo);
int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
PBYTE pCurPixAddr;
BYTE pix; // 当前8个像素
palnum = (palnum == 0) ? 2:palnum; // 计算调色板项的实际个数
ASSERT(palnum <= 2);
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
// 以555位格式的调色板数据
WORD descol555_0 = 0;
WORD descol555_1 = 0;
if (palnum > 0)
descol555_0 = _cnv_rgb_to_555(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
if (palnum > 1)
descol555_1 = _cnv_rgb_to_555(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
WORD *pDesPixAddr555;
if (sImgOrg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr555++ = descol555_1;
}
else
{
*pDesPixAddr555++ = descol555_0;
}
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr555++ = descol555_1;
}
else
{
*pDesPixAddr555++ = descol555_0;
}
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
// 以565位格式的调色板数据
WORD descol565_0 = 0;
WORD descol565_1 = 0;
if (palnum > 0)
descol565_0 = _cnv_rgb_to_565(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
if (palnum > 1)
descol565_1 = _cnv_rgb_to_565(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
WORD *pDesPixAddr565;
if (sImgOrg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr565++ = descol565_1;
}
else
{
*pDesPixAddr565++ = descol565_0;
}
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr565++ = descol565_1;
}
else
{
*pDesPixAddr565++ = descol565_0;
}
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
// 24位格式的调色板数据
BYTE red0, red1, green0, green1, blue0, blue1;
if (palnum > 0)
{
red0 = lpPalette[0].rgbRed;
green0 = lpPalette[0].rgbGreen;
blue0 = lpPalette[0].rgbBlue;
}
if (palnum > 1)
{
red1 = lpPalette[1].rgbRed;
green1 = lpPalette[1].rgbGreen;
blue1 = lpPalette[1].rgbBlue;
}
PBYTE pDesPixAddr24;
if (sImgOrg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr24++ = blue1;
*pDesPixAddr24++ = green1;
*pDesPixAddr24++ = red1;
}
else
{
*pDesPixAddr24++ = blue0;
*pDesPixAddr24++ = green0;
*pDesPixAddr24++ = red0;
}
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr24++ = blue1;
*pDesPixAddr24++ = green1;
*pDesPixAddr24++ = red1;
}
else
{
*pDesPixAddr24++ = blue0;
*pDesPixAddr24++ = green0;
*pDesPixAddr24++ = red0;
}
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
// 以888位格式的调色板数据
DWORD descol888_0 = 0;
DWORD descol888_1 = 0;
if (palnum > 0)
descol888_0 = _cnv_rgb_to_888(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
if (palnum > 1)
descol888_1 = _cnv_rgb_to_888(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
DWORD *pDesPixAddr888;
if (sImgOrg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr888++ = descol888_1;
}
else
{
*pDesPixAddr888++ = descol888_0;
}
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>i))&pix) // 此位被设置
{
*pDesPixAddr888++ = descol888_1;
}
else
{
*pDesPixAddr888++ = descol888_0;
}
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将4位(即16色)位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_4_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg, RGBQUAD *lpPalette)
{
ASSERT(pInfo);
ASSERT(lpPalette); // 16色位图应有调色板
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, i, j, isou;
ASSERT(pInfo->pImgInfo);
int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
PBYTE pCurPixAddr;
BYTE pix; // 当前2个像素
palnum = (palnum == 0) ? 16:palnum; // 计算调色板项的实际个数
ASSERT(palnum <= 16);
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
// 以555位格式的调色板数据
WORD descol555[16];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr555++ = descol555[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr555++ = descol555[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
// 以565位格式的调色板数据
WORD descol565[16];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr565++ = descol565[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr565++ = descol565[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
int index24_0, index24_1;
PBYTE pDesPixAddr24;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4);
index24_1 = (int)(pix&0xf);
for (i=0;ifpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4);
index24_1 = (int)(pix&0xf);
for (i=0;ifpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
// 以888位格式的调色板数据
DWORD descol888[16];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr888++ = descol888[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>4];
else
*pDesPixAddr888++ = descol888[pix&0xf];
}
}
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将4位RLE位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_4_RLE_read(LPINFOSTR pInfo, PBYTE lpSouData, int imgorg, RGBQUAD *lpPalette)
{
ASSERT(pInfo);
ASSERT(lpPalette); // 16色位图应有调色板
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSouData);
ASSERT(imgorg == 0); // 压缩位图必需是倒向的
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
PBYTE lpSou = lpSouData;
BYTE pix, pix2; // 当前值
int result, i;
BYTE **lppLineAddr = (BYTE**)::GlobalAlloc(GPTR, sizeof(PBYTE)*imgheight);
if (lppLineAddr == NULL)
{
pInfo->result = ER_MEMORYERR;
return -2; // 内存不足,返回
}
int linesize = ((imgwidth*4+31)/32)*4;
PBYTE lpDes = (PBYTE)::GlobalAlloc(GPTR, linesize*imgheight);
if (lpDes == NULL)
{
::GlobalFree(lppLineAddr);
pInfo->result = ER_MEMORYERR;
return -2; // 内存不足,返回
}
// 初始化行地址数组
for (i=0;istate >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
ASSERT(pInfo->pImgInfo);
int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
int heigCount, widthCount, i, isou;
PBYTE pCurPixAddr;
BYTE pix; // 当前像素
palnum = (palnum == 0) ? 256:palnum; // 计算调色板项的实际个数
ASSERT(palnum <= 256);
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
// 以555位格式的调色板数据
WORD descol555[256];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
// 以565位格式的调色板数据
WORD descol565[256];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
PBYTE pDesPixAddr24;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
// 以888位格式的调色板数据
DWORD descol888[256];
for (i=0;i=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将8位RLE位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_8_RLE_read(LPINFOSTR pInfo, PBYTE lpSouData, int imgorg, RGBQUAD *lpPalette)
{
ASSERT(pInfo);
ASSERT(lpPalette); // 256色位图应有调色板
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSouData);
ASSERT(imgorg == 0); // 压缩位图必需是倒向的
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
PBYTE lpSou = lpSouData;
BYTE pix, pix2; // 当前值
int result, i;
BYTE **lppLineAddr = (BYTE**)::GlobalAlloc(GPTR, sizeof(PBYTE)*imgheight);
if (lppLineAddr == NULL)
{
pInfo->result = ER_MEMORYERR;
return -2; // 内存不足,返回
}
int linesize = ((imgwidth+3)/4)*4; // 扫描行尺寸(in byte)
PBYTE lpDes = (PBYTE)::GlobalAlloc(GPTR, linesize*imgheight);
if (lpDes == NULL)
{
::GlobalFree(lppLineAddr);
pInfo->result = ER_MEMORYERR;
return -2; // 内存不足,返回
}
// 初始化行地址数组
for (i=0;istate >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, isou;
WORD *pCurPixAddr;
WORD pix; // 当前像素
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
WORD *pDesPixAddr555;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
WORD *pDesPixAddr565;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
PBYTE pDesPixAddr24;
BYTE red, green, blue;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
DWORD *pDesPixAddr888;
DWORD pix32;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将16位565位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_16_565_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
{
ASSERT(pInfo);
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, isou;
WORD *pCurPixAddr;
WORD pix; // 当前像素
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
WORD *pDesPixAddr555;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>1)&0x7fe0)|((*pCurPixAddr++)&0x1f);
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCount>1)&0x7fe0)|((*pCurPixAddr++)&0x1f);
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
WORD *pDesPixAddr565;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
PBYTE pDesPixAddr24;
BYTE red, green, blue;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
DWORD *pDesPixAddr888;
DWORD pix32;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将24位位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_24_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
{
ASSERT(pInfo);
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, isou;
PBYTE pCurPixAddr;
BYTE red, green, blue;
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
WORD *pDesPixAddr555;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
WORD *pDesPixAddr565;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
PBYTE pDesPixAddr24;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
::CopyMemory((PVOID)pDesPixAddr24, (PVOID)pCurPixAddr, imgwidth*3);
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
::CopyMemory((PVOID)pDesPixAddr24, (PVOID)pCurPixAddr, imgwidth*3);
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
DWORD *pDesPixAddr888;
DWORD pix32;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// 将32位位图转换为指定的标准格式位图
// pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
// imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
int _from_32_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
{
ASSERT(pInfo);
ASSERT(pInfo->state >= PKST_PASSINFO);
ASSERT(lpSou);
int imgheight = pInfo->imginfo.height; // 图像的高度
int imgwidth = pInfo->imginfo.width; // 图像的宽度
int scansize = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
int heigCount, widthCount, isou;
PBYTE pCurPixAddr;
BYTE red, green, blue;
switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
{
case DF_16_555:
{
WORD *pDesPixAddr555;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr555 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_16_565:
{
WORD *pDesPixAddr565;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr565 = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_24:
{
PBYTE pDesPixAddr24;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr24 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
for (widthCount=0;widthCountfpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_32:
{
PBYTE pDesPixAddr888;
if (imgorg == 0) // 源图是倒向位图
{
for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
{
pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
pDesPixAddr888 = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
::CopyMemory((PVOID)pDesPixAddr888, (PVOID)pCurPixAddr, imgwidth*4);
if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
else // 正向位图(top-down)
{
for (heigCount=0;heigCountpLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
::CopyMemory((PVOID)pDesPixAddr888, (PVOID)pCurPixAddr, imgwidth*4);
if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
{
if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
{
// 如果进度函数返回1,则说明用户想中断操作,返回。
pInfo->result = ER_USERBREAK;
return 1; // 用户中断操作
}
}
}
}
}
break;
case DF_NULL:
default:
ASSERT(FALSE);
pInfo->result = ER_ILLCOMM;
return -1;
break;
}
return 0;
}
// pInfo所指向的数据包中,annexdata.siAnnData[]变量的含意解释:
// [0] — 位深度,可以是1、4、8、16(555)、24、32(888)这六个值
// 中的一个,不能是其他值。另:不能存储为RLE格式
// [1] — 是否使用原始调色板。0 — 表示使用,1 — 表示使用当前
// 计算机缺省调色板
int _Save(CFile& pf, LPINFOSTR pInfo)
{
PBYTE lpBits;
HBITMAP hBmp;
ASSERT(pInfo);
int dibitcount = pInfo->annexdata.siAnnData[0]; // 目标文件的位深度
int palnum = _get_palette_size(dibitcount); // 调色板项数目
BITMAPINFO *pbmi = (BITMAPINFO*)::GlobalAlloc(GPTR, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*palnum);
RGBQUAD *ppal = (RGBQUAD*)((PBYTE)pbmi+sizeof(BITMAPINFOHEADER));
if (!pbmi)
{
pInfo->result = ER_MEMORYERR;
return 2; // 内存不足
}
HWND hWnd = ::GetDesktopWindow();
HDC hDC = ::GetDC(hWnd);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = dibitcount;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biWidth = pInfo->sDIBInfo.bmi.biWidth;
pbmi->bmiHeader.biHeight = pInfo->sDIBInfo.bmi.biHeight;
pbmi->bmiHeader.biClrImportant = 0;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biXPelsPerMeter = (int)(::GetDeviceCaps(hDC,LOGPIXELSX)*(float)39.373);
pbmi->bmiHeader.biYPelsPerMeter = (int)(::GetDeviceCaps(hDC,LOGPIXELSY)*(float)39.373);
if (palnum)
{
switch(pInfo->annexdata.siAnnData[1])
{
case 0: // 使用原位图调色板(读取的原始图像文件必需也是BMP位图)
if (pInfo->imginfo.imgformat == IMF_BMP)
{
if (pInfo->imginfo.bitcount == (unsigned int)dibitcount) // 只有原始图像的格式与目标文件的位深度相同时,才有意义
{
ASSERT(pInfo->pImgInfo); // 原始数据必需有效
ASSERT(((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biSize == sizeof(BITMAPINFOHEADER));
RGBQUAD *porg = (RGBQUAD*)(((BITMAPINFOHEADER*)(pInfo->pImgInfo))+1);
int palnum2 = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
palnum2 = (palnum2) ? palnum2:palnum;
ASSERT(palnum2 <= palnum);
for (int i=0;iresult = ER_MEMORYERR;
return 2; // 内存不足
}
::GetSystemPaletteEntries(hDC, 0, palnum, pal);
for (int i=0;iresult = ER_SYSERR;
return 5; // 操作系统不稳定
}
if (!SetDIBits(hDC, hBmp, 0, pInfo->imginfo.height, pInfo->_pbdata, (const BITMAPINFO*)&pInfo->sDIBInfo, DIB_RGB_COLORS))
{
::GlobalFree(pbmi);
::ReleaseDC(hWnd, hDC);
::DeleteObject(hBmp);
pInfo->result = ER_SYSERR;
return 5;
}
::ReleaseDC(hWnd, hDC);
BITMAPFILEHEADER bmf;
bmf.bfType = DIB_HEADER_MARKER;
bmf.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+\
sizeof(RGBQUAD)*palnum+((pInfo->imginfo.width*dibitcount+31)/32)*4*pInfo->imginfo.height;
bmf.bfReserved1 = 0;
bmf.bfReserved2 = 0;
bmf.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+\
sizeof(RGBQUAD)*palnum;
TRY
{
// writing bitmap file header
pf.SeekToBegin();
pf.Write((const void *)&bmf, sizeof(BITMAPFILEHEADER));
// writing bitmap info header
pf.Write((const void *)pbmi, sizeof(BITMAPINFOHEADER));
}
CATCH(CFileException, e)
{
::GlobalFree(pbmi);
::DeleteObject(hBmp);
pInfo->result = ER_FILERWERR;
return 1; // 写文件时出错
}
END_CATCH
::GlobalFree(pbmi);
RGBQUAD *palette = NULL;
TRY
{
if (palnum)
{
palette = (RGBQUAD*)::GlobalAlloc(GPTR, sizeof(RGBQUAD)*palnum);
if (!palette)
{
::DeleteObject(hBmp);
pInfo->result = ER_MEMORYERR;
return 2; // 内存不足
}
HDC hCompDC = ::CreateCompatibleDC(NULL);
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hCompDC, hBmp);
::GetDIBColorTable(hCompDC, 0, palnum, palette);
::SelectObject(hCompDC, hOldBmp);
::DeleteDC(hCompDC);
// writing color table.
pf.Write((const void *)palette, sizeof(RGBQUAD)*palnum);
::GlobalFree(palette);
}
pf.WriteHuge((const void *)lpBits, ((pInfo->imginfo.width*dibitcount+31)/32)*4*pInfo->imginfo.height);
}
CATCH(CFileException, e)
{
if (palette) ::GlobalFree(palette);
::DeleteObject(hBmp);
pInfo->result = ER_FILERWERR;
return 1; // 写文件时出错
}
END_CATCH
::DeleteObject(hBmp);
pInfo->result = ER_SUCCESS;
return 0; // 写文件成功
}
// 判断标准图像的位格式
DESFORMAT _get_desformat(LPINFOSTR pInfo)
{
ASSERT(pInfo);
// ASSERT(pInfo->state >= PKST_PASSVER);
ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
DESFORMAT result;
switch(pInfo->sDIBInfo.bmi.biBitCount)
{
case 32:
/******************************************************
32位掩码示意图
高 -> 低
0000 0000 0000 0000 0000 0000 0000 0000 888格式
1111 1111 ------------------------R
1111 1111 -------------G
1111 1111--B
* Win95 系统只支持这一种格式
******************************************************/
if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
{
result = DF_32;
break;
}
if ((pInfo->sDIBInfo.rmask == 0xff0000)&&
(pInfo->sDIBInfo.gmask == 0xff00)&&
(pInfo->sDIBInfo.bmask == 0xff))
result = DF_32;
else
{
ASSERT(FALSE); // 只支持888格式
result = DF_NULL;
}
break;
case 24:
result = DF_24;
break;
case 16:
/*******************************************
16位掩码示意图
高字节 低字节
0000 0000 0000 0000
1 1111--B // 555格式
11 111 -------G
111 11 --------------R
0
1 1111--B // 565格式
111 111 -------G
1111 1 --------------R
* Win95 系统只支持以上两种格式
*******************************************/
if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
{
result = DF_16_555;
break;
}
if ((pInfo->sDIBInfo.rmask == 0x7c00)&&
(pInfo->sDIBInfo.gmask == 0x3e0)&&
(pInfo->sDIBInfo.bmask == 0x1f))
result = DF_16_555;
else if ((pInfo->sDIBInfo.rmask == 0xf800)&&
(pInfo->sDIBInfo.gmask == 0x7e0)&&
(pInfo->sDIBInfo.bmask == 0x1f))
result = DF_16_565;
else
result = DF_NULL;
break;
default:
ASSERT(FALSE); // 不接受其它格式
result = DF_NULL;
break;
}
return result;
}
// 判断标准图像的位格式
SOUFORMAT _get_souformat(LPBITMAPINFO pInfo)
{
ASSERT(pInfo->bmiHeader.biSize);
SOUFORMAT result;
switch(pInfo->bmiHeader.biBitCount)
{
case 1:
ASSERT(pInfo->bmiHeader.biCompression == BI_RGB);
result = SF_1;
break;
case 4:
if (pInfo->bmiHeader.biCompression == BI_RGB)
result = SF_4;
else if ((pInfo->bmiHeader.biCompression == BI_RLE4)&&\
(pInfo->bmiHeader.biHeight > 0)) // 正向的位图不能被压缩
result = SF_4_RLE;
else
result = SF_NULL;
break;
case 8:
if (pInfo->bmiHeader.biCompression == BI_RGB)
result = SF_8;
else if ((pInfo->bmiHeader.biCompression == BI_RLE8)&&\
(pInfo->bmiHeader.biHeight > 0))
result = SF_8_RLE;
else
result = SF_NULL;
break;
case 16:
{
/*******************************************
16位掩码示意图
高字节 低字节
0000 0000 0000 0000
1 1111--B // 555格式
11 111 -------G
111 11 --------------R
0
1 1111--B // 565格式
111 111 -------G
1111 1 --------------R
* Win95 系统只支持以上两种格式
*******************************************/
if (pInfo->bmiHeader.biCompression == BI_RGB)
{
result = SF_16_555;
break;
}
DWORD *pMark = (DWORD*)((LPBITMAPINFOHEADER)pInfo+1);
if ((pMark[0] == 0x7c00)&&(pMark[1] == 0x3e0)&&(pMark[2] == 0x1f))
result = SF_16_555;
else if ((pMark[0] == 0xf800)&&(pMark[1] == 0x7e0)&&(pMark[2] == 0x1f))
result = SF_16_565;
else
result = SF_NULL;
break;
}
case 24:
ASSERT(pInfo->bmiHeader.biCompression == BI_RGB);
result = SF_24;
break;
case 32:
{
/******************************************************
32位掩码示意图
高 -> 低
0000 0000 0000 0000 0000 0000 0000 0000 888格式
1111 1111 ------------------------R
1111 1111 -------------G
1111 1111--B
* Win95 系统只支持这一种格式
******************************************************/
if (pInfo->bmiHeader.biCompression == BI_RGB)
{
result = SF_32;
break;
}
DWORD *pMark = (DWORD*)((LPBITMAPINFOHEADER)pInfo+1);
if ((pMark[0] == 0xff0000)&&(pMark[1] == 0x00ff00)&&(pMark[2] == 0xff))
result = SF_32;
else
result = SF_NULL; // 只支持888格式
break;
}
default:
result = SF_NULL;
break;
}
return result;
}
// 将指定的RGB颜色分量转换成555格式(WORD型值返回)
WORD _cnv_rgb_to_555(BYTE red, BYTE green, BYTE blue)
{
WORD result = 0;
result = (((WORD)red>>3)<<10)|(((WORD)green>>3)<<5)|((WORD)blue>>3);
return result;
}
// 将指定的555格式的颜色转换成RGB颜色分量
void _cnv_555_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
{
// 在555转换到RGB时,将像素的亮度调到最大
*red = (BYTE)((col>>7)&0xf8);
*green = (BYTE)((col>>2)&0xf8);
*blue = (BYTE)(col<<3);
}
// 将指定的RGB颜色分量转换成565格式(WORD型值返回)
WORD _cnv_rgb_to_565(BYTE red, BYTE green, BYTE blue)
{
WORD result = 0;
result = (((WORD)red>>3)<<11)|(((WORD)green>>2)<<5)|((WORD)blue>>3);
return result;
}
// 将指定的565格式的颜色转换成RGB颜色分量
void _cnv_565_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
{
// 在565转换到RGB时,将像素的亮度调到最大
*red = (BYTE)((col>>8)&0xf8);
*green = (BYTE)((col>>3)&0xfc);
*blue = (BYTE)(col<<3);
}
// 将指定的RGB颜色分量转换成888格式(DWORD型值返回)
DWORD _cnv_rgb_to_888(BYTE red, BYTE green, BYTE blue)
{
DWORD result = 0;
result = ((DWORD)red<<16)|((DWORD)green<<8)|(DWORD)blue;
return result;
}
// 向4位缓冲区写像素(只供_from_4_RLE_read()函数内部调用)
// 形参mark含意:0-初始化变量 1-写像素 2-移动到指定点 3-结束操作 4-获取当前地址
// 注:当mark等于2时,参数num将作为像素除2余数被代入,来对iCurOff赋值
PBYTE _write2buff4RLE(int mark, int num, BYTE pix, PBYTE lpDesData)
{
static PBYTE lpDes; // 缓冲区基地址
static PBYTE lpCur; // 缓冲区当前写地址
static int iCurOff; // 在字节中的当前位置,0-高半字节 1-低半字节
int i;
BYTE pixa[2];
switch(mark)
{
case 0: // 初始化变量
lpDes = lpDesData;
lpCur = lpDes;
iCurOff = 0;
break;
case 1: // 写像素
pixa[0] = pix>>4;
pixa[1] = pix&0xf;
for (i=0;i