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

图形图象

开发平台:

Visual C++

  1. // PngModule.cpp : Defines the initialization routines for the DLL.
  2. //
  3. #include "stdafx.h"
  4. #include "PngModule.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. static char ModuleProcessImgType[]="PNG"; // 本模块能处理的图像类型
  11. static char WriterList[]="Aurora"; // 本模块的作者列表
  12. static char WriterMess[]="第一版"; // 作者留言
  13. //
  14. // Note!
  15. //
  16. // If this DLL is dynamically linked against the MFC
  17. // DLLs, any functions exported from this DLL which
  18. // call into MFC must have the AFX_MANAGE_STATE macro
  19. // added at the very beginning of the function.
  20. //
  21. // For example:
  22. //
  23. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  24. // {
  25. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  26. // // normal function body here
  27. // }
  28. //
  29. // It is very important that this macro appear in each
  30. // function, prior to any calls into MFC.  This means that
  31. // it must appear as the first statement within the 
  32. // function, even before any object variable declarations
  33. // as their constructors may generate calls into the MFC
  34. // DLL.
  35. //
  36. // Please see MFC Technical Notes 33 and 58 for additional
  37. // details.
  38. //
  39. // 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
  40. // ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
  41. // 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
  42. //
  43. //
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CPngModuleApp
  46. BEGIN_MESSAGE_MAP(CPngModuleApp, CWinApp)
  47. //{{AFX_MSG_MAP(CPngModuleApp)
  48. // NOTE - the ClassWizard will add and remove mapping macros here.
  49. //    DO NOT EDIT what you see in these blocks of generated code!
  50. //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CPngModuleApp construction
  54. CPngModuleApp::CPngModuleApp()
  55. {
  56. // TODO: add construction code here,
  57. // Place all significant initialization in InitInstance
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // The one and only CPngModuleApp object
  61. CPngModuleApp theApp;
  62. long WINAPI GetLong(void)
  63. {
  64. return 2L;
  65. }
  66. // 接口函数声明 — 第一层,唯一与外界联系的接口
  67. int WINAPI AccessPNGModule(INFOSTR *pInfo)
  68. {
  69. // 这个函数可以不作修改的使用,除非你的返回值多于两种。
  70. switch(pInfo->comm)
  71. {
  72. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  73. _fnCMD_GETPROCTYPE(pInfo);
  74. break;
  75. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  76. _fnCMD_GETWRITERS(pInfo);
  77. break;
  78. case CMD_GETWRITERMESS: // 获取作者们的留言
  79. _fnCMD_GETWRITERMESS(pInfo);
  80. break;
  81. case CMD_GETBUILDID: // 获取图像模块内部版本号
  82. _fnCMD_GETBUILDID(pInfo);
  83. break;
  84. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  85. _fnCMD_IS_VALID_FILE(pInfo);
  86. break;
  87. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  88. _fnCMD_GET_FILE_INFO(pInfo);
  89. break;
  90. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  91. _fnCMD_LOAD_FROM_FILE(pInfo);
  92. break;
  93. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  94. _fnCMD_SAVE_TO_FILE(pInfo);
  95. break;
  96. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  97. _fnCMD_IS_SUPPORT(pInfo);
  98. break;
  99. case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
  100. _fnCMD_RESIZE(pInfo);
  101. break;
  102. default:
  103. pInfo->result = ER_ILLCOMM; // 非法命令
  104. ASSERT(FALSE); // 调用者的程序设计有问题 :-)
  105. break;
  106. }
  107. // 执行命令成功返回1, 失败返回0
  108. return (pInfo->result==ER_SUCCESS)? 1:0;
  109. }
  110. // 命令解释函数 — 第二层解释函数
  111. //********************************************************************//
  112. // 操作命令解释函数---解释:CMD_IS_SUPPORT命令
  113. // 查询某个命令是否被支持
  114. void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
  115. {
  116. // 这个函数是为客户程序查询时使用,如果你实现了对某个命令的
  117. // 解释,可修改相应的case中的设置,使其返回ER_SUCCESS,这就
  118. // 表示你的模块已经支持该命令了。同时,现在的这个文件中已包
  119. // 含了对前四个命令的解释,你只需向还未支持的命令函数中添加
  120. // 代码即可。
  121. ASSERT(pInfo->result == ER_EMPTY);
  122. switch(pInfo->annexdata.cmAnnData)  
  123. {
  124. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  125. pInfo->result = ER_SUCCESS;
  126. break;
  127. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  128. pInfo->result = ER_SUCCESS;
  129. break;
  130. case CMD_GETWRITERMESS: // 获取作者们的留言
  131. pInfo->result = ER_SUCCESS;
  132. break;
  133. case CMD_GETBUILDID: // 获取图像模块内部版本号
  134. pInfo->result = ER_SUCCESS;
  135. break;
  136. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  137. pInfo->result = ER_SUCCESS;
  138. break;
  139. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  140. pInfo->result = ER_SUCCESS;
  141. break;
  142. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  143. pInfo->result = ER_SUCCESS;
  144. break;
  145. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  146. pInfo->result = ER_SUCCESS;
  147. break;
  148. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  149. pInfo->result = ER_SUCCESS;
  150. break;
  151. case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
  152. pInfo->result = ER_NOTSUPPORT;
  153. break;
  154. default:
  155. pInfo->result = ER_NOTSUPPORT;
  156. break;
  157. }
  158. }
  159. // 操作命令解释函数---解释:CMD_GETPROCTYPE命令
  160. // 获取本模块能处理的图像类型,如:BMP,PCX等等
  161. void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
  162. {
  163. // 这是预定义的函数代码,你可以不必修改的使用。
  164. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  165. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  166. ASSERT(pInfo->result == ER_EMPTY);
  167. // 复制能处理的类型字符串
  168. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType, 
  169. sizeof(ModuleProcessImgType));
  170. pInfo->result = ER_SUCCESS;
  171. }
  172. // 操作命令解释函数---解释:CMD_GETWRITER命令
  173. // 获取本模块的作者列表,多人时用逗号分隔
  174. void _fnCMD_GETWRITERS(INFOSTR *pInfo)
  175. {
  176. // 这是预定义的函数代码,你可以不必修改的使用。
  177. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  178. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  179. ASSERT(pInfo->result == ER_EMPTY);
  180. // 复制开发者名单串
  181. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList, 
  182. sizeof(WriterList));
  183. pInfo->result = ER_SUCCESS;
  184. }
  185. // 操作命令解释函数---解释:CMD_GETWRITERMESS命令
  186. // 获取作者们的留言
  187. void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
  188. {
  189. // 这是预定义的函数代码,你可以不必修改的使用。
  190. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  191. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  192. ASSERT(pInfo->result == ER_EMPTY);
  193. // 复制开发者们的留言字符串
  194. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess, 
  195. sizeof(WriterMess));
  196. pInfo->result = ER_SUCCESS;
  197. }
  198. // 操作命令解释函数---解释:CMD_GETBUILDID命令
  199. // 获取图像模块内部版本号
  200. void _fnCMD_GETBUILDID(INFOSTR *pInfo)
  201. {
  202. // 这是预定义的函数代码,你可以不必修改的使用。
  203. // 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
  204. ASSERT(pInfo->annexdata.dwAnnData == 0);
  205. ASSERT(pInfo->result == ER_EMPTY);
  206. // 填写内部版本号码
  207. pInfo->annexdata.dwAnnData = MODULE_BUILDID;
  208. pInfo->result = ER_SUCCESS;
  209. }
  210. // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
  211. // 判断指定文件是否是有效的WMF文件
  212. void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
  213. {
  214. ASSERT(pInfo->result == ER_EMPTY);
  215. ASSERT(pInfo->annexdata.iAnnData == 0);
  216. ASSERT(::strlen(pInfo->filename));
  217. ASSERT(pInfo->state == PKST_NOTVER);
  218. BYTE Signature[8];
  219. HANDLE m_hPng;
  220. m_hPng = CreateFile(pInfo->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
  221. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  222. if(m_hPng == INVALID_HANDLE_VALUE)
  223. pInfo->result = ER_COMMINFOERR; //文件打开错
  224. else
  225. {
  226. DWORD dwBytes; 
  227. //读出PNG文件头上的8个标志字节
  228. BOOL Correct = ReadFile(m_hPng, Signature, 8, &dwBytes, NULL);
  229. if(!Correct)
  230. {
  231. pInfo->result = ER_FILERWERR;
  232. TRACE("读文件错误!");
  233. CloseHandle(m_hPng);
  234. return;
  235. }
  236. pInfo->result = ER_SUCCESS;
  237. //判断是否PNG
  238. if(png_sig_cmp(Signature, 0, 8))
  239. pInfo->annexdata.iAnnData = 0;
  240. else
  241. {
  242. //合法PNG文件
  243. pInfo->annexdata.iAnnData = 1;
  244. pInfo->state = PKST_PASSVER;
  245. }
  246. CloseHandle(m_hPng);
  247. }
  248. return;
  249. }
  250. // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
  251. // 获取指定文件的信息
  252. void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
  253. {
  254. // 检验入口参数是否符合接口定义
  255. ASSERT(pInfo->result == ER_EMPTY);
  256. ASSERT(::strlen(pInfo->filename));
  257. // 确认PNG文件有效且客户模块将imginfo晴空
  258. ASSERT(pInfo->state == PKST_PASSVER);
  259. ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
  260. HANDLE m_hPng;
  261. png_structp pPng;
  262. png_infop pPngInfo;
  263. __try
  264. {
  265. m_hPng = ::CreateFile(pInfo->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
  266. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  267. if(m_hPng == INVALID_HANDLE_VALUE) //打开文件错误
  268. {
  269. pInfo->result = ER_FILERWERR;
  270. __leave;
  271. }
  272. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  273. // 获取文件的长度、图像的宽度、高度等信息
  274. lpImgInfoStr->imgtype = IMT_RESSTATIC;
  275. lpImgInfoStr->imgformat = IMF_PNG;
  276. lpImgInfoStr->filesize = ::GetFileSize(m_hPng, NULL);
  277. /* 读文件信息头 */
  278. //分配PNG结构,并初始化
  279. pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
  280. (png_voidp)::GetForegroundWindow(), PngErrorHandler, NULL);
  281. if(pPng == NULL)
  282. {
  283. pInfo->result = ER_MEMORYERR;
  284. __leave;
  285. }
  286. //建立PNG信息头结构
  287. pPngInfo = png_create_info_struct(pPng);
  288. if(pPngInfo == NULL)
  289. {
  290. pInfo->result = ER_MEMORYERR;
  291. __leave;
  292. }
  293. //设置自定义读函数
  294. png_set_read_fn(pPng, (PVOID)m_hPng, PngRead4Win32);
  295. //读文件信息头(直到IDAT)
  296. png_read_info(pPng, pPngInfo);
  297. //获取图象信息
  298. PNGINFOHEADER pngInfoHeader;
  299. png_get_IHDR(pPng, pPngInfo, &pngInfoHeader.Width, 
  300. &pngInfoHeader.Height, &pngInfoHeader.bit_depth, 
  301. &pngInfoHeader.color_type, &pngInfoHeader.interlace_type,
  302. &pngInfoHeader.compression_type, &pngInfoHeader.filter_type);
  303. lpImgInfoStr->width = pngInfoHeader.Width;
  304. lpImgInfoStr->height = pngInfoHeader.Height;
  305. lpImgInfoStr->bitcount = 24; //所有格式的图形均转换为24位RGB
  306. lpImgInfoStr->compression = ICS_RGB;
  307. /**  获取图象每扫描行的字节数  **/
  308. /**  因为本模块准备将图形都转换为24位RGB图,所以linesize可以通过更简单的方法获得 */
  309. lpImgInfoStr->linesize = lpImgInfoStr->bitcount * lpImgInfoStr->width / 8;//png_get_rowbytes(pPng, pPngInfo);
  310. lpImgInfoStr->imgnumbers = 1; //PNG支持多幅图象,但此处暂定为1
  311. lpImgInfoStr->imgchang = 1; //图象显示器不允许修改图象
  312. //获取文件最后一次修改的时间
  313. FILETIME fLastWriteTime;
  314. SYSTEMTIME sLastWriteTime;
  315. if(::GetFileTime(m_hPng, NULL, NULL, &fLastWriteTime))
  316. {
  317. FileTimeToSystemTime(&fLastWriteTime, &sLastWriteTime);
  318. lpImgInfoStr->year = sLastWriteTime.wYear;
  319. lpImgInfoStr->monday = sLastWriteTime.wMonth;
  320. lpImgInfoStr->monday <<= 8;
  321. lpImgInfoStr->monday |= sLastWriteTime.wDay;
  322. // 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
  323. lpImgInfoStr->time = sLastWriteTime.wHour;
  324. lpImgInfoStr->time <<= 8;
  325. lpImgInfoStr->time |= sLastWriteTime.wMinute;
  326. lpImgInfoStr->time <<= 8;
  327. lpImgInfoStr->time |= sLastWriteTime.wSecond;
  328. lpImgInfoStr->time &= 0xffffff;
  329. //读参数成功,设置state,将执行结果置为成功
  330. pInfo->state = PKST_PASSINFO;
  331. pInfo->result = ER_SUCCESS;
  332. }
  333. else
  334. pInfo->result = ER_FILERWERR;
  335. __leave;
  336. }
  337. __finally
  338. {
  339. //清除分配单元,并且关闭文件
  340. if(pPng != NULL)
  341. png_destroy_read_struct(&pPng, &pPngInfo, (png_infopp)NULL);
  342. if(m_hPng != INVALID_HANDLE_VALUE)
  343. CloseHandle(m_hPng);
  344. }
  345. return;
  346. }
  347. // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
  348. // 从指定图像文件中读取数据
  349. void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
  350. {
  351. // 检验入口参数是否符合接口定义
  352. ASSERT(pInfo->result == ER_EMPTY);
  353. ASSERT(::strlen(pInfo->filename));
  354. // 此时,该文件必需是一个已存在的、有效的WMF文件,并且数据包中
  355. // 含有该文件的信息(imginfo结构中)
  356. ASSERT(pInfo->state == PKST_PASSINFO);
  357. ASSERT(pInfo->imginfo.imgformat == IMF_PNG);
  358. ASSERT(pInfo->pImgInfo == NULL);
  359. // 必需设置标准图像格式信息
  360. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  361. ASSERT(pInfo->pLineAddr != NULL);
  362. ASSERT(pInfo->_pbdata != NULL);
  363. HANDLE hPng;
  364. png_structp pPng;
  365. png_infop pPngInfo;
  366. __try
  367. {
  368. //分配PNG结构,并初始化
  369. pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, 
  370. (png_voidp)::GetForegroundWindow(), PngErrorHandler, NULL);
  371. if(pPng == NULL)
  372. {
  373. pInfo->result = ER_MEMORYERR;
  374. __leave;
  375. }
  376. //建立PNG信息头结构
  377. pPngInfo = png_create_info_struct(pPng);
  378. if(pPngInfo == NULL)
  379. {
  380. pInfo->result = ER_MEMORYERR;
  381. __leave;
  382. }
  383. hPng = ::CreateFile(pInfo->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
  384. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  385. if(hPng == INVALID_HANDLE_VALUE) //打开文件错误
  386. {
  387. pInfo->result = ER_FILERWERR;
  388. __leave;
  389. }
  390. //设置自定义读函数
  391. png_set_read_fn(pPng, (PVOID)hPng, PngRead4Win32);
  392.     if (setjmp(png_jmpbuf(pPng)))
  393.     {
  394. pInfo->result = ER_FILERWERR;
  395. __leave;
  396. }
  397. //读文件信息头(直到IDAT),在读取图象数据前必须
  398. png_read_info(pPng, pPngInfo);
  399. //获取PNG图象头,以备设置读取变换时引用
  400. PNGINFOHEADER pngInfoHeader;
  401. png_get_IHDR(pPng, pPngInfo, &pngInfoHeader.Width, 
  402. &pngInfoHeader.Height, &pngInfoHeader.bit_depth, 
  403. &pngInfoHeader.color_type, &pngInfoHeader.interlace_type,
  404. &pngInfoHeader.compression_type, &pngInfoHeader.filter_type);
  405. /* 通知PNGLIB将16位图形削减为8位 */
  406. png_set_strip_16(pPng);
  407. /* 将1、2、4位图形由压缩状态变为每位象素用1字节表示 */
  408. png_set_packing(pPng);
  409. /* 将索引图转换为RGB图 */
  410. if (pngInfoHeader.color_type == PNG_COLOR_TYPE_PALETTE &&
  411. pngInfoHeader.bit_depth <= 8)
  412. png_set_palette_to_rgb(pPng);
  413. /* 将小于8位的灰度图转换为8位灰度 */
  414. if (pngInfoHeader.color_type == PNG_COLOR_TYPE_GRAY && 
  415. pngInfoHeader.bit_depth < 8)
  416. png_set_gray_1_2_4_to_8(pPng);
  417. /* 将tRNS通道转换为alpha通道 */
  418. if (png_get_valid(pPng, pPngInfo,PNG_INFO_tRNS)) 
  419. png_set_tRNS_to_alpha(pPng);
  420. /* 若读图象时使用png_set_strip_alpha()去掉alpha通道,则可以不设置背景色
  421.    * 若读图象时未去掉alpha通道,则必须设置背景色,否则不能正确显示
  422.  */
  423. png_color_16 *image_background;
  424. png_color_16 user_background; //使用当前背景做图形背景
  425. COLORREF bkColor = ::GetBkColor(::GetDC(::GetForegroundWindow()));
  426. user_background.index = 0;
  427. user_background.red = GetRValue(bkColor);
  428. user_background.blue = GetBValue(bkColor);
  429. user_background.green = GetGValue(bkColor);
  430. user_background.gray = 255;
  431. if (png_get_bKGD(pPng, pPngInfo, &image_background)) //图象自带背景
  432. png_set_background(pPng, image_background,
  433.  PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
  434. else 
  435. png_set_background(pPng, &user_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
  436. /* 调整屏幕显示的GAMMA值 */
  437. /* screen gamma由CRT_gamma和环境矫正gamma组成 */
  438. /* 暂时不实现用户指定屏幕gamma */
  439. double screen_gamma;
  440. char *gamma_str;
  441. if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) //获取当前环境变量的值
  442. {
  443. screen_gamma = atof(gamma_str);
  444. }
  445. else
  446. {
  447. screen_gamma = 2.2;  /* A good guess for a PC monitors in a dimly
  448.   lit room */
  449. }
  450. /* 让LIBPNG处理gamma矫正 */
  451. /* 此处应支持用户输入图象gamma值 */
  452. int intent;
  453. if (png_get_sRGB(pPng, pPngInfo, &intent))
  454. png_set_gamma(pPng, screen_gamma, 0.45455); /* 对图象gamma的猜测 */
  455. else
  456. {
  457. double image_gamma;
  458. if (png_get_gAMA(pPng, pPngInfo, &image_gamma))
  459. png_set_gamma(pPng, screen_gamma, image_gamma);
  460. else
  461.  png_set_gamma(pPng, screen_gamma, 0.45455);
  462. }
  463. /* 将图象数据由RGB转换为BGR */
  464. png_set_bgr(pPng);
  465. /* 将灰度图转换为RGB图 */
  466. if (pngInfoHeader.color_type == PNG_COLOR_TYPE_GRAY || 
  467. pngInfoHeader.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)          
  468. png_set_gray_to_rgb(pPng);
  469. /* 打开INTERLACE处理器(使用png_read_row读图象时必须) */
  470. pngInfoHeader.number_passes = png_set_interlace_handling(pPng);
  471. /* 调用上述变换函数后必须,更新信息结构 */
  472. png_read_update_info(pPng, pPngInfo);
  473. // 下面开始读图象数据
  474. // 存储单元以在客户模块中分配
  475. DWORD Height = (pInfo->imginfo).height;
  476. DWORD dwBytes = (pInfo->imginfo).linesize;
  477. //分配读文件所需的数据缓冲区及行指针(必须)
  478. png_bytep* row_pointers = (png_bytep*)new PBYTE[Height];
  479. if(row_pointers == NULL)
  480. {
  481. pInfo->result = ER_MEMORYERR;
  482. __leave;
  483. }
  484. PBYTE pImage = new BYTE[Height * dwBytes];
  485. if(pImage == NULL)
  486. {
  487. delete []row_pointers;
  488. pInfo->result = ER_MEMORYERR;
  489. __leave;
  490. }
  491. //按24位位深度设置行指针,以正确读取图象数据
  492. for(DWORD row = 0; row < Height; row ++)
  493. row_pointers[row] = (png_bytep)(pImage + row * dwBytes);
  494. //设置JUMPBUFFER以便PNGLIB在遇到错误时能返回这里处理错误
  495. if (setjmp(png_jmpbuf(pPng)))
  496. {
  497. pInfo->result = ER_FILERWERR;
  498. __leave;
  499. }
  500. int pass;
  501. for(pass = 0; pass < pngInfoHeader.number_passes; pass++)
  502. {
  503. //每次读取一行图象
  504. for (row = 0L; row < Height; row++)
  505. {
  506. //调用回调函数,处理用户中断请求
  507. //这里的效果可能不太好,因为要在处理完一行数据之后才响应用户请求
  508. if(pInfo->fpProgress)
  509. {
  510. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, (100 * row * (pass + 1))/
  511. (Height * pngInfoHeader.number_passes)))
  512. { // 如果进度函数返回1,则说明用户想中断操作,返回。
  513. pInfo->result = ER_USERBREAK;
  514. __leave;
  515. }
  516. }
  517. //从文件中读取一行数据
  518. png_read_rows(pPng, &row_pointers[row], NULL, 1);
  519. }
  520. }
  521. //读取图象附加信息,包括zTxt、sTxt、tIME通道的信息
  522. //对这些信息暂不处理,以后可以加到pImginfo中传递给客户模块
  523. png_read_end(pPng, pPngInfo);
  524. //根据pInfo->sDIBInfo.bmi中提供的标准图象信息转换图象格式
  525. ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
  526. // 可接收三中格式的图像位数据请求:16,24,32。并且要求数据包位
  527. ASSERT((pInfo->sDIBInfo.bmi.biBitCount==16)||(pInfo->sDIBInfo.bmi.biBitCount==24)||(pInfo->sDIBInfo.bmi.biBitCount==32));
  528. if(pInfo->sDIBInfo.bmi.biBitCount == 16)
  529. {
  530. if(!Image24to16(pInfo, pImage, row_pointers))
  531. {
  532. //操作失败,释放内存
  533.   delete []pImage;
  534. delete []row_pointers;
  535. __leave;
  536. }
  537. }
  538. else if(pInfo->sDIBInfo.bmi.biBitCount == 32)
  539. {
  540. if(!Image24to32(pInfo, pImage, row_pointers))
  541. {
  542. delete []pImage;
  543. delete []row_pointers;
  544. __leave;
  545. }
  546. }
  547. else
  548. {
  549. //24位倒置、对齐并且拷贝到图象缓冲区中
  550. if(!Image24to24(pInfo, pImage, row_pointers))
  551. {
  552. delete []pImage;
  553. delete []row_pointers;
  554. __leave;
  555. }
  556. }
  557. //释放图象缓冲区
  558. delete []row_pointers;
  559. delete []pImage;
  560.  //成功!
  561.  pInfo->state = PKST_INFOANDBITS;
  562.  pInfo->result = ER_SUCCESS;
  563.  __leave;
  564. }
  565. __finally
  566. {
  567. //关闭PNG文件
  568. if(hPng != INVALID_HANDLE_VALUE)
  569. CloseHandle(hPng);
  570. //清除分配单元
  571. if(pPng != NULL)
  572. png_destroy_read_struct(&pPng, &pPngInfo, (png_infopp)NULL);
  573. }
  574. return;
  575. }
  576. // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
  577. // 将数据保存到指定文件中
  578. void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
  579. {
  580. // 检验入口参数是否符合接口定义
  581. ASSERT(pInfo->result == ER_EMPTY);
  582. ASSERT(::strlen(pInfo->filename));
  583. // 此时,该文件必需是一个已存在的、有效的WMF文件,并且数据包中
  584. // 含有该文件的信息(imginfo结构中)
  585. ASSERT(pInfo->state == PKST_INFOANDBITS);
  586. // 必须存在有效的图象信息
  587. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  588. ASSERT(pInfo->pLineAddr != NULL);
  589. ASSERT(pInfo->_pbdata != NULL);
  590. //仅支持16、24、32位位图
  591. if(pInfo->sDIBInfo.bmi.biBitCount == 1 || pInfo->sDIBInfo.bmi.biBitCount == 4 ||
  592. pInfo->sDIBInfo.bmi.biBitCount == 8)
  593. {
  594. pInfo->result = ER_NOTSUPPORT;
  595. return;
  596. }
  597. HANDLE hPng;
  598. png_structp pPng;
  599. png_infop pPngInfo;
  600. __try
  601. {
  602. //分配PNG结构,并初始化
  603. pPng = png_create_write_struct(PNG_LIBPNG_VER_STRING, 
  604. (png_voidp)::GetForegroundWindow(), PngErrorHandler, NULL);
  605. if(pPng == NULL)
  606. {
  607. pInfo->result = ER_MEMORYERR;
  608. __leave;
  609. }
  610. //建立PNG信息头结构
  611. pPngInfo = png_create_info_struct(pPng);
  612. if(pPngInfo == NULL)
  613. {
  614. pInfo->result = ER_MEMORYERR;
  615. __leave;
  616. }
  617. hPng = ::CreateFile(pInfo->filename, GENERIC_READ | GENERIC_WRITE, 
  618. FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  619. if(hPng == INVALID_HANDLE_VALUE) //打开文件错误
  620. {
  621. pInfo->result = ER_FILERWERR;
  622. __leave;
  623. }
  624. //设置自定义写函数
  625. png_set_write_fn(pPng, (PVOID)hPng, PngWrite4Win32, (png_flush_ptr)PngFlush4Win32);
  626.     if (setjmp(png_jmpbuf(pPng)))
  627.     {
  628. pInfo->result = ER_FILERWERR;
  629. __leave;
  630. }
  631. //设置并写文件信息头
  632. pngSetIHDR(pPng, pPngInfo, pInfo);
  633. //图象变换
  634. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  635. DWORD BitCount = bmpInfo.biBitCount;
  636. DWORD Height = bmpInfo.biHeight;
  637. DWORD Width = bmpInfo.biWidth;
  638. PBYTE pngImage;
  639. PBYTE* row_pointers;
  640. pngImage = new BYTE[Height * Width * 3];
  641. if(pngImage == NULL)
  642. {
  643. pInfo->result = ER_MEMORYERR;
  644. __leave;
  645. }
  646. row_pointers = new PBYTE[Height];
  647. if(row_pointers == NULL)
  648. {
  649. pInfo->result = ER_MEMORYERR;
  650. __leave;
  651. }
  652. if(BitCount == 16)
  653. {
  654. if(!TransformImage16(pInfo, pngImage))
  655. {
  656. delete []pngImage;
  657. delete []row_pointers;
  658. __leave;
  659. }
  660. //置行指针,行指针倒置,因为PNG图象是top-down排列的
  661. for(DWORD i = 0; i < Height; i++)
  662. row_pointers[i] = pngImage + Width * 3 * (Height - i - 1);
  663. }
  664. else if(BitCount == 24)
  665. {
  666. if(!TransformImage24(pInfo, pngImage))
  667. {
  668. delete []pngImage;
  669. delete []row_pointers;
  670. __leave;
  671. }
  672. for(DWORD i = 0; i < Height; i++)
  673. row_pointers[i] = pngImage + Width * 3 * (Height - i - 1);
  674. }
  675. else //if(BitCount == 32)
  676. {
  677. if(!TransformImage32(pInfo, pngImage))
  678. {
  679. delete []pngImage;
  680. delete []row_pointers;
  681. __leave;
  682. }
  683. for(DWORD i = 0; i < Height; i++)
  684. row_pointers[i] = pngImage + Width * 3 * (Height - i - 1);
  685. }
  686. //写图象
  687. /* 这里用交错格式(interlaced)存储 */
  688. DWORD number_passes = png_set_interlace_handling(pPng);
  689.     for (DWORD pass = 0; pass < number_passes; pass++)
  690. /* 一次只写入一行 */
  691.     for (DWORD y = 0; y < Height; y++)
  692. //进度函数调用
  693. if(pInfo->fpProgress)
  694. {
  695. if ((*(pInfo->fpProgress))(RWPROGRESSSIZE, pass * y * 100 / (pass * Height)))
  696. {
  697. pInfo->result = ER_USERBREAK;
  698. __leave;
  699. }
  700. png_write_rows(pPng, &row_pointers[y], 1);
  701.     /* 这里可以写入tEXt, zTXt, and tIME */
  702. /* 写入IEND通道,必须 */
  703. png_write_end(pPng, pPngInfo);
  704. delete []pngImage;
  705. delete []row_pointers;
  706. /* 使用png_free释放用png_malloced分配的调色板或其他单元 */
  707. //png_free(pPng, palette);
  708. pInfo->result = ER_SUCCESS;
  709. }
  710. __finally
  711. {
  712. //关闭PNG文件
  713. if(hPng != INVALID_HANDLE_VALUE)
  714. CloseHandle(hPng);
  715. //清除分配单元
  716. if(pPng != NULL)
  717. png_destroy_write_struct(&pPng, &pPngInfo);
  718. }
  719. return;
  720. }
  721. // 操作命令解释函数---解释:CMD_RESIZE命令
  722. // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
  723. void _fnCMD_RESIZE(INFOSTR *pInfo)
  724. {
  725. pInfo->result = ER_NOTSUPPORT;
  726. return;
  727. }
  728. /* ====================================================================================== */
  729. /* 内部处理函数   */
  730. /* ====================================================================================== */
  731. /*
  732.  * PNG库自定义错误处理函数
  733.  * 
  734.  */
  735. static void
  736. PngErrorHandler(png_structp png_ptr, png_const_charp message)
  737. {
  738. TRACE("错误:%s", message);
  739. CString ErrMsg = "错误:";
  740. ErrMsg += message; 
  741. ::MessageBox((HWND)png_ptr->error_ptr, ErrMsg, NULL, 0);
  742. #ifdef PNG_SETJMP_SUPPORTED
  743. #  ifdef USE_FAR_KEYWORD
  744.    {
  745.       jmp_buf jmpbuf;
  746.       png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
  747.       longjmp(jmpbuf, 1);
  748.    }
  749. #  else
  750.    longjmp(png_ptr->jmpbuf, 1);
  751. # endif
  752. #else
  753.    if (png_ptr == NULL)
  754.      /* make compiler happy */ ;
  755.    PNG_ABORT();
  756. #endif
  757. }
  758. /* ==============================
  759.  * PNG库自定义读函数
  760.  * 参数:
  761.  * data — 返回数据缓冲区
  762.  * length — 读数据长度
  763.  */
  764. static void
  765. PngRead4Win32(png_structp png_ptr, png_bytep data, png_size_t length)
  766. {
  767.    HANDLE m_hPng;
  768.    m_hPng = (HANDLE)CVT_PTR(png_ptr->io_ptr);
  769.    if(m_hPng != NULL)
  770.    {
  771.    DWORD dwBytes;
  772.    BOOL Correct = ReadFile(m_hPng, (PVOID)data, (DWORD)length, &dwBytes, NULL);
  773.    if(!Correct || dwBytes != (DWORD)length)
  774.    {
  775.    png_error(png_ptr, "Read Error");
  776.    }
  777.    }
  778. }
  779. /* ==============================
  780.  * PNG库自定义写函数
  781.  * 参数:
  782.  * data — 数据缓冲区
  783.  * length — 数据长度
  784.  */
  785. static void
  786. PngWrite4Win32(png_structp png_ptr, png_bytep data, png_size_t length)
  787. {
  788.    HANDLE m_hPng;
  789.    m_hPng = (HANDLE)CVT_PTR(png_ptr->io_ptr);
  790.    if(m_hPng != NULL)
  791.    {
  792.    DWORD dwBytes;
  793.    BOOL Correct = WriteFile(m_hPng, (PVOID)data, (DWORD)length, &dwBytes, NULL);
  794.    if(!Correct || dwBytes != (DWORD)length)
  795.    {
  796.    png_error(png_ptr, "Write Error");
  797.    }
  798.    }
  799. }
  800. /* ==============================
  801.  * PNG库自定义FLUSH函数
  802.  * 参数:
  803.  * data — 数据缓冲区
  804.  * length — 数据长度
  805.  */
  806. static void
  807. PngFlush4Win32(png_structp png_ptr)
  808. {
  809.    HANDLE m_hPng;
  810.    m_hPng = (HANDLE)CVT_PTR(png_ptr->io_ptr);
  811.    if (m_hPng != NULL)
  812.    {
  813.    BOOL Correct = FlushFileBuffers(m_hPng);
  814.    if(!Correct)
  815.        png_error(png_ptr, "Flush Error");
  816.    }
  817. }
  818. /* ==========================================================================*
  819.  * 图象的输出格式将根据用户的需要进行适当的变换
  820.  * 下面的一组函数用于将图象由从PNG读出时的24位变换为输出格式
  821.  * ==========================================================================*/
  822. /* 
  823.  * 将图象由24位转换为32位
  824.  */
  825. BOOL Image24to32(INFOSTR *pInfo, PBYTE pImage, PBYTE* pLineAddr)
  826. {
  827. DWORD Height = (pInfo->imginfo).height;
  828. DWORD Width = (pInfo->imginfo).width;
  829. PBYTE p2 = pInfo->_pbdata;
  830. PBYTE p1;// = pImage;
  831. PBYTE *pLine = pLineAddr + Height - 1;
  832. for(DWORD y = 0L; y < Height; y++)
  833. {
  834. if(pInfo->fpProgress)
  835. {
  836. if ((*(pInfo->fpProgress))(RWPROGRESSSIZE, y * 100 / Height))
  837. {
  838. pInfo->result = ER_USERBREAK;
  839. return FALSE;
  840. }
  841. }
  842. p1 = *(pLine --);
  843. for(DWORD i = 0L; i < Width; i ++)
  844. {
  845. *p2++ = *p1++;
  846. *p2++ = *p1++;
  847. *p2++ = *p1++;
  848. *p2++ = 0;
  849. }
  850. }
  851. return TRUE;
  852. }
  853. /*
  854.  * 将位图转换为16位
  855.  */
  856. BOOL Image24to16(INFOSTR *pInfo, PBYTE pImage, PBYTE* pLineAddr)
  857. {
  858. DWORD BMask = (pInfo->sDIBInfo).bmask;
  859. DWORD RMask = (pInfo->sDIBInfo).rmask;
  860. DWORD GMask = (pInfo->sDIBInfo).gmask;
  861. DWORD Height = (pInfo->imginfo).height;
  862. DWORD Width = (pInfo->imginfo).width;
  863. if(pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  864. {
  865. BMask = 0x0000001F;
  866. GMask = 0x000003E0;
  867. RMask = 0x00007C00; 
  868. }
  869. PWORD p2 = (PWORD)pInfo->_pbdata;
  870. PBYTE p1;// = pImage;
  871. PBYTE *pLine = pLineAddr + Height - 1;
  872. WORD Red, Blue, Green;
  873. WORD rs;
  874. double Rmax24, Bmax24, Gmax24;
  875. double Rmax16, Bmax16, Gmax16;
  876. Rmax24 = Bmax24 = Gmax24 = (1 << 8) - 1;
  877. Rmax16 = Bmax16 = (1 << 5) - 1;
  878. if(GMask == 0x000003E0)
  879. {
  880. Gmax16 = (1 << 5) - 1;
  881. rs = 10;
  882. }
  883. else
  884. {
  885. rs = 11;
  886. Gmax16 = (1 << 6) - 1;
  887. }
  888. for(DWORD y = 0L; y < Height; y++)
  889. {
  890. if(pInfo->fpProgress)
  891. {
  892. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, y * 100 / Height))
  893. {
  894. pInfo->result = ER_USERBREAK;
  895. return FALSE;
  896. }
  897. }
  898. p1 = *(pLine --);
  899. for(DWORD i = 0; i < Width; i++)
  900. {
  901. //为保持与原图基本一致应按比例变化
  902. Blue = (WORD)((double)(*p1++) * Bmax16 / Bmax24) & BMask;
  903. Green = ((WORD)((double)(*p1++) * Gmax16 / Gmax24) << 5) & GMask;
  904. Red = ((WORD)((double)(*p1++) * Rmax16 / Rmax24) << rs) & RMask;
  905. *p2++ = Blue | Green | Red;
  906. }
  907. //考虑DWORD对齐
  908. if(Width % 2)
  909. *p2++  = 255; //边界用白色填充
  910. }
  911. return TRUE;
  912. }
  913. /*
  914.  * 24位位图倒置,并且按DWORD边界对齐
  915.  */
  916. BOOL Image24to24(INFOSTR *pInfo, PBYTE pImage, PBYTE* pLineAddr)
  917. {
  918. DWORD Height = (pInfo->imginfo).height;
  919. DWORD Width = (pInfo->imginfo).width * 3;
  920. DWORD Linesize = (Width + sizeof(DWORD) - 1) / sizeof(DWORD) * sizeof(DWORD);
  921. PBYTE p1;
  922. PBYTE p2 = pInfo->_pbdata;
  923. PBYTE *pLine = pLineAddr + Height - 1;
  924. for(DWORD y = 0L; y < Height; y++)
  925. {
  926. if(pInfo->fpProgress)
  927. {
  928. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, y * 100 / Height))
  929. {
  930. pInfo->result = ER_USERBREAK;
  931. return FALSE;
  932. }
  933. }
  934. p1 = *(pLine--);
  935. memcpy(p2, p1, Width);
  936. //DWORD对齐
  937. memset(p2 + Width, 255, Linesize - Width);
  938. p2 += Linesize;
  939. }
  940. return TRUE;
  941. }
  942. /* ===============================================================================*
  943.  * 设置PNG头信息,并且写PNG文件头
  944.  * ===============================================================================*/
  945. /*
  946.  * 根据BMP信息头设置PNG文件信息头
  947.  */
  948. void pngSetIHDR(png_structp pPng, png_infop pPngInfo, INFOSTR *pInfo)
  949. {
  950. //所有的PNG文件都保存为color type 2, bitdepth 8(24位), 无alpha通道的图形
  951. DWORD Height, Width;
  952. int color_type, bit_depth;
  953. int compression_type, filter_type;
  954. int interlace_type = PNG_INTERLACE_ADAM7; //缺省设置为ADAM7交错图象
  955. compression_type = PNG_COMPRESSION_TYPE_DEFAULT; //缺省压缩类型
  956. filter_type = PNG_FILTER_TYPE_DEFAULT; //缺省FILTER
  957. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  958. Height = bmpInfo.biHeight; //图象真实高度
  959. Width = bmpInfo.biWidth; //图象真实宽度
  960. int BitCount = bmpInfo.biBitCount;
  961. color_type = 2; //RGB图
  962. bit_depth = 8;
  963. png_set_IHDR(pPng, pPngInfo, Width, Height, bit_depth, color_type,
  964. interlace_type, compression_type, filter_type);
  965. if(BitCount == 16)
  966. {
  967. //设置真实位数通道
  968. png_color_8 sig_bit;
  969. sig_bit.red = 5;
  970. sig_bit.blue = 5;
  971. sig_bit.green = 5;
  972. if(bmpInfo.biCompression == BI_BITFIELDS)
  973. if(pInfo->sDIBInfo.gmask == 0x07E0)
  974. sig_bit.green = 6;
  975. png_set_sBIT(pPng, pPngInfo, &sig_bit);
  976. }
  977. //将信息写入信息头
  978. png_write_info(pPng, pPngInfo);
  979. }
  980. /* ============================================================================*
  981.  * 调用PNGLIB存储图象之前先将图象数据转换为PNG格式的数据
  982.  * 下面的几个函数用于将图象由BMP格式转换为PNG格式
  983.  * ============================================================================*/
  984. /*
  985.  * 图象变换,将16位图象扩展为24位,并按BGR格式排列
  986.  */
  987. BOOL TransformImage16(INFOSTR *pInfo, PBYTE pngImage)
  988. {
  989. PBYTE pImage = (PBYTE)pInfo->_pbdata;
  990. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  991. ASSERT(bmpInfo.biBitCount == 16);
  992. DWORD gMask, bMask, rMask;
  993. bMask = 0x001F;
  994. gMask = 0x03E0;
  995. rMask = 0x7C00;
  996. if(bmpInfo.biCompression == BI_BITFIELDS)
  997. {
  998. bMask = pInfo->sDIBInfo.bmask;
  999. gMask = pInfo->sDIBInfo.gmask;
  1000. rMask = pInfo->sDIBInfo.rmask;
  1001. }
  1002. int rs = 10;
  1003. DWORD Rmax16, Gmax16, Bmax16;
  1004. DWORD Rmax24, Gmax24, Bmax24;
  1005. Rmax16 = Gmax16 = Bmax16 = (1 << 5) - 1;
  1006. Rmax24 = Gmax24 = Bmax24 = (1 << 8) - 1;
  1007. if(gMask == 0x07e0)
  1008. {
  1009. rs = 10;
  1010. Gmax16 = (1 << 6) - 1;
  1011. }
  1012. DWORD height = bmpInfo.biHeight;
  1013. DWORD width = bmpInfo.biWidth;
  1014. DWORD linesize = DIBSCANLINE_WIDTHBYTES(width * bmpInfo.biBitCount);
  1015. PWORD pRow = (PWORD)pImage;
  1016. PBYTE p = pngImage;
  1017. for(DWORD row = 0; row < height; row ++)
  1018. {
  1019. pRow = (WORD*)(pImage + linesize * row);
  1020. //进度控制
  1021. if(pInfo->fpProgress)
  1022. {
  1023. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, row * 100 / height))
  1024. {
  1025. pInfo->result = ER_USERBREAK;
  1026. return FALSE;
  1027. }
  1028. }
  1029. for(DWORD i = 0; i < width; i++)
  1030. {
  1031. WORD red = (*pRow) & rMask;
  1032. WORD green = *pRow & gMask;
  1033. *p++ = (BYTE)((double)(red >> rs) * (double)Rmax24 / (double)Rmax16); //red
  1034. *p++ = (BYTE)((double)(green >> 5) * (double)Gmax24 / (double)Gmax16); //green
  1035. *p++ = (BYTE)((double)(*pRow & bMask) * (double)Bmax24 / (double)Bmax16);//blue
  1036. pRow ++;
  1037. }
  1038. }
  1039. return TRUE;
  1040. }
  1041. /*
  1042.  * 24位图象变换,24位图象可以不用变换,直接拷贝图象即可。
  1043.  *
  1044.  * 这里去掉为DWORD对齐而增加的填充字节。
  1045.  *
  1046.  */
  1047. BOOL TransformImage24(INFOSTR *pInfo, PBYTE pngImage)
  1048. {
  1049. PBYTE pImage = (PBYTE)pInfo->_pbdata;
  1050. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  1051. ASSERT(bmpInfo.biBitCount == 24);
  1052. DWORD height = bmpInfo.biHeight;
  1053. DWORD width = bmpInfo.biWidth;
  1054. DWORD linesize = DIBSCANLINE_WIDTHBYTES(width * bmpInfo.biBitCount);
  1055. PBYTE pRow = pImage;
  1056. PBYTE p = pngImage;
  1057. for(DWORD row = 0; row < height; row ++)
  1058. {
  1059. pRow = pImage + row * linesize;
  1060. //进度控制
  1061. if(pInfo->fpProgress)
  1062. {
  1063. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, row * 100 / height))
  1064. {
  1065. pInfo->result = ER_USERBREAK;
  1066. return FALSE;
  1067. }
  1068. }
  1069. for(DWORD i = 0; i < width; i++)
  1070. {
  1071. *p++ = *(pRow + 2); //red
  1072. *p++ = *(pRow + 1); //green
  1073. *p++ = *(pRow); //blue
  1074. pRow += 3;
  1075. }
  1076. }
  1077. return TRUE;
  1078. }
  1079. /*
  1080.  * 32位图象转换,去掉最高的未用字节
  1081.  */
  1082. BOOL TransformImage32(INFOSTR* pInfo, PBYTE pngImage)
  1083. {
  1084. PBYTE pImage = (PBYTE)pInfo->_pbdata;
  1085. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  1086. ASSERT(bmpInfo.biBitCount == 32);
  1087. DWORD height = bmpInfo.biHeight;
  1088. DWORD width = bmpInfo.biWidth;
  1089. DWORD linesize = DIBSCANLINE_WIDTHBYTES(width * bmpInfo.biBitCount);
  1090. PBYTE pRow = pImage;
  1091. PBYTE p = pngImage;
  1092. for(DWORD row = 0; row < height; row ++)
  1093. {
  1094. pRow = pImage + row * linesize;
  1095. //进度控制
  1096. if(pInfo->fpProgress)
  1097. {
  1098. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, row * 100 / height))
  1099. {
  1100. pInfo->result = ER_USERBREAK;
  1101. return FALSE;
  1102. }
  1103. }
  1104. for(DWORD i = 0; i < width; i++)
  1105. {
  1106. *p++ = *(pRow + 2); //red
  1107. *p++ = *(pRow + 1); //green
  1108. *p++ = *(pRow); //blue
  1109. pRow += 4;
  1110. }
  1111. }
  1112. return TRUE;
  1113. }
  1114. /*
  1115.  * 1、4、8位位图象转换,无需转换,直接拷贝
  1116.  */
  1117. BOOL TransformImage1_4_8(INFOSTR* pInfo, PBYTE pngImage)
  1118. {
  1119. PBYTE pImage = (PBYTE)pInfo->_pbdata;
  1120. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  1121. DWORD height = bmpInfo.biHeight;
  1122. DWORD linesize = DIBSCANLINE_WIDTHBYTES(bmpInfo.biWidth * bmpInfo.biBitCount);
  1123. memcpy(pngImage, pImage, height * linesize);
  1124. return TRUE;
  1125. }