BmpModule.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:98k
源码类别:

图形图象

开发平台:

Visual C++

  1. /********************************************************************
  2. BmpModule.cpp - ISee图像浏览器—BMP图像读写模块实现文件
  3.           
  4.     版权所有(C) 2000 VCHelp-coPathway-ISee workgroup member
  5.     这一程序是自由软件,你可以遵照自由软件基金会出版的GNU 通用公共许
  6. 可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根
  7. 据你的选择)用任何更新的版本。
  8.     发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定
  9. 目地的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
  10.     你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果还没有,
  11. 写信给:
  12.     The Free Software Foundation, Inc.,  675  Mass Ave,  Cambridge,
  13.     MA02139,  USA
  14. 如果你在使用本软件时有什么问题或建议,用以下地址可以与我们取得联
  15. 系:
  16. http://isee.126.com
  17. http://www.vchelp.net
  18. 或:
  19. iseesoft@china.com
  20. 编写人:YZ
  21. E-Mail:yzfree@sina.com
  22. 文件版本:
  23. Beta  1.5
  24. Build 01209
  25. Date  2000-12-9
  26. ********************************************************************/
  27. #include "stdafx.h"
  28. #include "..publicgol_isee.h" // 此文件定义了接口数据包
  29. #include "BmpModule.h"
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. static char ModuleProcessImgType[]="BMP,DIB,RLE"; // 本模块能处理的图像类型
  36. static char WriterList[]="YZ"; // 本模块的作者列表
  37. static char WriterMess[]="没想到做好BMP模块还真挺复杂^_^"; // 作者留言
  38. static int  RWPROGRESSSIZE;
  39. static const int RWPROGRESSSTEP = 10;
  40. //
  41. // Note!
  42. //
  43. // If this DLL is dynamically linked against the MFC
  44. // DLLs, any functions exported from this DLL which
  45. // call into MFC must have the AFX_MANAGE_STATE macro
  46. // added at the very beginning of the function.
  47. //
  48. // For example:
  49. //
  50. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  51. // {
  52. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  53. // // normal function body here
  54. // }
  55. //
  56. // It is very important that this macro appear in each
  57. // function, prior to any calls into MFC.  This means that
  58. // it must appear as the first statement within the 
  59. // function, even before any object variable declarations
  60. // as their constructors may generate calls into the MFC
  61. // DLL.
  62. //
  63. // Please see MFC Technical Notes 33 and 58 for additional
  64. // details.
  65. //
  66. // 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
  67. // ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
  68. // 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
  69. //
  70. //
  71. /////////////////////////////////////////////////////////////////////////////
  72. // CBmpModuleApp
  73. BEGIN_MESSAGE_MAP(CBmpModuleApp, CWinApp)
  74. //{{AFX_MSG_MAP(CBmpModuleApp)
  75. // NOTE - the ClassWizard will add and remove mapping macros here.
  76. //    DO NOT EDIT what you see in these blocks of generated code!
  77. //}}AFX_MSG_MAP
  78. END_MESSAGE_MAP()
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CBmpModuleApp construction
  81. CBmpModuleApp::CBmpModuleApp()
  82. {
  83. // TODO: add construction code here,
  84. // Place all significant initialization in InitInstance
  85. }
  86. /////////////////////////////////////////////////////////////////////////////
  87. // The one and only CBmpModuleApp object
  88. CBmpModuleApp theApp;
  89. // 接口函数声明 — 第一层,唯一与外界联系的接口
  90. int WINAPI AccessBMPModule(INFOSTR *pInfo)
  91. {
  92. // 这个函数可以不作修改的使用,除非你的返回值多于两种。
  93. switch(pInfo->comm)
  94. {
  95. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  96. _fnCMD_GETPROCTYPE(pInfo);
  97. break;
  98. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  99. _fnCMD_GETWRITERS(pInfo);
  100. break;
  101. case CMD_GETWRITERMESS: // 获取作者们的留言
  102. _fnCMD_GETWRITERMESS(pInfo);
  103. break;
  104. case CMD_GETBUILDID: // 获取图像模块内部版本号
  105. _fnCMD_GETBUILDID(pInfo);
  106. break;
  107. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的BMP文件
  108. _fnCMD_IS_VALID_FILE(pInfo);
  109. break;
  110. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  111. _fnCMD_GET_FILE_INFO(pInfo);
  112. break;
  113. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  114. _fnCMD_LOAD_FROM_FILE(pInfo);
  115. break;
  116. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  117. _fnCMD_SAVE_TO_FILE(pInfo);
  118. break;
  119. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  120. _fnCMD_IS_SUPPORT(pInfo);
  121. break;
  122. case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
  123. _fnCMD_RESIZE(pInfo);
  124. break;
  125. default:
  126. pInfo->result = ER_ILLCOMM; // 非法命令
  127. ASSERT(FALSE); // 调用者的程序设计有问题 :-)
  128. break;
  129. }
  130. // 执行命令成功返回1, 失败返回0
  131. return (pInfo->result==ER_SUCCESS)? 1:0;
  132. }
  133. // 命令解释函数 — 第二层解释函数
  134. //********************************************************************//
  135. // 操作命令解释函数---解释:CMD_IS_SUPPORT命令
  136. // 查询某个命令是否被支持
  137. void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
  138. {
  139. // 这个函数是为客户程序查询时使用,如果你实现了对某个命令的
  140. // 解释,可修改相应的case中的设置,使其返回ER_SUCCESS,这就
  141. // 表示你的模块已经支持该命令了。同时,现在的这个文件中已包
  142. // 含了对前四个命令的解释,你只需向还未支持的命令函数中添加
  143. // 代码即可。
  144. ASSERT(pInfo->result == ER_EMPTY);
  145. switch(pInfo->annexdata.cmAnnData)  
  146. {
  147. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  148. pInfo->result = ER_SUCCESS;
  149. break;
  150. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  151. pInfo->result = ER_SUCCESS;
  152. break;
  153. case CMD_GETWRITERMESS: // 获取作者们的留言
  154. pInfo->result = ER_SUCCESS;
  155. break;
  156. case CMD_GETBUILDID: // 获取图像模块内部版本号
  157. pInfo->result = ER_SUCCESS;
  158. break;
  159. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  160. pInfo->result = ER_SUCCESS;
  161. break;
  162. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  163. pInfo->result = ER_SUCCESS;
  164. break;
  165. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  166. pInfo->result = ER_SUCCESS;
  167. break;
  168. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  169. pInfo->result = ER_SUCCESS;
  170. break;
  171. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  172. pInfo->result = ER_SUCCESS;
  173. break;
  174. case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
  175. pInfo->result = ER_NOTSUPPORT;
  176. break;
  177. default:
  178. pInfo->result = ER_NOTSUPPORT;
  179. break;
  180. }
  181. }
  182. // 操作命令解释函数---解释:CMD_GETPROCTYPE命令
  183. // 获取本模块能处理的图像类型,如:BMP,PCX等等
  184. void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
  185. {
  186. // 这是预定义的函数代码,你可以不必修改的使用。
  187. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  188. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  189. ASSERT(pInfo->result == ER_EMPTY);
  190. // 复制能处理的类型字符串
  191. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType, 
  192. sizeof(ModuleProcessImgType));
  193. pInfo->result = ER_SUCCESS;
  194. }
  195. // 操作命令解释函数---解释:CMD_GETWRITER命令
  196. // 获取本模块的作者列表,多人时用逗号分隔
  197. void _fnCMD_GETWRITERS(INFOSTR *pInfo)
  198. {
  199. // 这是预定义的函数代码,你可以不必修改的使用。
  200. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  201. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  202. ASSERT(pInfo->result == ER_EMPTY);
  203. // 复制开发者名单串
  204. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList, 
  205. sizeof(WriterList));
  206. pInfo->result = ER_SUCCESS;
  207. }
  208. // 操作命令解释函数---解释:CMD_GETWRITERMESS命令
  209. // 获取作者们的留言
  210. void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
  211. {
  212. // 这是预定义的函数代码,你可以不必修改的使用。
  213. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  214. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  215. ASSERT(pInfo->result == ER_EMPTY);
  216. // 复制开发者们的留言字符串
  217. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess, 
  218. sizeof(WriterMess));
  219. pInfo->result = ER_SUCCESS;
  220. }
  221. // 操作命令解释函数---解释:CMD_GETBUILDID命令
  222. // 获取图像模块内部版本号
  223. void _fnCMD_GETBUILDID(INFOSTR *pInfo)
  224. {
  225. // 这是预定义的函数代码,你可以不必修改的使用。
  226. // 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
  227. ASSERT(pInfo->annexdata.dwAnnData == 0);
  228. ASSERT(pInfo->result == ER_EMPTY);
  229. // 填写内部版本号码
  230. pInfo->annexdata.dwAnnData = MODULE_BUILDID;
  231. pInfo->result = ER_SUCCESS;
  232. }
  233. // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
  234. // 判断指定文件是否是有效的BMP文件
  235. void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
  236. {
  237. CFile file;
  238. BITMAPFILEHEADER bmfHeader;
  239. BITMAPINFOHEADER bmiHeader;
  240. DWORD dwSize;
  241. UINT uRet, uRet2;
  242. ASSERT(pInfo);
  243. // 检验入口参数是否符合接口定义
  244. ASSERT(pInfo->result == ER_EMPTY);
  245. ASSERT(pInfo->annexdata.iAnnData == 0);
  246. ASSERT(::strlen(pInfo->filename));
  247. ASSERT(pInfo->state == PKST_NOTVER);
  248. // 设初值
  249. pInfo->result = ER_SUCCESS;
  250. pInfo->annexdata.iAnnData = 0;
  251. // 先判断指定的文件是否存在
  252. if (!IsFileExist(pInfo->filename))
  253. pInfo->result = ER_COMMINFOERR;
  254. else
  255. {
  256. // 打开指定文件
  257. if (!file.Open(pInfo->filename, CFile::modeRead))
  258. {
  259. pInfo->result = ER_FILERWERR; // 打开文件时出错
  260. return;
  261. }
  262. // 获取BMP文件的长度(以字节为单位)
  263. dwSize = file.GetLength();
  264. // 用长度判断
  265. if (dwSize < (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
  266. {
  267. // 这不是一个BMP文件,BMP文件的长度起码大于文件头
  268. // 加信息头结构的长度
  269. file.Close();
  270. return;
  271. }
  272. // 读取BMP的文件头及信息头结构,并检查它们的有效性
  273. file.SeekToBegin();
  274. uRet  = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
  275. uRet2 = file.Read((LPSTR)&bmiHeader, sizeof(BITMAPINFOHEADER));
  276. if ((uRet != sizeof(BITMAPFILEHEADER))||(uRet2 != sizeof(BITMAPINFOHEADER)))
  277. {
  278. pInfo->result = ER_FILERWERR; // 读文件时出错
  279. file.Close();
  280. return;
  281. }
  282. // 判断文件头部的位图标志(‘BM’)
  283. if (bmfHeader.bfType != DIB_HEADER_MARKER)
  284. {
  285. file.Close();
  286. return;
  287. }
  288. // 判断信息结构的尺寸
  289. switch(bmiHeader.biSize)
  290. {
  291. case sizeof(BITMAPINFOHEADER):
  292. break;
  293. default:
  294. //case sizeof(BITMAPCOREHEADER): // 不支持OS/2格式的位图
  295. //case sizeof(BITMAPV5HEADER): // 不支持NT5以上系统产生的位图
  296. //case sizeof(BITMAPV4HEADER): // 不支持Windows4.0系统产生的位图,以后支持
  297. file.Close();
  298. return;
  299. }
  300. // 检验位数据偏移地址
  301. if ((bmfHeader.bfOffBits > dwSize)||
  302. (bmfHeader.bfOffBits < (bmiHeader.biSize+sizeof(BITMAPFILEHEADER))))
  303. {
  304. file.Close();
  305. return;
  306. }
  307. // 到此,大致可以表明该文件是一个有效的BMP文件,iAnnData变量设为1
  308. pInfo->annexdata.iAnnData = 1;
  309. pInfo->state = PKST_PASSVER; // 表示通过校验
  310. file.Close();
  311. }
  312. }
  313. // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
  314. // 获取指定文件的信息
  315. void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
  316. {
  317. CFile file;
  318. CFileStatus status;
  319. LPBITMAPINFO pDIB;
  320. BITMAPFILEHEADER bmfHeader;
  321. UINT uRet, uDibInfoSize;
  322. // 检验入口参数是否符合接口定义
  323. ASSERT(pInfo->result == ER_EMPTY);
  324. ASSERT(::strlen(pInfo->filename));
  325. // 此时,该文件必需是一个已存在的、并且是有效的BMP文件
  326. ASSERT(pInfo->state == PKST_PASSVER);
  327. // 客户模块必需要先将imginfo清空为0
  328. ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
  329. // 打开指定文件
  330. if (!file.Open(pInfo->filename, CFile::modeRead))
  331. {
  332. pInfo->result = ER_FILERWERR;
  333. return;
  334. }
  335. // 读取BMP的文件头结构
  336. file.SeekToBegin();
  337. uRet  = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
  338. if (uRet != sizeof(BITMAPFILEHEADER))
  339. {
  340. file.Close();
  341. pInfo->result = ER_FILERWERR;
  342. return;
  343. }
  344. uDibInfoSize = bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
  345. // 分配内存,用于存放信息头及颜色表(如果有)
  346. pDIB = (LPBITMAPINFO)::GlobalAlloc(GPTR, uDibInfoSize);
  347. if (!pDIB)
  348. {
  349. file.Close();
  350. pInfo->result = ER_MEMORYERR;
  351. return;
  352. }
  353. // 读取图像信息数据
  354. file.Seek((LONG)sizeof(BITMAPFILEHEADER), CFile::begin);
  355. uRet = file.Read((void *)pDIB, uDibInfoSize);
  356. if (uRet != uDibInfoSize)
  357. {
  358. ::GlobalFree((void*)pDIB);
  359. file.Close();
  360. pInfo->result = ER_FILERWERR;
  361. return;
  362. }
  363. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  364. // 获取文件的长度、图像的宽度、高度等信息
  365. lpImgInfoStr->imgtype = IMT_RESSTATIC;
  366. lpImgInfoStr->imgformat = IMF_BMP;
  367. lpImgInfoStr->filesize = file.GetLength();
  368. lpImgInfoStr->width = pDIB->bmiHeader.biWidth;
  369. // 图像的高度值有时可能是负值,所以使用了abs()函数
  370. lpImgInfoStr->height = (DWORD)::abs(pDIB->bmiHeader.biHeight);
  371. lpImgInfoStr->bitcount = (DWORD)pDIB->bmiHeader.biBitCount;
  372. switch(pDIB->bmiHeader.biCompression)
  373. {
  374. case BI_RGB: //0L
  375. lpImgInfoStr->compression = ICS_RGB; break;
  376. case BI_RLE8: //1L
  377. lpImgInfoStr->compression = ICS_RLE8; break;
  378. case BI_RLE4: //2L
  379. lpImgInfoStr->compression = ICS_RLE4; break;
  380. case BI_BITFIELDS://3L
  381. lpImgInfoStr->compression = ICS_BITFIELDS; break;
  382. default:
  383. //case BI_PNG: // 以后的版本将支持这两种位格式
  384. //case BI_JPEG:
  385. ASSERT(FALSE);
  386. }
  387. // 每一图像行所占的字节数(DWORD对齐,并且只对非压缩位图有效)
  388. lpImgInfoStr->linesize = DIBSCANLINE_WIDTHBYTES(pDIB->bmiHeader.biWidth*pDIB->bmiHeader.biBitCount);
  389. lpImgInfoStr->imgnumbers = 1; // BMP文件中只有一个图像
  390. lpImgInfoStr->imgchang = 0; // 表示可以被编辑
  391. // 获取文件最后的修改日期(月在高字节,日在低字节)
  392. file.GetStatus(status);
  393. lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
  394. lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
  395. lpImgInfoStr->monday <<= 8;
  396. lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
  397. // 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
  398. lpImgInfoStr->time = status.m_mtime.GetHour();
  399. lpImgInfoStr->time <<= 8;
  400. lpImgInfoStr->time |= status.m_mtime.GetMinute();
  401. lpImgInfoStr->time <<= 8;
  402. lpImgInfoStr->time |= status.m_mtime.GetSecond();
  403. lpImgInfoStr->time &= 0xffffff;
  404. ::GlobalFree((void*)pDIB);
  405. file.Close();
  406. // 设置出口数据
  407. pInfo->state = PKST_PASSINFO;
  408. pInfo->result = ER_SUCCESS;
  409. }
  410. // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
  411. // 从指定图像文件中读取数据
  412. void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
  413. {
  414. // 检验入口参数是否符合接口定义
  415. ASSERT(pInfo->result == ER_EMPTY);
  416. ASSERT(::strlen(pInfo->filename));
  417. // 此时,该文件必需是一个已存在的、有效的BMP文件,并且数据包中
  418. // 含有该文件的信息(imginfo结构中)
  419. ASSERT(pInfo->state == PKST_PASSINFO);
  420. ASSERT(pInfo->imginfo.imgformat == IMF_BMP);
  421. ASSERT(pInfo->pImgInfo == NULL);
  422. // 必需设置标准图像格式信息
  423. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  424. ASSERT(pInfo->pLineAddr != NULL);
  425. ASSERT(pInfo->_pbdata != NULL);
  426. CFile file;
  427. // 以图像的高度值作为进度总值
  428. RWPROGRESSSIZE = (int)pInfo->imginfo.height;
  429. if (pInfo->fpProgress)
  430. {
  431. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  432. {
  433. // 如果进度函数返回1,则说明用户想中断操作,返回。
  434. pInfo->result = ER_USERBREAK;
  435. return;
  436. }
  437. }
  438. // 打开指定文件
  439. if (!file.Open(pInfo->filename, CFile::modeRead))
  440. {
  441. pInfo->result = ER_FILERWERR;
  442. return;
  443. }
  444. file.Seek(0, CFile::begin);
  445. if (pInfo->fpProgress)
  446. {
  447. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  448. {
  449. // 如果进度函数返回1,则说明用户想中断操作,返回。
  450. file.Close();
  451. pInfo->result = ER_USERBREAK;
  452. return;
  453. }
  454. }
  455. // 读取并转换图像到数据包中
  456. if (_Read(file, pInfo) == 0)
  457. {
  458. // 成功
  459. pInfo->state = PKST_INFOANDBITS;
  460. pInfo->modify = 0;
  461. pInfo->result = ER_SUCCESS;
  462. }
  463. file.Close();
  464. if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
  465. (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
  466. }
  467. // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
  468. // 将数据保存到指定文件中
  469. // pInfo所指向的数据包中,annexdata.siAnnData[]变量的含意解释:
  470. // [0] — 位深度,可以是1、4、8、16(555)、24、32(888)这六个值
  471. // 中的一个,不能是其他值。另:不能存储为RLE格式
  472. // [1] — 是否使用原始调色板。0 — 表示使用,1 — 表示使用当前
  473. // 计算机缺省调色板
  474. void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
  475. {
  476. // 检验入口参数是否符合接口定义
  477. ASSERT(pInfo->result == ER_EMPTY);
  478. // 该文件名可以是一个已存在的文件,也可以是不存在的文件(本函数将创建)。
  479. ASSERT(::strlen(pInfo->filename));
  480. ASSERT(pInfo->state == PKST_INFOANDBITS);
  481. // 必需设置标准图像格式信息
  482. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  483. ASSERT(pInfo->pLineAddr != NULL);
  484. ASSERT(pInfo->_pbdata != NULL);
  485. CFile file;
  486. CFileStatus status;
  487. BITMAPFILEHEADER bmf;
  488. int uDibInfoSize;
  489. LPBITMAPINFO pDIB;
  490. int uRet;
  491. // 此时imginfo中的数据可能与sDIBInfo不一样,以sDIBInfo为准
  492. RWPROGRESSSIZE = (int)::abs(pInfo->sDIBInfo.bmi.biHeight);
  493. if (pInfo->fpProgress)
  494. {
  495. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  496. { // 如果进度函数返回1,则说明用户想中断操作,返回。
  497. pInfo->result = ER_USERBREAK;
  498. return;
  499. }
  500. }
  501. // 打开指定文件(如果不存在就创建,如果存在,不截断为0长度),不
  502. // 允许其它进程写该文件
  503. if (!file.Open(pInfo->filename, CFile::modeCreate|CFile::modeNoTruncate|
  504. CFile::modeReadWrite|CFile::shareDenyWrite))
  505. {
  506. pInfo->result = ER_FILERWERR;
  507. return;
  508. }
  509. file.Seek(0, CFile::begin);
  510. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  511. // 读取并转换图像到数据包中
  512. if (_Save(file, pInfo) == 0)
  513. {
  514. file.Flush(); // 刷新文件的内容、尺寸、最后修改日期
  515. file.Seek(0, CFile::begin);
  516. if (file.Read((void*)&bmf, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
  517. {
  518. file.Close();
  519. pInfo->result = ER_FILERWERR;
  520. return;
  521. }
  522. uDibInfoSize = bmf.bfOffBits-sizeof(BITMAPFILEHEADER);
  523. // 分配内存,用于存放信息头及颜色表(如果有)
  524. pDIB = (LPBITMAPINFO)::GlobalAlloc(GPTR, uDibInfoSize);
  525. if (!pDIB)
  526. {
  527. file.Close();
  528. pInfo->result = ER_MEMORYERR;
  529. return;
  530. }
  531. // 读取图像信息数据
  532. file.Seek((LONG)sizeof(BITMAPFILEHEADER), CFile::begin);
  533. uRet = file.Read((void *)pDIB, uDibInfoSize);
  534. if (uRet != uDibInfoSize)
  535. {
  536. ::GlobalFree((void*)pDIB);
  537. file.Close();
  538. pInfo->result = ER_FILERWERR;
  539. return;
  540. }
  541. if (pInfo->pImgInfo) // 释放图像的原始信息块
  542. ::GlobalFree((void*)pInfo->pImgInfo);
  543. pInfo->pImgInfo = (void*)pDIB; // 设置原始信息块
  544. // 获取文件的长度、图像的宽度、高度等信息
  545. lpImgInfoStr->imgtype = IMT_RESSTATIC;
  546. lpImgInfoStr->imgformat = IMF_BMP;
  547. lpImgInfoStr->filesize = file.GetLength();
  548. lpImgInfoStr->width = pInfo->sDIBInfo.bmi.biWidth;
  549. // 图像的高度值有时可能是负值,所以使用了abs()函数
  550. lpImgInfoStr->height = (DWORD)::abs(pInfo->sDIBInfo.bmi.biHeight);
  551. lpImgInfoStr->bitcount = (DWORD)pInfo->annexdata.siAnnData[0]; // 新的位深度值
  552. lpImgInfoStr->compression = ICS_RGB; // 写函数当前只支持BI_RGB格式
  553. // 每一图像行所占的字节数(DWORD对齐,并且只对非压缩位图有效)
  554. lpImgInfoStr->linesize = DIBSCANLINE_WIDTHBYTES(lpImgInfoStr->width*lpImgInfoStr->bitcount);
  555. lpImgInfoStr->imgnumbers = 1; // BMP文件中只有一个图像
  556. lpImgInfoStr->imgchang = 0; // 表示可以被编辑
  557. // 获取文件最后的修改日期(月在高字节,日在低字节)
  558. file.GetStatus(status);
  559. lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
  560. lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
  561. lpImgInfoStr->monday <<= 8;
  562. lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
  563. // 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
  564. lpImgInfoStr->time = status.m_mtime.GetHour();
  565. lpImgInfoStr->time <<= 8;
  566. lpImgInfoStr->time |= status.m_mtime.GetMinute();
  567. lpImgInfoStr->time <<= 8;
  568. lpImgInfoStr->time |= status.m_mtime.GetSecond();
  569. lpImgInfoStr->time &= 0xffffff;
  570. // 成功
  571. pInfo->result = ER_SUCCESS;
  572. }
  573. file.Close();
  574. if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
  575. (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
  576. }
  577. // 操作命令解释函数---解释:CMD_RESIZE命令
  578. // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
  579. void _fnCMD_RESIZE(INFOSTR *pInfo)
  580. {
  581. // 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像,
  582. // 比如WMF、EMF之类。
  583. // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
  584. // ----------------------------------------------------------------->
  585. pInfo->result = ER_NOTSUPPORT;
  586. }
  587. /*************************************************************************
  588.  *
  589.  * IsFileExist()
  590.  * 
  591.  * 参数说明:
  592.  *
  593.  * char *lpFileName - 待判断的文件路径和名称(文件名)
  594.  *
  595.  * 返回值:
  596.  *
  597.  * BOOL - 如果指定的文件存在返回TRUE,否则返回FALSE。
  598.  * 
  599.  * 描述:
  600.  *
  601.  * 判断指定的文件是否存在
  602.  * 
  603.  * 该文件必需可以被读和写
  604.  *
  605.  ************************************************************************/
  606. BOOL IsFileExist(char *lpFileName)
  607. {
  608. CFile file;
  609. BOOL bExist = FALSE; // 文件存在是TRUE,不存在是FALSE
  610. CFileException e;
  611. // 确定指定的文件是否存在
  612. if (file.Open(lpFileName, CFile::modeReadWrite|CFile::shareDenyNone, &e))
  613. {
  614. bExist = TRUE;
  615. file.Close();
  616. }
  617. else
  618. {
  619. // 可能有其他程序正在处理此文件
  620. switch(e.m_cause)
  621. {
  622. case CFileException::tooManyOpenFiles:
  623. case CFileException::accessDenied:
  624. case CFileException::sharingViolation:
  625. case CFileException::lockViolation:
  626. return TRUE;
  627. case CFileException::fileNotFound:
  628. case CFileException::badPath:
  629. case CFileException::invalidFile:
  630. case CFileException::hardIO:
  631. default:
  632. return FALSE;
  633. }
  634. }
  635. return bExist;
  636. }
  637. // 将指定文件读入目标缓冲区
  638. int _Read(CFile& file, LPINFOSTR pInfo)
  639. {
  640. RGBQUAD *pPalette;
  641. int imgorg;
  642. BITMAPFILEHEADER bmfHeader;
  643. BITMAPINFOHEADER bmiHeader;
  644. PBYTE pBits;
  645. PBYTE pImgInfo;
  646. DWORD dwSize, dwRet;
  647. UINT uRet;
  648. /* 读取DIB的文件头结构 */
  649. file.SeekToBegin();
  650. uRet   = file.Read((LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
  651. uRet  += file.Read((LPSTR)&bmiHeader, sizeof(BITMAPINFOHEADER));
  652. if (uRet != (sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
  653. {
  654. pInfo->result = ER_FILERWERR;
  655. return 1; // 读文件时出错
  656. }
  657. // pImgInfo将包含位图信息结构及调色板信息(如果有的话)
  658. pImgInfo = (PBYTE)::GlobalAlloc(GPTR, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER));
  659. if (pImgInfo == NULL)
  660. {
  661. pInfo->result = ER_MEMORYERR;
  662. return 2; // 内存不足
  663. }
  664. // 读取位图文件的原始信息
  665. file.Seek(sizeof(BITMAPFILEHEADER), CFile::begin);
  666. uRet = file.Read((void*)pImgInfo, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER));
  667. if (uRet != (bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
  668. {
  669. ::GlobalFree(pImgInfo);
  670. pInfo->result = ER_FILERWERR;
  671. return 1;
  672. }
  673. // 正常情况下,高度值不会是负值或0
  674. ASSERT(RWPROGRESSSIZE > 0);
  675. if (pInfo->fpProgress)
  676. {
  677. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  678. {
  679. // 如果进度函数返回1,则说明用户想中断操作,返回。
  680. ::GlobalFree(pImgInfo);
  681. pInfo->result = ER_USERBREAK;
  682. return 4; // 用户中断操作
  683. }
  684. }
  685. // 获取文件长度
  686. dwSize = file.GetLength();
  687. // 分配内存,用于存放位数据
  688. pBits = (PBYTE)::GlobalAlloc(GPTR, dwSize-bmfHeader.bfOffBits);
  689. if (!pBits)
  690. {
  691. ::GlobalFree(pImgInfo);
  692. pInfo->result = ER_MEMORYERR;
  693. return 2; // 内存不足
  694. }
  695. // 读取位数据
  696. file.Seek(bmfHeader.bfOffBits, CFile::begin);
  697. dwRet = file.ReadHuge((void*)pBits, (dwSize-bmfHeader.bfOffBits));
  698. if (dwRet != (dwSize-bmfHeader.bfOffBits))
  699. {
  700. ::GlobalFree(pImgInfo);
  701. ::GlobalFree(pBits);
  702. pInfo->result = ER_FILERWERR;
  703. return 1;
  704. }
  705. if (pInfo->fpProgress)
  706. {
  707. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  708. {
  709. // 如果进度函数返回1,则说明用户想中断操作,返回。
  710. ::GlobalFree(pImgInfo);
  711. ::GlobalFree(pBits);
  712. pInfo->result = ER_USERBREAK;
  713. return 4; // 用户中断操作
  714. }
  715. }
  716. // 下面的读取函数需要该指针,所以在此处赋值
  717. pInfo->pImgInfo = pImgInfo;
  718. pPalette = (RGBQUAD*)(pImgInfo+bmiHeader.biSize);
  719. imgorg = (bmiHeader.biHeight > 0) ? 0:1; // 0-为倒向位图  1-为正向
  720. int result = 0; // 接收各函数的返回值
  721. // 根据位图文件的位深度的不同而调用相应的读取函数
  722. switch(_get_souformat((LPBITMAPINFO)pImgInfo))
  723. {
  724. case SF_1:
  725. result = _from_1_read(pInfo, pBits, imgorg, pPalette);
  726. break;
  727. case SF_4:
  728. result = _from_4_read(pInfo, pBits, imgorg, pPalette);
  729. break;
  730. case SF_4_RLE:
  731. result = _from_4_RLE_read(pInfo, pBits, imgorg, pPalette);
  732. break;
  733. case SF_8:
  734. result = _from_8_read(pInfo, pBits, imgorg, pPalette);
  735. break;
  736. case SF_8_RLE:
  737. result = _from_8_RLE_read(pInfo, pBits, imgorg, pPalette);
  738. break;
  739. case SF_16_555:
  740. result = _from_16_555_read(pInfo, pBits, imgorg);
  741. break;
  742. case SF_16_565:
  743. result = _from_16_565_read(pInfo, pBits, imgorg);
  744. break;
  745. case SF_24:
  746. result = _from_24_read(pInfo, pBits, imgorg);
  747. break;
  748. case SF_32:
  749. result = _from_32_read(pInfo, pBits, imgorg);
  750. break;
  751. default:
  752. ::GlobalFree(pImgInfo);
  753. ::GlobalFree(pBits);
  754. pInfo->pImgInfo = NULL;
  755. pInfo->result = ER_SYSERR;
  756. return 3; // 图像文件格式异常
  757. }
  758. // 释放从文件中读取的位数据(此数据已被转换并保存到了数据包中)
  759. ::GlobalFree(pBits);
  760. if (result == 0) // 执行成功
  761. {
  762. pInfo->result = ER_SUCCESS;
  763. }
  764. else
  765. {
  766. ::GlobalFree(pImgInfo);
  767. pInfo->pImgInfo = NULL;
  768. return 4; // 执行过程中产生的错误,详见pInfo->result
  769. }
  770. return 0;
  771. }
  772. // 将1位(即单色)位图转换为指定的标准格式位图
  773. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  774. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  775. int _from_1_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg, RGBQUAD *lpPalette)
  776. {
  777. ASSERT(pInfo);
  778. ASSERT(lpPalette); // 单色位图应有两个调色板项
  779. ASSERT(pInfo->state >= PKST_PASSINFO);
  780. ASSERT(lpSou);
  781. int sImgOrg = imgorg; // 源图像扫描行次序的标志:0-为倒向 1-为正向
  782. // 源图像的次序由调用者传入
  783. int imgheight = pInfo->imginfo.height; // 图像的高度
  784. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  785. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  786. int heigCount, widthCount, i, j, isou;
  787. ASSERT(pInfo->pImgInfo);
  788. int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
  789. PBYTE pCurPixAddr;
  790. BYTE pix; // 当前8个像素
  791. palnum = (palnum == 0) ? 2:palnum; // 计算调色板项的实际个数
  792. ASSERT(palnum <= 2);
  793. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  794. {
  795. case DF_16_555:
  796. {
  797. // 以555位格式的调色板数据
  798. WORD descol555_0 = 0;
  799. WORD descol555_1 = 0;
  800. if (palnum > 0)
  801. descol555_0 = _cnv_rgb_to_555(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
  802. if (palnum > 1)
  803. descol555_1 = _cnv_rgb_to_555(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
  804. WORD *pDesPixAddr555;
  805. if (sImgOrg == 0) // 源图是倒向位图
  806. {
  807. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  808. {
  809. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  810. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  811. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  812. {
  813. pix = *pCurPixAddr++;
  814. if ((imgwidth-widthCount)<8) // 结尾判断
  815. j = imgwidth-widthCount;
  816. else
  817. j = 8;
  818. for (i=0;i<j;i++)
  819. {
  820. // 最高位代表最左面的像素
  821. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  822. {
  823. *pDesPixAddr555++ = descol555_1;
  824. }
  825. else
  826. {
  827. *pDesPixAddr555++ = descol555_0;
  828. }
  829. }
  830. }
  831. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  832. {
  833. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  834. {
  835. // 如果进度函数返回1,则说明用户想中断操作,返回。
  836. pInfo->result = ER_USERBREAK;
  837. return 1; // 用户中断操作
  838. }
  839. }
  840. }
  841. }
  842. else // 正向位图(top-down)
  843. {
  844. for (heigCount=0;heigCount<imgheight;heigCount++)
  845. {
  846. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  847. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  848. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  849. {
  850. pix = *pCurPixAddr++;
  851. if ((imgwidth-widthCount)<8) // 结尾判断
  852. j = imgwidth-widthCount;
  853. else
  854. j = 8;
  855. for (i=0;i<j;i++)
  856. {
  857. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  858. {
  859. *pDesPixAddr555++ = descol555_1;
  860. }
  861. else
  862. {
  863. *pDesPixAddr555++ = descol555_0;
  864. }
  865. }
  866. }
  867. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  868. {
  869. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  870. {
  871. // 如果进度函数返回1,则说明用户想中断操作,返回。
  872. pInfo->result = ER_USERBREAK;
  873. return 1; // 用户中断操作
  874. }
  875. }
  876. }
  877. }
  878. }
  879. break;
  880. case DF_16_565:
  881. {
  882. // 以565位格式的调色板数据
  883. WORD descol565_0 = 0;
  884. WORD descol565_1 = 0;
  885. if (palnum > 0)
  886. descol565_0 = _cnv_rgb_to_565(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
  887. if (palnum > 1)
  888. descol565_1 = _cnv_rgb_to_565(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
  889. WORD *pDesPixAddr565;
  890. if (sImgOrg == 0) // 源图是倒向位图
  891. {
  892. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  893. {
  894. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  895. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  896. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  897. {
  898. pix = *pCurPixAddr++;
  899. if ((imgwidth-widthCount)<8) // 结尾判断
  900. j = imgwidth-widthCount;
  901. else
  902. j = 8;
  903. for (i=0;i<j;i++)
  904. {
  905. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  906. {
  907. *pDesPixAddr565++ = descol565_1;
  908. }
  909. else
  910. {
  911. *pDesPixAddr565++ = descol565_0;
  912. }
  913. }
  914. }
  915. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  916. {
  917. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  918. {
  919. // 如果进度函数返回1,则说明用户想中断操作,返回。
  920. pInfo->result = ER_USERBREAK;
  921. return 1; // 用户中断操作
  922. }
  923. }
  924. }
  925. }
  926. else // 正向位图(top-down)
  927. {
  928. for (heigCount=0;heigCount<imgheight;heigCount++)
  929. {
  930. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  931. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  932. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  933. {
  934. pix = *pCurPixAddr++;
  935. if ((imgwidth-widthCount)<8) // 结尾判断
  936. j = imgwidth-widthCount;
  937. else
  938. j = 8;
  939. for (i=0;i<j;i++)
  940. {
  941. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  942. {
  943. *pDesPixAddr565++ = descol565_1;
  944. }
  945. else
  946. {
  947. *pDesPixAddr565++ = descol565_0;
  948. }
  949. }
  950. }
  951. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  952. {
  953. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  954. {
  955. // 如果进度函数返回1,则说明用户想中断操作,返回。
  956. pInfo->result = ER_USERBREAK;
  957. return 1; // 用户中断操作
  958. }
  959. }
  960. }
  961. }
  962. }
  963. break;
  964. case DF_24:
  965. {
  966. // 24位格式的调色板数据
  967. BYTE red0, red1, green0, green1, blue0, blue1;
  968. if (palnum > 0)
  969. {
  970. red0 = lpPalette[0].rgbRed;
  971. green0 = lpPalette[0].rgbGreen;
  972. blue0 = lpPalette[0].rgbBlue;
  973. }
  974. if (palnum > 1)
  975. {
  976. red1 = lpPalette[1].rgbRed;
  977. green1 = lpPalette[1].rgbGreen;
  978. blue1 = lpPalette[1].rgbBlue;
  979. }
  980. PBYTE pDesPixAddr24;
  981. if (sImgOrg == 0) // 源图是倒向位图
  982. {
  983. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  984. {
  985. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  986. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  987. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  988. {
  989. pix = *pCurPixAddr++;
  990. if ((imgwidth-widthCount)<8) // 结尾判断
  991. j = imgwidth-widthCount;
  992. else
  993. j = 8;
  994. for (i=0;i<j;i++)
  995. {
  996. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  997. {
  998. *pDesPixAddr24++ = blue1;
  999. *pDesPixAddr24++ = green1;
  1000. *pDesPixAddr24++ = red1;
  1001. }
  1002. else
  1003. {
  1004. *pDesPixAddr24++ = blue0;
  1005. *pDesPixAddr24++ = green0;
  1006. *pDesPixAddr24++ = red0;
  1007. }
  1008. }
  1009. }
  1010. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1011. {
  1012. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1013. {
  1014. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1015. pInfo->result = ER_USERBREAK;
  1016. return 1; // 用户中断操作
  1017. }
  1018. }
  1019. }
  1020. }
  1021. else // 正向位图(top-down)
  1022. {
  1023. for (heigCount=0;heigCount<imgheight;heigCount++)
  1024. {
  1025. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1026. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1027. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  1028. {
  1029. pix = *pCurPixAddr++;
  1030. if ((imgwidth-widthCount)<8) // 结尾判断
  1031. j = imgwidth-widthCount;
  1032. else
  1033. j = 8;
  1034. for (i=0;i<j;i++)
  1035. {
  1036. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  1037. {
  1038. *pDesPixAddr24++ = blue1;
  1039. *pDesPixAddr24++ = green1;
  1040. *pDesPixAddr24++ = red1;
  1041. }
  1042. else
  1043. {
  1044. *pDesPixAddr24++ = blue0;
  1045. *pDesPixAddr24++ = green0;
  1046. *pDesPixAddr24++ = red0;
  1047. }
  1048. }
  1049. }
  1050. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1051. {
  1052. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1053. {
  1054. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1055. pInfo->result = ER_USERBREAK;
  1056. return 1; // 用户中断操作
  1057. }
  1058. }
  1059. }
  1060. }
  1061. }
  1062. break;
  1063. case DF_32:
  1064. {
  1065. // 以888位格式的调色板数据
  1066. DWORD descol888_0 = 0;
  1067. DWORD descol888_1 = 0;
  1068. if (palnum > 0)
  1069. descol888_0 = _cnv_rgb_to_888(lpPalette[0].rgbRed, lpPalette[0].rgbGreen, lpPalette[0].rgbBlue);
  1070. if (palnum > 1)
  1071. descol888_1 = _cnv_rgb_to_888(lpPalette[1].rgbRed, lpPalette[1].rgbGreen, lpPalette[1].rgbBlue);
  1072. DWORD *pDesPixAddr888;
  1073. if (sImgOrg == 0) // 源图是倒向位图
  1074. {
  1075. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1076. {
  1077. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1078. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1079. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  1080. {
  1081. pix = *pCurPixAddr++;
  1082. if ((imgwidth-widthCount)<8) // 结尾判断
  1083. j = imgwidth-widthCount;
  1084. else
  1085. j = 8;
  1086. for (i=0;i<j;i++)
  1087. {
  1088. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  1089. {
  1090. *pDesPixAddr888++ = descol888_1;
  1091. }
  1092. else
  1093. {
  1094. *pDesPixAddr888++ = descol888_0;
  1095. }
  1096. }
  1097. }
  1098. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1099. {
  1100. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1101. {
  1102. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1103. pInfo->result = ER_USERBREAK;
  1104. return 1; // 用户中断操作
  1105. }
  1106. }
  1107. }
  1108. }
  1109. else // 正向位图(top-down)
  1110. {
  1111. for (heigCount=0;heigCount<imgheight;heigCount++)
  1112. {
  1113. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1114. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1115. for (widthCount=0;widthCount<imgwidth;widthCount+=8)
  1116. {
  1117. pix = *pCurPixAddr++;
  1118. if ((imgwidth-widthCount)<8) // 结尾判断
  1119. j = imgwidth-widthCount;
  1120. else
  1121. j = 8;
  1122. for (i=0;i<j;i++)
  1123. {
  1124. if (((BYTE)(0x80>>i))&pix) // 此位被设置
  1125. {
  1126. *pDesPixAddr888++ = descol888_1;
  1127. }
  1128. else
  1129. {
  1130. *pDesPixAddr888++ = descol888_0;
  1131. }
  1132. }
  1133. }
  1134. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1135. {
  1136. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1137. {
  1138. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1139. pInfo->result = ER_USERBREAK;
  1140. return 1; // 用户中断操作
  1141. }
  1142. }
  1143. }
  1144. }
  1145. }
  1146. break;
  1147. case DF_NULL:
  1148. default:
  1149. ASSERT(FALSE);
  1150. pInfo->result = ER_ILLCOMM;
  1151. return -1;
  1152. break;
  1153. }
  1154. return 0;
  1155. }
  1156. // 将4位(即16色)位图转换为指定的标准格式位图
  1157. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  1158. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  1159. int _from_4_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg, RGBQUAD *lpPalette)
  1160. {
  1161. ASSERT(pInfo);
  1162. ASSERT(lpPalette); // 16色位图应有调色板
  1163. ASSERT(pInfo->state >= PKST_PASSINFO);
  1164. ASSERT(lpSou);
  1165. int imgheight = pInfo->imginfo.height; // 图像的高度
  1166. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  1167. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  1168. int heigCount, widthCount, i, j, isou;
  1169. ASSERT(pInfo->pImgInfo);
  1170. int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
  1171. PBYTE pCurPixAddr;
  1172. BYTE pix; // 当前2个像素
  1173. palnum = (palnum == 0) ? 16:palnum; // 计算调色板项的实际个数
  1174. ASSERT(palnum <= 16);
  1175. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  1176. {
  1177. case DF_16_555:
  1178. {
  1179. // 以555位格式的调色板数据
  1180. WORD descol555[16];
  1181. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1182. descol555[i] = _cnv_rgb_to_555(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1183. WORD *pDesPixAddr555;
  1184. if (imgorg == 0) // 源图是倒向位图
  1185. {
  1186. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1187. {
  1188. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1189. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1190. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1191. {
  1192. pix = *pCurPixAddr++;
  1193. if ((imgwidth-widthCount)<2) // 结尾判断
  1194. j = imgwidth-widthCount;
  1195. else
  1196. j = 2;
  1197. for (i=0;i<j;i++)
  1198. {
  1199. if (i==0)
  1200. *pDesPixAddr555++ = descol555[pix>>4];
  1201. else
  1202. *pDesPixAddr555++ = descol555[pix&0xf];
  1203. }
  1204. }
  1205. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1206. {
  1207. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1208. {
  1209. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1210. pInfo->result = ER_USERBREAK;
  1211. return 1; // 用户中断操作
  1212. }
  1213. }
  1214. }
  1215. }
  1216. else // 正向位图(top-down)
  1217. {
  1218. for (heigCount=0;heigCount<imgheight;heigCount++)
  1219. {
  1220. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1221. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1222. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1223. {
  1224. pix = *pCurPixAddr++;
  1225. if ((imgwidth-widthCount)<2) // 结尾判断
  1226. j = imgwidth-widthCount;
  1227. else
  1228. j = 2;
  1229. for (i=0;i<j;i++)
  1230. {
  1231. if (i==0)
  1232. *pDesPixAddr555++ = descol555[pix>>4];
  1233. else
  1234. *pDesPixAddr555++ = descol555[pix&0xf];
  1235. }
  1236. }
  1237. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1238. {
  1239. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1240. {
  1241. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1242. pInfo->result = ER_USERBREAK;
  1243. return 1; // 用户中断操作
  1244. }
  1245. }
  1246. }
  1247. }
  1248. }
  1249. break;
  1250. case DF_16_565:
  1251. {
  1252. // 以565位格式的调色板数据
  1253. WORD descol565[16];
  1254. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1255. descol565[i] = _cnv_rgb_to_565(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1256. WORD *pDesPixAddr565;
  1257. if (imgorg == 0) // 源图是倒向位图
  1258. {
  1259. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1260. {
  1261. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1262. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1263. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1264. {
  1265. pix = *pCurPixAddr++;
  1266. if ((imgwidth-widthCount)<2) // 结尾判断
  1267. j = imgwidth-widthCount;
  1268. else
  1269. j = 2;
  1270. for (i=0;i<j;i++)
  1271. {
  1272. if (i==0)
  1273. *pDesPixAddr565++ = descol565[pix>>4];
  1274. else
  1275. *pDesPixAddr565++ = descol565[pix&0xf];
  1276. }
  1277. }
  1278. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1279. {
  1280. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1281. {
  1282. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1283. pInfo->result = ER_USERBREAK;
  1284. return 1; // 用户中断操作
  1285. }
  1286. }
  1287. }
  1288. }
  1289. else // 正向位图(top-down)
  1290. {
  1291. for (heigCount=0;heigCount<imgheight;heigCount++)
  1292. {
  1293. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1294. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1295. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1296. {
  1297. pix = *pCurPixAddr++;
  1298. if ((imgwidth-widthCount)<2) // 结尾判断
  1299. j = imgwidth-widthCount;
  1300. else
  1301. j = 2;
  1302. for (i=0;i<j;i++)
  1303. {
  1304. if (i==0)
  1305. *pDesPixAddr565++ = descol565[pix>>4];
  1306. else
  1307. *pDesPixAddr565++ = descol565[pix&0xf];
  1308. }
  1309. }
  1310. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1311. {
  1312. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1313. {
  1314. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1315. pInfo->result = ER_USERBREAK;
  1316. return 1; // 用户中断操作
  1317. }
  1318. }
  1319. }
  1320. }
  1321. }
  1322. break;
  1323. case DF_24:
  1324. {
  1325. int index24_0, index24_1;
  1326. PBYTE pDesPixAddr24;
  1327. if (imgorg  == 0) // 源图是倒向位图
  1328. {
  1329. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1330. {
  1331. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1332. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1333. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1334. {
  1335. pix = *pCurPixAddr++;
  1336. if ((imgwidth-widthCount)<2) // 结尾判断
  1337. j = imgwidth-widthCount;
  1338. else
  1339. j = 2;
  1340. index24_0 = (int)(pix>>4);
  1341. index24_1 = (int)(pix&0xf);
  1342. for (i=0;i<j;i++)
  1343. {
  1344. if (i==0)
  1345. {
  1346. *pDesPixAddr24++ = lpPalette[index24_0].rgbBlue;
  1347. *pDesPixAddr24++ = lpPalette[index24_0].rgbGreen;
  1348. *pDesPixAddr24++ = lpPalette[index24_0].rgbRed;
  1349. }
  1350. else
  1351. {
  1352. *pDesPixAddr24++ = lpPalette[index24_1].rgbBlue;
  1353. *pDesPixAddr24++ = lpPalette[index24_1].rgbGreen;
  1354. *pDesPixAddr24++ = lpPalette[index24_1].rgbRed;
  1355. }
  1356. }
  1357. }
  1358. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1359. {
  1360. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1361. {
  1362. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1363. pInfo->result = ER_USERBREAK;
  1364. return 1; // 用户中断操作
  1365. }
  1366. }
  1367. }
  1368. }
  1369. else // 正向位图(top-down)
  1370. {
  1371. for (heigCount=0;heigCount<imgheight;heigCount++)
  1372. {
  1373. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1374. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1375. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1376. {
  1377. pix = *pCurPixAddr++;
  1378. if ((imgwidth-widthCount)<2) // 结尾判断
  1379. j = imgwidth-widthCount;
  1380. else
  1381. j = 2;
  1382. index24_0 = (int)(pix>>4);
  1383. index24_1 = (int)(pix&0xf);
  1384. for (i=0;i<j;i++)
  1385. {
  1386. if (i==0)
  1387. {
  1388. *pDesPixAddr24++ = lpPalette[index24_0].rgbBlue;
  1389. *pDesPixAddr24++ = lpPalette[index24_0].rgbGreen;
  1390. *pDesPixAddr24++ = lpPalette[index24_0].rgbRed;
  1391. }
  1392. else
  1393. {
  1394. *pDesPixAddr24++ = lpPalette[index24_1].rgbBlue;
  1395. *pDesPixAddr24++ = lpPalette[index24_1].rgbGreen;
  1396. *pDesPixAddr24++ = lpPalette[index24_1].rgbRed;
  1397. }
  1398. }
  1399. }
  1400. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1401. {
  1402. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1403. {
  1404. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1405. pInfo->result = ER_USERBREAK;
  1406. return 1; // 用户中断操作
  1407. }
  1408. }
  1409. }
  1410. }
  1411. }
  1412. break;
  1413. case DF_32:
  1414. {
  1415. // 以888位格式的调色板数据
  1416. DWORD descol888[16];
  1417. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1418. descol888[i] = _cnv_rgb_to_888(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1419. DWORD *pDesPixAddr888;
  1420. if (imgorg == 0) // 源图是倒向位图
  1421. {
  1422. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1423. {
  1424. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1425. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1426. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1427. {
  1428. pix = *pCurPixAddr++;
  1429. if ((imgwidth-widthCount)<2) // 结尾判断
  1430. j = imgwidth-widthCount;
  1431. else
  1432. j = 2;
  1433. for (i=0;i<j;i++)
  1434. {
  1435. // 注:在4位位图中,每个字节的高4位代表两个像素
  1436. //     中左面的那个像素,例如某扫描行的第一个像
  1437. //     素是红色,第二个像素是白色,红的索引是A,
  1438. //     白的索引是9,那么就应该写成9A,而不能写成
  1439. //     A9,虽然习惯、逻辑上是那样。
  1440. if (i == 0)
  1441. *pDesPixAddr888++ = descol888[pix>>4];
  1442. else
  1443. *pDesPixAddr888++ = descol888[pix&0xf];
  1444. }
  1445. }
  1446. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1447. {
  1448. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1449. {
  1450. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1451. pInfo->result = ER_USERBREAK;
  1452. return 1; // 用户中断操作
  1453. }
  1454. }
  1455. }
  1456. }
  1457. else // 正向位图(top-down)
  1458. {
  1459. for (heigCount=0;heigCount<imgheight;heigCount++)
  1460. {
  1461. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1462. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1463. for (widthCount=0;widthCount<imgwidth;widthCount+=2)
  1464. {
  1465. pix = *pCurPixAddr++;
  1466. if ((imgwidth-widthCount)<2) // 结尾判断
  1467. j = imgwidth-widthCount;
  1468. else
  1469. j = 2;
  1470. for (i=0;i<j;i++)
  1471. {
  1472. if (i == 0)
  1473. *pDesPixAddr888++ = descol888[pix>>4];
  1474. else
  1475. *pDesPixAddr888++ = descol888[pix&0xf];
  1476. }
  1477. }
  1478. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1479. {
  1480. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1481. {
  1482. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1483. pInfo->result = ER_USERBREAK;
  1484. return 1; // 用户中断操作
  1485. }
  1486. }
  1487. }
  1488. }
  1489. }
  1490. break;
  1491. case DF_NULL:
  1492. default:
  1493. ASSERT(FALSE);
  1494. pInfo->result = ER_ILLCOMM;
  1495. return -1;
  1496. break;
  1497. }
  1498. return 0;
  1499. }
  1500. // 将4位RLE位图转换为指定的标准格式位图
  1501. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  1502. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  1503. int _from_4_RLE_read(LPINFOSTR pInfo, PBYTE lpSouData, int imgorg, RGBQUAD *lpPalette)
  1504. {
  1505. ASSERT(pInfo);
  1506. ASSERT(lpPalette); // 16色位图应有调色板
  1507. ASSERT(pInfo->state >= PKST_PASSINFO);
  1508. ASSERT(lpSouData);
  1509. ASSERT(imgorg == 0); // 压缩位图必需是倒向的
  1510. int imgheight = pInfo->imginfo.height; // 图像的高度
  1511. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  1512. PBYTE lpSou = lpSouData;
  1513. BYTE pix, pix2; // 当前值
  1514. int result, i;
  1515. BYTE **lppLineAddr = (BYTE**)::GlobalAlloc(GPTR, sizeof(PBYTE)*imgheight);
  1516. if (lppLineAddr == NULL)
  1517. {
  1518. pInfo->result = ER_MEMORYERR;
  1519. return -2; // 内存不足,返回
  1520. }
  1521. int linesize = ((imgwidth*4+31)/32)*4;
  1522. PBYTE lpDes = (PBYTE)::GlobalAlloc(GPTR, linesize*imgheight);
  1523. if (lpDes == NULL)
  1524. {
  1525. ::GlobalFree(lppLineAddr);
  1526. pInfo->result = ER_MEMORYERR;
  1527. return -2; // 内存不足,返回
  1528. }
  1529. // 初始化行地址数组
  1530. for (i=0;i<imgheight;i++)
  1531. lppLineAddr[i] = (PBYTE)(lpDes+linesize*i);
  1532. BOOL bEOF = FALSE; // 图像结尾标志
  1533. int  line = 0; // 当前行
  1534. _write2buff4RLE(0, 0, 0, lppLineAddr[line]); // 初始化写函数
  1535. // 先将RLE的数据解压成标准的BMP数据
  1536. while(!bEOF)
  1537. {
  1538. pix = *lpSou++;
  1539. if (pix == 0) // 绝对方式
  1540. {
  1541. pix2 = *lpSou++;
  1542. switch(pix2)
  1543. {
  1544. case 0: // 行结尾
  1545. line++;
  1546. _write2buff4RLE(2, 0, 0, lppLineAddr[line]);// 指定新的偏移地址
  1547. break;
  1548. case 1: // 图像结尾
  1549. bEOF = TRUE;
  1550. break;
  1551. case 2: // 当前地址偏移
  1552. pix = *lpSou++; pix2 = *lpSou++;
  1553. line += pix2; // 下移pix2行
  1554. _write2buff4RLE(2, pix%2, 0, (PBYTE)(lppLineAddr[line]+(DWORD)pix/2));
  1555. break;
  1556. default: // 不能压缩的像素
  1557. for (i=0;i<pix2/2;i++)
  1558. {
  1559. pix = *(lpSou+i);
  1560. _write2buff4RLE(1, 2, pix, NULL);
  1561. }
  1562. if (pix2%2)
  1563. { // 补充遗漏的单个像素
  1564. pix = *(lpSou+i);
  1565. _write2buff4RLE(1, 1, pix, NULL);
  1566. }
  1567. // (pix2+1)/2是将像素对齐到字节边界上,再加1、除2是对齐到字边界上
  1568. lpSou = (PBYTE)(lpSou + ((pix2+1)/2+1)/2*2); // 字对齐
  1569. break;
  1570. }
  1571. }
  1572. else // 编码方式
  1573. {
  1574. // pix == 相同像素的个数
  1575. pix2 = *lpSou++; // pix2 == 像素
  1576. _write2buff4RLE(1, (int)pix, pix2, NULL);
  1577. }
  1578. }
  1579. _write2buff4RLE(3, 0, 0, NULL); // 结束写函数
  1580. ::GlobalFree(lppLineAddr);
  1581. // 用标准4位转换函数转换到目标格式
  1582. result = _from_4_read(pInfo, lpDes, 0, lpPalette);
  1583. ::GlobalFree(lpDes);
  1584. return result;
  1585. }
  1586. // 将8位(即256色)位图转换为指定的标准格式位图
  1587. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  1588. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  1589. int _from_8_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg, RGBQUAD *lpPalette)
  1590. {
  1591. ASSERT(pInfo);
  1592. ASSERT(lpPalette); // 256色位图应有调色板
  1593. ASSERT(pInfo->state >= PKST_PASSINFO);
  1594. ASSERT(lpSou);
  1595. int imgheight = pInfo->imginfo.height; // 图像的高度
  1596. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  1597. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  1598. ASSERT(pInfo->pImgInfo);
  1599. int palnum = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
  1600. int heigCount, widthCount, i, isou;
  1601. PBYTE pCurPixAddr;
  1602. BYTE pix; // 当前像素
  1603. palnum = (palnum == 0) ? 256:palnum; // 计算调色板项的实际个数
  1604. ASSERT(palnum <= 256);
  1605. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  1606. {
  1607. case DF_16_555:
  1608. {
  1609. // 以555位格式的调色板数据
  1610. WORD descol555[256];
  1611. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1612. descol555[i] = _cnv_rgb_to_555(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1613. WORD *pDesPixAddr555;
  1614. if (imgorg == 0) // 源图是倒向位图
  1615. {
  1616. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1617. {
  1618. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1619. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1620. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1621. *pDesPixAddr555++ = descol555[*pCurPixAddr++];
  1622. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1623. {
  1624. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1625. {
  1626. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1627. pInfo->result = ER_USERBREAK;
  1628. return 1; // 用户中断操作
  1629. }
  1630. }
  1631. }
  1632. }
  1633. else // 正向位图(top-down)
  1634. {
  1635. for (heigCount=0;heigCount<imgheight;heigCount++)
  1636. {
  1637. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1638. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1639. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1640. *pDesPixAddr555++ = descol555[*pCurPixAddr++];
  1641. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1642. {
  1643. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1644. {
  1645. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1646. pInfo->result = ER_USERBREAK;
  1647. return 1; // 用户中断操作
  1648. }
  1649. }
  1650. }
  1651. }
  1652. }
  1653. break;
  1654. case DF_16_565:
  1655. {
  1656. // 以565位格式的调色板数据
  1657. WORD descol565[256];
  1658. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1659. descol565[i] = _cnv_rgb_to_565(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1660. WORD *pDesPixAddr565;
  1661. if (imgorg == 0) // 源图是倒向位图
  1662. {
  1663. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1664. {
  1665. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1666. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1667. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1668. *pDesPixAddr565++ = descol565[*pCurPixAddr++];
  1669. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1670. {
  1671. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1672. {
  1673. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1674. pInfo->result = ER_USERBREAK;
  1675. return 1; // 用户中断操作
  1676. }
  1677. }
  1678. }
  1679. }
  1680. else // 正向位图(top-down)
  1681. {
  1682. for (heigCount=0;heigCount<imgheight;heigCount++)
  1683. {
  1684. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1685. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1686. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1687. *pDesPixAddr565++ = descol565[*pCurPixAddr++];
  1688. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1689. {
  1690. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1691. {
  1692. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1693. pInfo->result = ER_USERBREAK;
  1694. return 1; // 用户中断操作
  1695. }
  1696. }
  1697. }
  1698. }
  1699. }
  1700. break;
  1701. case DF_24:
  1702. {
  1703. PBYTE pDesPixAddr24;
  1704. if (imgorg  == 0) // 源图是倒向位图
  1705. {
  1706. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1707. {
  1708. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1709. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1710. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1711. {
  1712. pix = *pCurPixAddr++;
  1713. *pDesPixAddr24++ = lpPalette[pix].rgbBlue;
  1714. *pDesPixAddr24++ = lpPalette[pix].rgbGreen;
  1715. *pDesPixAddr24++ = lpPalette[pix].rgbRed;
  1716. }
  1717. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1718. {
  1719. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1720. {
  1721. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1722. pInfo->result = ER_USERBREAK;
  1723. return 1; // 用户中断操作
  1724. }
  1725. }
  1726. }
  1727. }
  1728. else // 正向位图(top-down)
  1729. {
  1730. for (heigCount=0;heigCount<imgheight;heigCount++)
  1731. {
  1732. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1733. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1734. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1735. {
  1736. pix = *pCurPixAddr++;
  1737. *pDesPixAddr24++ = lpPalette[pix].rgbBlue;
  1738. *pDesPixAddr24++ = lpPalette[pix].rgbGreen;
  1739. *pDesPixAddr24++ = lpPalette[pix].rgbRed;
  1740. }
  1741. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1742. {
  1743. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1744. {
  1745. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1746. pInfo->result = ER_USERBREAK;
  1747. return 1; // 用户中断操作
  1748. }
  1749. }
  1750. }
  1751. }
  1752. }
  1753. break;
  1754. case DF_32:
  1755. {
  1756. // 以888位格式的调色板数据
  1757. DWORD descol888[256];
  1758. for (i=0;i<palnum;i++) // 初始化色素颜色数据
  1759. descol888[i] = _cnv_rgb_to_888(lpPalette[i].rgbRed, lpPalette[i].rgbGreen, lpPalette[i].rgbBlue);
  1760. DWORD *pDesPixAddr888;
  1761. if (imgorg == 0) // 源图是倒向位图
  1762. {
  1763. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1764. {
  1765. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1766. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1767. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1768. *pDesPixAddr888++ = descol888[*pCurPixAddr++];
  1769. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1770. {
  1771. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1772. {
  1773. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1774. pInfo->result = ER_USERBREAK;
  1775. return 1; // 用户中断操作
  1776. }
  1777. }
  1778. }
  1779. }
  1780. else // 正向位图(top-down)
  1781. {
  1782. for (heigCount=0;heigCount<imgheight;heigCount++)
  1783. {
  1784. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1785. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1786. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1787. *pDesPixAddr888++ = descol888[*pCurPixAddr++];
  1788. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1789. {
  1790. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1791. {
  1792. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1793. pInfo->result = ER_USERBREAK;
  1794. return 1; // 用户中断操作
  1795. }
  1796. }
  1797. }
  1798. }
  1799. }
  1800. break;
  1801. case DF_NULL:
  1802. default:
  1803. ASSERT(FALSE);
  1804. pInfo->result = ER_ILLCOMM;
  1805. return -1;
  1806. break;
  1807. }
  1808. return 0;
  1809. }
  1810. // 将8位RLE位图转换为指定的标准格式位图
  1811. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  1812. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  1813. int _from_8_RLE_read(LPINFOSTR pInfo, PBYTE lpSouData, int imgorg, RGBQUAD *lpPalette)
  1814. {
  1815. ASSERT(pInfo);
  1816. ASSERT(lpPalette); // 256色位图应有调色板
  1817. ASSERT(pInfo->state >= PKST_PASSINFO);
  1818. ASSERT(lpSouData);
  1819. ASSERT(imgorg == 0); // 压缩位图必需是倒向的
  1820. int imgheight = pInfo->imginfo.height; // 图像的高度
  1821. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  1822. PBYTE lpSou = lpSouData;
  1823. BYTE pix, pix2; // 当前值
  1824. int result, i;
  1825. BYTE **lppLineAddr = (BYTE**)::GlobalAlloc(GPTR, sizeof(PBYTE)*imgheight);
  1826. if (lppLineAddr == NULL)
  1827. {
  1828. pInfo->result = ER_MEMORYERR;
  1829. return -2; // 内存不足,返回
  1830. }
  1831. int linesize = ((imgwidth+3)/4)*4; // 扫描行尺寸(in byte)
  1832. PBYTE lpDes = (PBYTE)::GlobalAlloc(GPTR, linesize*imgheight);
  1833. if (lpDes == NULL)
  1834. {
  1835. ::GlobalFree(lppLineAddr);
  1836. pInfo->result = ER_MEMORYERR;
  1837. return -2; // 内存不足,返回
  1838. }
  1839. // 初始化行地址数组
  1840. for (i=0;i<imgheight;i++)
  1841. lppLineAddr[i] = (PBYTE)(lpDes+linesize*i);
  1842. BOOL bEOF = FALSE; // 图像结尾标志
  1843. int  line = 0; // 当前行
  1844. _write2buff8RLE(0, 0, 0, lppLineAddr[line]); // 初始化写函数
  1845. while(!bEOF)
  1846. {
  1847. pix = *lpSou++;
  1848. if (pix == 0) // 绝对方式
  1849. {
  1850. pix2 = *lpSou++;
  1851. switch(pix2)
  1852. {
  1853. case 0: // 行结尾
  1854. line++;
  1855. _write2buff8RLE(2, 0, 0, lppLineAddr[line]);// 指定新的偏移地址
  1856. break;
  1857. case 1: // 图像结尾
  1858. bEOF = TRUE;
  1859. break;
  1860. case 2: // 当前地址偏移
  1861. pix = *lpSou++; pix2 = *lpSou++;
  1862. line += pix2; // 下移pix2行
  1863. _write2buff8RLE(2, 0, 0, (PBYTE)(lppLineAddr[line]+(DWORD)pix));
  1864. break;
  1865. default: // 不能压缩的像素
  1866. for (i=0;i<pix2;i++)
  1867. {
  1868. pix = *(lpSou+i);
  1869. _write2buff8RLE(1, 1, pix, NULL);
  1870. }
  1871. // (pix2+1)/2是将像素对齐到字节边界上,再加1、除2是对齐到字边界上
  1872. lpSou = (PBYTE)(lpSou + ((pix2+1)/2)*2); // 字对齐
  1873. break;
  1874. }
  1875. }
  1876. else // 编码方式
  1877. {
  1878. // pix == 相同像素的个数
  1879. pix2 = *lpSou++; // pix2 == 像素
  1880. _write2buff8RLE(1, (int)pix, pix2, NULL);
  1881. }
  1882. }
  1883. _write2buff8RLE(3, 0, 0, NULL); // 结束写函数
  1884. ::GlobalFree(lppLineAddr);
  1885. // 用标准8位转换函数转换到目标格式
  1886. result = _from_8_read(pInfo, lpDes, 0, lpPalette);
  1887. ::GlobalFree(lpDes);
  1888. return result;
  1889. }
  1890. // 将16位555位图转换为指定的标准格式位图
  1891. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  1892. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  1893. int _from_16_555_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
  1894. {
  1895. ASSERT(pInfo);
  1896. ASSERT(pInfo->state >= PKST_PASSINFO);
  1897. ASSERT(lpSou);
  1898. int imgheight = pInfo->imginfo.height; // 图像的高度
  1899. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  1900. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  1901. int heigCount, widthCount, isou;
  1902. WORD *pCurPixAddr;
  1903. WORD pix; // 当前像素
  1904. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  1905. {
  1906. case DF_16_555:
  1907. {
  1908. WORD *pDesPixAddr555;
  1909. if (imgorg == 0) // 源图是倒向位图
  1910. {
  1911. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1912. {
  1913. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1914. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1915. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1916. *pDesPixAddr555++ = *pCurPixAddr++;
  1917. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1918. {
  1919. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1920. {
  1921. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1922. pInfo->result = ER_USERBREAK;
  1923. return 1; // 用户中断操作
  1924. }
  1925. }
  1926. }
  1927. }
  1928. else // 正向位图(top-down)
  1929. {
  1930. for (heigCount=0;heigCount<imgheight;heigCount++)
  1931. {
  1932. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1933. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1934. for (widthCount=0;widthCount<imgwidth;widthCount++)
  1935. *pDesPixAddr555++ = *pCurPixAddr++;
  1936. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1937. {
  1938. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1939. {
  1940. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1941. pInfo->result = ER_USERBREAK;
  1942. return 1; // 用户中断操作
  1943. }
  1944. }
  1945. }
  1946. }
  1947. }
  1948. break;
  1949. case DF_16_565:
  1950. {
  1951. WORD *pDesPixAddr565;
  1952. if (imgorg == 0) // 源图是倒向位图
  1953. {
  1954. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1955. {
  1956. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1957. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  1958. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从555到565的转换
  1959. *pDesPixAddr565++ = (((*pCurPixAddr)&0xffe0)<<1)|((*pCurPixAddr++)&0x1f);
  1960. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  1961. {
  1962. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  1963. {
  1964. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1965. pInfo->result = ER_USERBREAK;
  1966. return 1; // 用户中断操作
  1967. }
  1968. }
  1969. }
  1970. }
  1971. else // 正向位图(top-down)
  1972. {
  1973. for (heigCount=0;heigCount<imgheight;heigCount++)
  1974. {
  1975. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  1976. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  1977. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从555到565的转换
  1978. *pDesPixAddr565++ = (((*pCurPixAddr)&0xffe0)<<1)|((*pCurPixAddr++)&0x1f);
  1979. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  1980. {
  1981. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  1982. {
  1983. // 如果进度函数返回1,则说明用户想中断操作,返回。
  1984. pInfo->result = ER_USERBREAK;
  1985. return 1; // 用户中断操作
  1986. }
  1987. }
  1988. }
  1989. }
  1990. }
  1991. break;
  1992. case DF_24:
  1993. {
  1994. PBYTE pDesPixAddr24;
  1995. BYTE  red, green, blue;
  1996. if (imgorg  == 0) // 源图是倒向位图
  1997. {
  1998. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  1999. {
  2000. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2001. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2002. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2003. {
  2004. pix = *pCurPixAddr++;
  2005. _cnv_555_to_rgb(pix, &red, &green, &blue);
  2006. *pDesPixAddr24++ = blue;
  2007. *pDesPixAddr24++ = green;
  2008. *pDesPixAddr24++ = red;
  2009. }
  2010. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2011. {
  2012. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2013. {
  2014. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2015. pInfo->result = ER_USERBREAK;
  2016. return 1; // 用户中断操作
  2017. }
  2018. }
  2019. }
  2020. }
  2021. else // 正向位图(top-down)
  2022. {
  2023. for (heigCount=0;heigCount<imgheight;heigCount++)
  2024. {
  2025. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2026. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2027. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2028. {
  2029. pix = *pCurPixAddr++;
  2030. _cnv_555_to_rgb(pix, &red, &green, &blue);
  2031. *pDesPixAddr24++ = blue;
  2032. *pDesPixAddr24++ = green;
  2033. *pDesPixAddr24++ = red;
  2034. }
  2035. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2036. {
  2037. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2038. {
  2039. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2040. pInfo->result = ER_USERBREAK;
  2041. return 1; // 用户中断操作
  2042. }
  2043. }
  2044. }
  2045. }
  2046. }
  2047. break;
  2048. case DF_32:
  2049. {
  2050. DWORD *pDesPixAddr888;
  2051. DWORD pix32;
  2052. if (imgorg == 0) // 源图是倒向位图
  2053. {
  2054. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2055. {
  2056. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2057. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2058. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2059. {
  2060. pix32 = (DWORD)*pCurPixAddr++; // 实现555到888的转换
  2061. *pDesPixAddr888++ = ((pix32<<3)&0xf8)|((pix32<<6)&0xf800)|((pix32<<9)&0xf80000);
  2062. }
  2063. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2064. {
  2065. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2066. {
  2067. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2068. pInfo->result = ER_USERBREAK;
  2069. return 1; // 用户中断操作
  2070. }
  2071. }
  2072. }
  2073. }
  2074. else // 正向位图(top-down)
  2075. {
  2076. for (heigCount=0;heigCount<imgheight;heigCount++)
  2077. {
  2078. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2079. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2080. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2081. {
  2082. pix32 = (DWORD)*pCurPixAddr++; // 实现555到888的转换
  2083. *pDesPixAddr888++ = ((pix32<<3)&0xf8)|((pix32<<6)&0xf800)|((pix32<<9)&0xf80000);
  2084. }
  2085. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2086. {
  2087. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2088. {
  2089. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2090. pInfo->result = ER_USERBREAK;
  2091. return 1; // 用户中断操作
  2092. }
  2093. }
  2094. }
  2095. }
  2096. }
  2097. break;
  2098. case DF_NULL:
  2099. default:
  2100. ASSERT(FALSE);
  2101. pInfo->result = ER_ILLCOMM;
  2102. return -1;
  2103. break;
  2104. }
  2105. return 0;
  2106. }
  2107. // 将16位565位图转换为指定的标准格式位图
  2108. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  2109. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  2110. int _from_16_565_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
  2111. {
  2112. ASSERT(pInfo);
  2113. ASSERT(pInfo->state >= PKST_PASSINFO);
  2114. ASSERT(lpSou);
  2115. int imgheight = pInfo->imginfo.height; // 图像的高度
  2116. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  2117. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  2118. int heigCount, widthCount, isou;
  2119. WORD *pCurPixAddr;
  2120. WORD pix; // 当前像素
  2121. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  2122. {
  2123. case DF_16_555:
  2124. {
  2125. WORD *pDesPixAddr555;
  2126. if (imgorg == 0) // 源图是倒向位图
  2127. {
  2128. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2129. {
  2130. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2131. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2132. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从565到555的转换
  2133. *pDesPixAddr555++ = (((*pCurPixAddr)>>1)&0x7fe0)|((*pCurPixAddr++)&0x1f);
  2134. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2135. {
  2136. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2137. {
  2138. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2139. pInfo->result = ER_USERBREAK;
  2140. return 1; // 用户中断操作
  2141. }
  2142. }
  2143. }
  2144. }
  2145. else // 正向位图(top-down)
  2146. {
  2147. for (heigCount=0;heigCount<imgheight;heigCount++)
  2148. {
  2149. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2150. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2151. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从565到555的转换
  2152. *pDesPixAddr555++ = (((*pCurPixAddr)>>1)&0x7fe0)|((*pCurPixAddr++)&0x1f);
  2153. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2154. {
  2155. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2156. {
  2157. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2158. pInfo->result = ER_USERBREAK;
  2159. return 1; // 用户中断操作
  2160. }
  2161. }
  2162. }
  2163. }
  2164. }
  2165. break;
  2166. case DF_16_565:
  2167. {
  2168. WORD *pDesPixAddr565;
  2169. if (imgorg == 0) // 源图是倒向位图
  2170. {
  2171. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2172. {
  2173. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2174. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2175. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2176. *pDesPixAddr565++ = *pCurPixAddr++;
  2177. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2178. {
  2179. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2180. {
  2181. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2182. pInfo->result = ER_USERBREAK;
  2183. return 1; // 用户中断操作
  2184. }
  2185. }
  2186. }
  2187. }
  2188. else // 正向位图(top-down)
  2189. {
  2190. for (heigCount=0;heigCount<imgheight;heigCount++)
  2191. {
  2192. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2193. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2194. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2195. *pDesPixAddr565++ = *pCurPixAddr++;
  2196. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2197. {
  2198. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2199. {
  2200. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2201. pInfo->result = ER_USERBREAK;
  2202. return 1; // 用户中断操作
  2203. }
  2204. }
  2205. }
  2206. }
  2207. }
  2208. break;
  2209. case DF_24:
  2210. {
  2211. PBYTE pDesPixAddr24;
  2212. BYTE  red, green, blue;
  2213. if (imgorg  == 0) // 源图是倒向位图
  2214. {
  2215. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2216. {
  2217. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2218. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2219. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2220. {
  2221. pix = *pCurPixAddr++;
  2222. _cnv_565_to_rgb(pix, &red, &green, &blue);
  2223. *pDesPixAddr24++ = blue;
  2224. *pDesPixAddr24++ = green;
  2225. *pDesPixAddr24++ = red;
  2226. }
  2227. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2228. {
  2229. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2230. {
  2231. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2232. pInfo->result = ER_USERBREAK;
  2233. return 1; // 用户中断操作
  2234. }
  2235. }
  2236. }
  2237. }
  2238. else // 正向位图(top-down)
  2239. {
  2240. for (heigCount=0;heigCount<imgheight;heigCount++)
  2241. {
  2242. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2243. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2244. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2245. {
  2246. pix = *pCurPixAddr++;
  2247. _cnv_565_to_rgb(pix, &red, &green, &blue);
  2248. *pDesPixAddr24++ = blue;
  2249. *pDesPixAddr24++ = green;
  2250. *pDesPixAddr24++ = red;
  2251. }
  2252. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2253. {
  2254. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2255. {
  2256. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2257. pInfo->result = ER_USERBREAK;
  2258. return 1; // 用户中断操作
  2259. }
  2260. }
  2261. }
  2262. }
  2263. }
  2264. break;
  2265. case DF_32:
  2266. {
  2267. DWORD *pDesPixAddr888;
  2268. DWORD pix32;
  2269. if (imgorg == 0) // 源图是倒向位图
  2270. {
  2271. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2272. {
  2273. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2274. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2275. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2276. {
  2277. pix32 = (DWORD)*pCurPixAddr++; // 实现565到888的转换
  2278. *pDesPixAddr888++ = ((pix32<<3)&0xf8)|((pix32<<5)&0xfc00)|((pix32<<8)&0xf80000);
  2279. }
  2280. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2281. {
  2282. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2283. {
  2284. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2285. pInfo->result = ER_USERBREAK;
  2286. return 1; // 用户中断操作
  2287. }
  2288. }
  2289. }
  2290. }
  2291. else // 正向位图(top-down)
  2292. {
  2293. for (heigCount=0;heigCount<imgheight;heigCount++)
  2294. {
  2295. pCurPixAddr  = (WORD*)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2296. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2297. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2298. {
  2299. pix32 = (DWORD)*pCurPixAddr++; // 实现565到888的转换
  2300. *pDesPixAddr888++ = ((pix32<<3)&0xf8)|((pix32<<5)&0xfc00)|((pix32<<8)&0xf80000);
  2301. }
  2302. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2303. {
  2304. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2305. {
  2306. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2307. pInfo->result = ER_USERBREAK;
  2308. return 1; // 用户中断操作
  2309. }
  2310. }
  2311. }
  2312. }
  2313. }
  2314. break;
  2315. case DF_NULL:
  2316. default:
  2317. ASSERT(FALSE);
  2318. pInfo->result = ER_ILLCOMM;
  2319. return -1;
  2320. break;
  2321. }
  2322. return 0;
  2323. }
  2324. // 将24位位图转换为指定的标准格式位图
  2325. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  2326. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  2327. int _from_24_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
  2328. {
  2329. ASSERT(pInfo);
  2330. ASSERT(pInfo->state >= PKST_PASSINFO);
  2331. ASSERT(lpSou);
  2332. int imgheight = pInfo->imginfo.height; // 图像的高度
  2333. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  2334. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  2335. int heigCount, widthCount, isou;
  2336. PBYTE pCurPixAddr;
  2337. BYTE  red, green, blue;
  2338. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  2339. {
  2340. case DF_16_555:
  2341. {
  2342. WORD *pDesPixAddr555;
  2343. if (imgorg == 0) // 源图是倒向位图
  2344. {
  2345. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2346. {
  2347. pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2348. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2349. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从24到555的转换
  2350. {
  2351. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2352. *pDesPixAddr555++ = _cnv_rgb_to_555(red, green, blue);
  2353. }
  2354. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2355. {
  2356. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2357. {
  2358. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2359. pInfo->result = ER_USERBREAK;
  2360. return 1; // 用户中断操作
  2361. }
  2362. }
  2363. }
  2364. }
  2365. else // 正向位图(top-down)
  2366. {
  2367. for (heigCount=0;heigCount<imgheight;heigCount++)
  2368. {
  2369. pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2370. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2371. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从24到555的转换
  2372. {
  2373. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2374. *pDesPixAddr555++ = _cnv_rgb_to_555(red, green, blue);
  2375. }
  2376. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2377. {
  2378. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2379. {
  2380. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2381. pInfo->result = ER_USERBREAK;
  2382. return 1; // 用户中断操作
  2383. }
  2384. }
  2385. }
  2386. }
  2387. }
  2388. break;
  2389. case DF_16_565:
  2390. {
  2391. WORD *pDesPixAddr565;
  2392. if (imgorg == 0) // 源图是倒向位图
  2393. {
  2394. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2395. {
  2396. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2397. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2398. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2399. {
  2400. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2401. *pDesPixAddr565++ = _cnv_rgb_to_565(red, green, blue);
  2402. }
  2403. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2404. {
  2405. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2406. {
  2407. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2408. pInfo->result = ER_USERBREAK;
  2409. return 1; // 用户中断操作
  2410. }
  2411. }
  2412. }
  2413. }
  2414. else // 正向位图(top-down)
  2415. {
  2416. for (heigCount=0;heigCount<imgheight;heigCount++)
  2417. {
  2418. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2419. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2420. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2421. {
  2422. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2423. *pDesPixAddr565++ = _cnv_rgb_to_565(red, green, blue);
  2424. }
  2425. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2426. {
  2427. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2428. {
  2429. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2430. pInfo->result = ER_USERBREAK;
  2431. return 1; // 用户中断操作
  2432. }
  2433. }
  2434. }
  2435. }
  2436. }
  2437. break;
  2438. case DF_24:
  2439. {
  2440. PBYTE pDesPixAddr24;
  2441. if (imgorg  == 0) // 源图是倒向位图
  2442. {
  2443. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2444. {
  2445. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2446. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2447. ::CopyMemory((PVOID)pDesPixAddr24, (PVOID)pCurPixAddr, imgwidth*3);
  2448. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2449. {
  2450. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2451. {
  2452. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2453. pInfo->result = ER_USERBREAK;
  2454. return 1; // 用户中断操作
  2455. }
  2456. }
  2457. }
  2458. }
  2459. else // 正向位图(top-down)
  2460. {
  2461. for (heigCount=0;heigCount<imgheight;heigCount++)
  2462. {
  2463. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2464. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2465. ::CopyMemory((PVOID)pDesPixAddr24, (PVOID)pCurPixAddr, imgwidth*3);
  2466. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2467. {
  2468. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2469. {
  2470. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2471. pInfo->result = ER_USERBREAK;
  2472. return 1; // 用户中断操作
  2473. }
  2474. }
  2475. }
  2476. }
  2477. }
  2478. break;
  2479. case DF_32:
  2480. {
  2481. DWORD *pDesPixAddr888;
  2482. DWORD pix32;
  2483. if (imgorg == 0) // 源图是倒向位图
  2484. {
  2485. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2486. {
  2487. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2488. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2489. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2490. {
  2491. pix32 = *((DWORD*)pCurPixAddr);
  2492. pix32 &= 0xffffff; // 888格式,舍弃最高位
  2493. pCurPixAddr += 3;
  2494. *pDesPixAddr888++ = pix32;
  2495. }
  2496. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2497. {
  2498. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2499. {
  2500. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2501. pInfo->result = ER_USERBREAK;
  2502. return 1; // 用户中断操作
  2503. }
  2504. }
  2505. }
  2506. }
  2507. else // 正向位图(top-down)
  2508. {
  2509. for (heigCount=0;heigCount<imgheight;heigCount++)
  2510. {
  2511. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2512. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2513. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2514. {
  2515. pix32 = *((DWORD*)pCurPixAddr);
  2516. pix32 &= 0xffffff; // 888格式,舍弃最高位
  2517. pCurPixAddr += 3;
  2518. *pDesPixAddr888++ = pix32;
  2519. }
  2520. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2521. {
  2522. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2523. {
  2524. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2525. pInfo->result = ER_USERBREAK;
  2526. return 1; // 用户中断操作
  2527. }
  2528. }
  2529. }
  2530. }
  2531. }
  2532. break;
  2533. case DF_NULL:
  2534. default:
  2535. ASSERT(FALSE);
  2536. pInfo->result = ER_ILLCOMM;
  2537. return -1;
  2538. break;
  2539. }
  2540. return 0;
  2541. }
  2542. // 将32位位图转换为指定的标准格式位图
  2543. // pInfo中的目标图像缓冲区必需已经被分配,且其中的源图像信息结构已被正确填写
  2544. // imgorg参数是源图像的扫描行次序标志:0-为倒向 1-为正向
  2545. int _from_32_read(LPINFOSTR pInfo, PBYTE lpSou, int imgorg)
  2546. {
  2547. ASSERT(pInfo);
  2548. ASSERT(pInfo->state >= PKST_PASSINFO);
  2549. ASSERT(lpSou);
  2550. int imgheight = pInfo->imginfo.height; // 图像的高度
  2551. int imgwidth  = pInfo->imginfo.width; // 图像的宽度
  2552. int scansize  = pInfo->imginfo.linesize;// 每一扫描行的宽度(in byte)
  2553. int heigCount, widthCount, isou;
  2554. PBYTE pCurPixAddr;
  2555. BYTE  red, green, blue;
  2556. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  2557. {
  2558. case DF_16_555:
  2559. {
  2560. WORD *pDesPixAddr555;
  2561. if (imgorg == 0) // 源图是倒向位图
  2562. {
  2563. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2564. {
  2565. pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2566. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2567. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从24到555的转换
  2568. {
  2569. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2570. pCurPixAddr++; // 舍弃最高位
  2571. *pDesPixAddr555++ = _cnv_rgb_to_555(red, green, blue);
  2572. }
  2573. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2574. {
  2575. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2576. {
  2577. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2578. pInfo->result = ER_USERBREAK;
  2579. return 1; // 用户中断操作
  2580. }
  2581. }
  2582. }
  2583. }
  2584. else // 正向位图(top-down)
  2585. {
  2586. for (heigCount=0;heigCount<imgheight;heigCount++)
  2587. {
  2588. pCurPixAddr = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2589. pDesPixAddr555  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2590. for (widthCount=0;widthCount<imgwidth;widthCount++) // 实现从24到555的转换
  2591. {
  2592. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2593. pCurPixAddr++; // 舍弃最高位
  2594. *pDesPixAddr555++ = _cnv_rgb_to_555(red, green, blue);
  2595. }
  2596. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2597. {
  2598. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2599. {
  2600. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2601. pInfo->result = ER_USERBREAK;
  2602. return 1; // 用户中断操作
  2603. }
  2604. }
  2605. }
  2606. }
  2607. }
  2608. break;
  2609. case DF_16_565:
  2610. {
  2611. WORD *pDesPixAddr565;
  2612. if (imgorg == 0) // 源图是倒向位图
  2613. {
  2614. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2615. {
  2616. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2617. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2618. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2619. {
  2620. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2621. *pCurPixAddr++;
  2622. *pDesPixAddr565++ = _cnv_rgb_to_565(red, green, blue);
  2623. }
  2624. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2625. {
  2626. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2627. {
  2628. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2629. pInfo->result = ER_USERBREAK;
  2630. return 1; // 用户中断操作
  2631. }
  2632. }
  2633. }
  2634. }
  2635. else // 正向位图(top-down)
  2636. {
  2637. for (heigCount=0;heigCount<imgheight;heigCount++)
  2638. {
  2639. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2640. pDesPixAddr565  = (WORD*)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2641. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2642. {
  2643. blue = *pCurPixAddr++; green = *pCurPixAddr++; red = *pCurPixAddr++;
  2644. *pCurPixAddr++;
  2645. *pDesPixAddr565++ = _cnv_rgb_to_565(red, green, blue);
  2646. }
  2647. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2648. {
  2649. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2650. {
  2651. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2652. pInfo->result = ER_USERBREAK;
  2653. return 1; // 用户中断操作
  2654. }
  2655. }
  2656. }
  2657. }
  2658. }
  2659. break;
  2660. case DF_24:
  2661. {
  2662. PBYTE pDesPixAddr24;
  2663. if (imgorg  == 0) // 源图是倒向位图
  2664. {
  2665. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2666. {
  2667. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2668. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2669. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2670. {
  2671. *pDesPixAddr24++ = *pCurPixAddr++;
  2672. *pDesPixAddr24++ = *pCurPixAddr++;
  2673. *pDesPixAddr24++ = *pCurPixAddr++;
  2674. *pCurPixAddr++;
  2675. }
  2676. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2677. {
  2678. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2679. {
  2680. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2681. pInfo->result = ER_USERBREAK;
  2682. return 1; // 用户中断操作
  2683. }
  2684. }
  2685. }
  2686. }
  2687. else // 正向位图(top-down)
  2688. {
  2689. for (heigCount=0;heigCount<imgheight;heigCount++)
  2690. {
  2691. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2692. pDesPixAddr24  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2693. for (widthCount=0;widthCount<imgwidth;widthCount++)
  2694. {
  2695. *pDesPixAddr24++ = *pCurPixAddr++;
  2696. *pDesPixAddr24++ = *pCurPixAddr++;
  2697. *pDesPixAddr24++ = *pCurPixAddr++;
  2698. *pCurPixAddr++;
  2699. }
  2700. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2701. {
  2702. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2703. {
  2704. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2705. pInfo->result = ER_USERBREAK;
  2706. return 1; // 用户中断操作
  2707. }
  2708. }
  2709. }
  2710. }
  2711. }
  2712. break;
  2713. case DF_32:
  2714. {
  2715. PBYTE pDesPixAddr888;
  2716. if (imgorg == 0) // 源图是倒向位图
  2717. {
  2718. for (heigCount=imgheight-1, isou=0;heigCount>=0;heigCount--, isou++)
  2719. {
  2720. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2721. pDesPixAddr888  = (PBYTE)pInfo->pLineAddr[isou];// 目标缓冲区当前行第一个像素的地址
  2722. ::CopyMemory((PVOID)pDesPixAddr888, (PVOID)pCurPixAddr, imgwidth*4);
  2723. if ((pInfo->fpProgress)&&(!(isou%RWPROGRESSSTEP)))
  2724. {
  2725. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, isou))
  2726. {
  2727. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2728. pInfo->result = ER_USERBREAK;
  2729. return 1; // 用户中断操作
  2730. }
  2731. }
  2732. }
  2733. }
  2734. else // 正向位图(top-down)
  2735. {
  2736. for (heigCount=0;heigCount<imgheight;heigCount++)
  2737. {
  2738. pCurPixAddr  = (PBYTE)(lpSou+heigCount*scansize); // 源图像当前行的第一个像素地址
  2739. pDesPixAddr888  = (PBYTE)pInfo->pLineAddr[heigCount];// 目标缓冲区当前行第一个像素的地址
  2740. ::CopyMemory((PVOID)pDesPixAddr888, (PVOID)pCurPixAddr, imgwidth*4);
  2741. if ((pInfo->fpProgress)&&(!(heigCount%RWPROGRESSSTEP)))
  2742. {
  2743. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, heigCount))
  2744. {
  2745. // 如果进度函数返回1,则说明用户想中断操作,返回。
  2746. pInfo->result = ER_USERBREAK;
  2747. return 1; // 用户中断操作
  2748. }
  2749. }
  2750. }
  2751. }
  2752. }
  2753. break;
  2754. case DF_NULL:
  2755. default:
  2756. ASSERT(FALSE);
  2757. pInfo->result = ER_ILLCOMM;
  2758. return -1;
  2759. break;
  2760. }
  2761. return 0;
  2762. }
  2763. // pInfo所指向的数据包中,annexdata.siAnnData[]变量的含意解释:
  2764. // [0] — 位深度,可以是1、4、8、16(555)、24、32(888)这六个值
  2765. // 中的一个,不能是其他值。另:不能存储为RLE格式
  2766. // [1] — 是否使用原始调色板。0 — 表示使用,1 — 表示使用当前
  2767. // 计算机缺省调色板
  2768. int _Save(CFile& pf, LPINFOSTR pInfo)
  2769. {
  2770. PBYTE lpBits;
  2771. HBITMAP hBmp;
  2772. ASSERT(pInfo);
  2773. int dibitcount = pInfo->annexdata.siAnnData[0]; // 目标文件的位深度
  2774. int palnum = _get_palette_size(dibitcount); // 调色板项数目
  2775. BITMAPINFO *pbmi = (BITMAPINFO*)::GlobalAlloc(GPTR, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*palnum);
  2776. RGBQUAD *ppal = (RGBQUAD*)((PBYTE)pbmi+sizeof(BITMAPINFOHEADER));
  2777. if (!pbmi)
  2778. {
  2779. pInfo->result = ER_MEMORYERR;
  2780. return 2; // 内存不足
  2781. }
  2782. HWND hWnd = ::GetDesktopWindow();
  2783. HDC hDC = ::GetDC(hWnd);
  2784. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2785. pbmi->bmiHeader.biPlanes = 1;
  2786. pbmi->bmiHeader.biBitCount = dibitcount;
  2787. pbmi->bmiHeader.biCompression = BI_RGB;
  2788. pbmi->bmiHeader.biSizeImage = 0;
  2789. pbmi->bmiHeader.biWidth = pInfo->sDIBInfo.bmi.biWidth;
  2790. pbmi->bmiHeader.biHeight = pInfo->sDIBInfo.bmi.biHeight;
  2791. pbmi->bmiHeader.biClrImportant = 0;
  2792. pbmi->bmiHeader.biClrUsed = 0;
  2793. pbmi->bmiHeader.biXPelsPerMeter = (int)(::GetDeviceCaps(hDC,LOGPIXELSX)*(float)39.373);
  2794. pbmi->bmiHeader.biYPelsPerMeter = (int)(::GetDeviceCaps(hDC,LOGPIXELSY)*(float)39.373);
  2795. if (palnum)
  2796. {
  2797. switch(pInfo->annexdata.siAnnData[1])
  2798. {
  2799. case 0: // 使用原位图调色板(读取的原始图像文件必需也是BMP位图)
  2800. if (pInfo->imginfo.imgformat == IMF_BMP)
  2801. {
  2802. if (pInfo->imginfo.bitcount == (unsigned int)dibitcount) // 只有原始图像的格式与目标文件的位深度相同时,才有意义
  2803. {
  2804. ASSERT(pInfo->pImgInfo); // 原始数据必需有效
  2805. ASSERT(((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biSize == sizeof(BITMAPINFOHEADER));
  2806. RGBQUAD *porg = (RGBQUAD*)(((BITMAPINFOHEADER*)(pInfo->pImgInfo))+1);
  2807. int palnum2 = ((BITMAPINFOHEADER*)(pInfo->pImgInfo))->biClrUsed;
  2808. palnum2 = (palnum2) ? palnum2:palnum;
  2809. ASSERT(palnum2 <= palnum);
  2810. for (int i=0;i<palnum2;i++)
  2811. {
  2812. ppal[i].rgbBlue = porg[i].rgbBlue;
  2813. ppal[i].rgbGreen = porg[i].rgbGreen;
  2814. ppal[i].rgbRed = porg[i].rgbRed;
  2815. ppal[i].rgbReserved = 0;
  2816. }
  2817. break;
  2818. }
  2819. }
  2820. else
  2821. {
  2822. ; // 仍使用系统缺省调色板
  2823. }
  2824. case 1: // 使用系统缺省调色板
  2825. {
  2826. LPPALETTEENTRY pal = (LPPALETTEENTRY)::GlobalAlloc(GPTR, sizeof(PALETTEENTRY)*palnum);
  2827. if (!pal)
  2828. {
  2829. ::GlobalFree(pbmi);
  2830. ::ReleaseDC(hWnd, hDC);
  2831. pInfo->result = ER_MEMORYERR;
  2832. return 2; // 内存不足
  2833. }
  2834. ::GetSystemPaletteEntries(hDC, 0, palnum, pal);
  2835. for (int i=0;i<palnum;i++)
  2836. {
  2837. ppal[i].rgbBlue = pal[i].peBlue;
  2838. ppal[i].rgbGreen = pal[i].peGreen;
  2839. ppal[i].rgbRed = pal[i].peRed;
  2840. ppal[i].rgbReserved = 0;
  2841. }
  2842. ::GlobalFree(pal);
  2843. }
  2844. break;
  2845. default:
  2846. ASSERT(FALSE);
  2847. break;
  2848. }
  2849. }
  2850. hBmp = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, (void**)&lpBits, NULL, 0);
  2851. if (hBmp == NULL)
  2852. {
  2853. ::GlobalFree(pbmi);
  2854. ::ReleaseDC(hWnd, hDC);
  2855. pInfo->result = ER_SYSERR;
  2856. return 5; // 操作系统不稳定
  2857. }
  2858. if (!SetDIBits(hDC, hBmp, 0, pInfo->imginfo.height, pInfo->_pbdata, (const BITMAPINFO*)&pInfo->sDIBInfo, DIB_RGB_COLORS))
  2859. {
  2860. ::GlobalFree(pbmi);
  2861. ::ReleaseDC(hWnd, hDC);
  2862. ::DeleteObject(hBmp);
  2863. pInfo->result = ER_SYSERR;
  2864. return 5;
  2865. }
  2866. ::ReleaseDC(hWnd, hDC);
  2867. BITMAPFILEHEADER bmf;
  2868.  
  2869. bmf.bfType = DIB_HEADER_MARKER;
  2870. bmf.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
  2871. sizeof(RGBQUAD)*palnum+((pInfo->imginfo.width*dibitcount+31)/32)*4*pInfo->imginfo.height;
  2872. bmf.bfReserved1 = 0;
  2873. bmf.bfReserved2 = 0;
  2874. bmf.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
  2875. sizeof(RGBQUAD)*palnum;
  2876. TRY
  2877. {
  2878. // writing bitmap file header
  2879. pf.SeekToBegin();
  2880. pf.Write((const void *)&bmf, sizeof(BITMAPFILEHEADER));
  2881. // writing bitmap info header
  2882. pf.Write((const void *)pbmi, sizeof(BITMAPINFOHEADER));
  2883. }
  2884. CATCH(CFileException, e)
  2885. {
  2886. ::GlobalFree(pbmi);
  2887. ::DeleteObject(hBmp);
  2888. pInfo->result = ER_FILERWERR;
  2889. return 1; // 写文件时出错
  2890. }
  2891. END_CATCH
  2892. ::GlobalFree(pbmi);
  2893. RGBQUAD *palette = NULL;
  2894. TRY
  2895. {
  2896. if (palnum)
  2897. {
  2898. palette = (RGBQUAD*)::GlobalAlloc(GPTR, sizeof(RGBQUAD)*palnum);
  2899. if (!palette)
  2900. {
  2901. ::DeleteObject(hBmp);
  2902. pInfo->result = ER_MEMORYERR;
  2903. return 2; // 内存不足
  2904. }
  2905. HDC hCompDC = ::CreateCompatibleDC(NULL);
  2906. HBITMAP hOldBmp = (HBITMAP)::SelectObject(hCompDC, hBmp);
  2907. ::GetDIBColorTable(hCompDC, 0, palnum, palette);
  2908. ::SelectObject(hCompDC, hOldBmp);
  2909. ::DeleteDC(hCompDC);
  2910. // writing color table.
  2911. pf.Write((const void *)palette, sizeof(RGBQUAD)*palnum);
  2912. ::GlobalFree(palette);
  2913. }
  2914. pf.WriteHuge((const void *)lpBits, ((pInfo->imginfo.width*dibitcount+31)/32)*4*pInfo->imginfo.height);
  2915. }
  2916. CATCH(CFileException, e)
  2917. {
  2918. if (palette) ::GlobalFree(palette);
  2919. ::DeleteObject(hBmp);
  2920. pInfo->result = ER_FILERWERR;
  2921. return 1; // 写文件时出错
  2922. }
  2923. END_CATCH
  2924. ::DeleteObject(hBmp);
  2925. pInfo->result = ER_SUCCESS;
  2926. return 0; // 写文件成功
  2927. }
  2928. // 判断标准图像的位格式
  2929. DESFORMAT _get_desformat(LPINFOSTR pInfo)
  2930. {
  2931. ASSERT(pInfo);
  2932. // ASSERT(pInfo->state >= PKST_PASSVER);
  2933. ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
  2934. DESFORMAT result;
  2935. switch(pInfo->sDIBInfo.bmi.biBitCount)
  2936. {
  2937. case 32:
  2938. /******************************************************
  2939. 32位掩码示意图
  2940.     高               ->                 低
  2941. 0000 0000   0000 0000   0000 0000   0000 0000  888格式
  2942.             1111 1111  ------------------------R
  2943.                         1111 1111 -------------G
  2944.                                     1111 1111--B
  2945. * Win95 系统只支持这一种格式
  2946. ******************************************************/
  2947. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  2948. {
  2949. result = DF_32;
  2950. break;
  2951. }
  2952. if ((pInfo->sDIBInfo.rmask == 0xff0000)&&
  2953. (pInfo->sDIBInfo.gmask == 0xff00)&&
  2954. (pInfo->sDIBInfo.bmask == 0xff))
  2955. result = DF_32;
  2956. else
  2957. {
  2958. ASSERT(FALSE); // 只支持888格式
  2959. result = DF_NULL;
  2960. }
  2961. break;
  2962. case 24:
  2963. result = DF_24;
  2964. break;
  2965. case 16:
  2966. /*******************************************
  2967. 16位掩码示意图
  2968.   高字节      低字节
  2969. 0000 0000   0000 0000 
  2970.    1 1111--B // 555格式
  2971.    11 111 -------G
  2972.  111 11  --------------R
  2973. 0
  2974.    1 1111--B // 565格式
  2975.   111   111 -------G
  2976. 1111 1   --------------R
  2977. * Win95 系统只支持以上两种格式
  2978. *******************************************/
  2979. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  2980. {
  2981. result = DF_16_555;
  2982. break;
  2983. }
  2984. if ((pInfo->sDIBInfo.rmask == 0x7c00)&&
  2985. (pInfo->sDIBInfo.gmask == 0x3e0)&&
  2986. (pInfo->sDIBInfo.bmask == 0x1f))
  2987. result = DF_16_555;
  2988. else if ((pInfo->sDIBInfo.rmask == 0xf800)&&
  2989. (pInfo->sDIBInfo.gmask == 0x7e0)&&
  2990. (pInfo->sDIBInfo.bmask == 0x1f))
  2991. result = DF_16_565;
  2992. else
  2993. result = DF_NULL;
  2994. break;
  2995. default:
  2996. ASSERT(FALSE); // 不接受其它格式
  2997. result = DF_NULL;
  2998. break;
  2999. }
  3000. return result;
  3001. }
  3002. // 判断标准图像的位格式
  3003. SOUFORMAT _get_souformat(LPBITMAPINFO pInfo)
  3004. {
  3005. ASSERT(pInfo->bmiHeader.biSize);
  3006. SOUFORMAT result;
  3007. switch(pInfo->bmiHeader.biBitCount)
  3008. {
  3009. case 1:
  3010. ASSERT(pInfo->bmiHeader.biCompression == BI_RGB);
  3011. result = SF_1;
  3012. break;
  3013. case 4:
  3014. if (pInfo->bmiHeader.biCompression == BI_RGB)
  3015. result = SF_4;
  3016. else if ((pInfo->bmiHeader.biCompression == BI_RLE4)&&
  3017.  (pInfo->bmiHeader.biHeight > 0)) // 正向的位图不能被压缩
  3018. result = SF_4_RLE;
  3019. else
  3020. result = SF_NULL;
  3021. break;
  3022. case 8:
  3023. if (pInfo->bmiHeader.biCompression == BI_RGB)
  3024. result = SF_8;
  3025. else if ((pInfo->bmiHeader.biCompression == BI_RLE8)&&
  3026.  (pInfo->bmiHeader.biHeight > 0))
  3027. result = SF_8_RLE;
  3028. else
  3029. result = SF_NULL;
  3030. break;
  3031. case 16:
  3032. {
  3033. /*******************************************
  3034. 16位掩码示意图
  3035.   高字节      低字节
  3036. 0000 0000   0000 0000 
  3037.    1 1111--B // 555格式
  3038.    11 111 -------G
  3039.  111 11  --------------R
  3040. 0
  3041.    1 1111--B // 565格式
  3042.   111   111 -------G
  3043. 1111 1   --------------R
  3044. * Win95 系统只支持以上两种格式
  3045. *******************************************/
  3046. if (pInfo->bmiHeader.biCompression == BI_RGB)
  3047. {
  3048. result = SF_16_555;
  3049. break;
  3050. }
  3051. DWORD *pMark = (DWORD*)((LPBITMAPINFOHEADER)pInfo+1);
  3052. if ((pMark[0] == 0x7c00)&&(pMark[1] == 0x3e0)&&(pMark[2] == 0x1f))
  3053. result = SF_16_555;
  3054. else if ((pMark[0] == 0xf800)&&(pMark[1] == 0x7e0)&&(pMark[2] == 0x1f))
  3055. result = SF_16_565;
  3056. else
  3057. result = SF_NULL;
  3058. break;
  3059. }
  3060. case 24:
  3061. ASSERT(pInfo->bmiHeader.biCompression == BI_RGB);
  3062. result = SF_24;
  3063. break;
  3064. case 32:
  3065. {
  3066. /******************************************************
  3067. 32位掩码示意图
  3068.     高               ->                 低
  3069. 0000 0000   0000 0000   0000 0000   0000 0000  888格式
  3070.             1111 1111  ------------------------R
  3071.                         1111 1111 -------------G
  3072.                                     1111 1111--B
  3073. * Win95 系统只支持这一种格式
  3074. ******************************************************/
  3075. if (pInfo->bmiHeader.biCompression == BI_RGB)
  3076. {
  3077. result = SF_32;
  3078. break;
  3079. }
  3080. DWORD *pMark = (DWORD*)((LPBITMAPINFOHEADER)pInfo+1);
  3081. if ((pMark[0] == 0xff0000)&&(pMark[1] == 0x00ff00)&&(pMark[2] == 0xff))
  3082. result = SF_32;
  3083. else
  3084. result = SF_NULL; // 只支持888格式
  3085. break;
  3086. }
  3087. default:
  3088. result = SF_NULL;
  3089. break;
  3090. }
  3091. return result;
  3092. }
  3093. // 将指定的RGB颜色分量转换成555格式(WORD型值返回)
  3094. WORD _cnv_rgb_to_555(BYTE red, BYTE green, BYTE blue)
  3095. {
  3096. WORD result = 0;
  3097. result = (((WORD)red>>3)<<10)|(((WORD)green>>3)<<5)|((WORD)blue>>3);
  3098. return result;
  3099. }
  3100. // 将指定的555格式的颜色转换成RGB颜色分量
  3101. void _cnv_555_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
  3102. {
  3103. // 在555转换到RGB时,将像素的亮度调到最大
  3104. *red = (BYTE)((col>>7)&0xf8);
  3105. *green = (BYTE)((col>>2)&0xf8);
  3106. *blue = (BYTE)(col<<3);
  3107. }
  3108. // 将指定的RGB颜色分量转换成565格式(WORD型值返回)
  3109. WORD _cnv_rgb_to_565(BYTE red, BYTE green, BYTE blue)
  3110. {
  3111. WORD result = 0;
  3112. result = (((WORD)red>>3)<<11)|(((WORD)green>>2)<<5)|((WORD)blue>>3);
  3113. return result;
  3114. }
  3115. // 将指定的565格式的颜色转换成RGB颜色分量
  3116. void _cnv_565_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
  3117. {
  3118. // 在565转换到RGB时,将像素的亮度调到最大
  3119. *red = (BYTE)((col>>8)&0xf8);
  3120. *green = (BYTE)((col>>3)&0xfc);
  3121. *blue = (BYTE)(col<<3);
  3122. }
  3123. // 将指定的RGB颜色分量转换成888格式(DWORD型值返回)
  3124. DWORD _cnv_rgb_to_888(BYTE red, BYTE green, BYTE blue)
  3125. {
  3126. DWORD result = 0;
  3127. result = ((DWORD)red<<16)|((DWORD)green<<8)|(DWORD)blue;
  3128. return result;
  3129. }
  3130. // 向4位缓冲区写像素(只供_from_4_RLE_read()函数内部调用)
  3131. // 形参mark含意:0-初始化变量  1-写像素  2-移动到指定点  3-结束操作  4-获取当前地址
  3132. // 注:当mark等于2时,参数num将作为像素除2余数被代入,来对iCurOff赋值
  3133. PBYTE _write2buff4RLE(int mark, int num, BYTE pix, PBYTE lpDesData)
  3134. {
  3135. static PBYTE lpDes; // 缓冲区基地址
  3136. static PBYTE lpCur; // 缓冲区当前写地址
  3137. static int   iCurOff; // 在字节中的当前位置,0-高半字节  1-低半字节
  3138. int i;
  3139. BYTE pixa[2];
  3140. switch(mark)
  3141. {
  3142. case 0: // 初始化变量
  3143. lpDes = lpDesData;
  3144. lpCur = lpDes;
  3145. iCurOff = 0;
  3146. break;
  3147. case 1: // 写像素
  3148. pixa[0] = pix>>4;
  3149. pixa[1] = pix&0xf;
  3150. for (i=0;i<num;i++)
  3151. {
  3152. if (iCurOff == 0) // 左像素
  3153. {
  3154. *lpCur = pixa[i%2]<<4;
  3155. iCurOff = 1;
  3156. }
  3157. else // 右像素
  3158. {
  3159. ASSERT(iCurOff == 1);
  3160. *lpCur |= pixa[i%2];
  3161. lpCur++;
  3162. iCurOff = 0;
  3163. }
  3164. }
  3165. break;
  3166. case 2: // 移动到指定点
  3167. lpCur = lpDesData;
  3168. iCurOff = num;
  3169. break;
  3170. case 3: // 结束操作
  3171. lpDes = NULL;
  3172. lpCur = lpDes;
  3173. iCurOff = 0;
  3174. break;
  3175. case 4: // 获取当前地址
  3176. break;
  3177. default:
  3178. ASSERT(FALSE);
  3179. break;
  3180. }
  3181. return lpCur;
  3182. }
  3183. // 向8位缓冲区写像素(只供_from_8_RLE_read()函数内部调用)
  3184. // 形参mark含意:0-初始化变量  1-写像素  2-移动到指定点  3-结束操作  4-获取当前地址
  3185. PBYTE _write2buff8RLE(int mark, int num, BYTE pix, PBYTE lpDesData)
  3186. {
  3187. static PBYTE lpDes; // 缓冲区基地址
  3188. static PBYTE lpCur; // 缓冲区当前写地址
  3189. int i;
  3190. switch(mark)
  3191. {
  3192. case 0: // 初始化变量
  3193. lpDes = lpDesData;
  3194. lpCur = lpDes;
  3195. break;
  3196. case 1: // 写像素
  3197. for (i=0;i<num;i++)
  3198. *lpCur++ = pix;
  3199. break;
  3200. case 2: // 移动到指定点
  3201. lpCur = lpDesData;
  3202. break;
  3203. case 3: // 结束操作
  3204. lpDes = NULL;
  3205. lpCur = lpDes;
  3206. break;
  3207. case 4: // 获取当前地址
  3208. break;
  3209. default:
  3210. ASSERT(FALSE);
  3211. break;
  3212. }
  3213. return lpCur;
  3214. }
  3215. // 计算调色板的尺寸
  3216. int _get_palette_size(int bitcount)
  3217. {
  3218. int result;
  3219. switch(bitcount)
  3220. {
  3221. case 1:
  3222. result = 2;
  3223. break;
  3224. case 4:
  3225. result = 16;
  3226. break;
  3227. case 8:
  3228. result = 256;
  3229. break;
  3230. case 16:
  3231. case 24:
  3232. case 32:
  3233. result = 0;
  3234. break;
  3235. default:
  3236. ASSERT(FALSE); // 非法情况
  3237. result = 0;
  3238. break;
  3239. }
  3240. return result;
  3241. }