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

图形图象

开发平台:

Visual C++

  1. /********************************************************************
  2. JpegModule.cpp - ISee图像浏览器—JPEG图像读写模块实现文件
  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. 编写人:orbit
  21. E-Mail:Inte2000@263.net
  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 "JpegModule.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[]="JPEG,JPG"; // 本模块能处理的图像类型
  36. static char WriterList[]="orbit"; // 本模块的作者列表
  37. static char WriterMess[]="死不了人的!"; // 作者留言
  38. //@@@@@@@@@@@@ YZ 于2000-12-9增加以下两行代码@@@@@@@@@@@@@
  39. static int  RWPROGRESSSIZE;
  40. static const int RWPROGRESSSTEP = 10;
  41. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  42. //
  43. // Note!
  44. //
  45. // If this DLL is dynamically linked against the MFC
  46. // DLLs, any functions exported from this DLL which
  47. // call into MFC must have the AFX_MANAGE_STATE macro
  48. // added at the very beginning of the function.
  49. //
  50. // For example:
  51. //
  52. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  53. // {
  54. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  55. // // normal function body here
  56. // }
  57. //
  58. // It is very important that this macro appear in each
  59. // function, prior to any calls into MFC.  This means that
  60. // it must appear as the first statement within the 
  61. // function, even before any object variable declarations
  62. // as their constructors may generate calls into the MFC
  63. // DLL.
  64. //
  65. // Please see MFC Technical Notes 33 and 58 for additional
  66. // details.
  67. //
  68. // 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
  69. // ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
  70. // 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
  71. //
  72. //
  73. /////////////////////////////////////////////////////////////////////////////
  74. // CJpegModuleApp
  75. BEGIN_MESSAGE_MAP(CJpegModuleApp, CWinApp)
  76. //{{AFX_MSG_MAP(CJpegModuleApp)
  77. // NOTE - the ClassWizard will add and remove mapping macros here.
  78. //    DO NOT EDIT what you see in these blocks of generated code!
  79. //}}AFX_MSG_MAP
  80. END_MESSAGE_MAP()
  81. /////////////////////////////////////////////////////////////////////////////
  82. // CJpegModuleApp construction
  83. CJpegModuleApp::CJpegModuleApp()
  84. {
  85. // TODO: add construction code here,
  86. // Place all significant initialization in InitInstance
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. // The one and only CJpegModuleApp object
  90. CJpegModuleApp theApp;
  91. // 接口函数声明 — 第一层,唯一与外界联系的接口
  92. int WINAPI AccessJPEGModule(INFOSTR *pInfo)
  93. {
  94. // 这个函数可以不作修改的使用,除非你的返回值多于两种。
  95. switch(pInfo->comm)
  96. {
  97. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  98. _fnCMD_GETPROCTYPE(pInfo);
  99. break;
  100. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  101. _fnCMD_GETWRITERS(pInfo);
  102. break;
  103. case CMD_GETWRITERMESS: // 获取作者们的留言
  104. _fnCMD_GETWRITERMESS(pInfo);
  105. break;
  106. case CMD_GETBUILDID: // 获取图像模块内部版本号
  107. _fnCMD_GETBUILDID(pInfo);
  108. break;
  109. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  110. _fnCMD_IS_VALID_FILE(pInfo);
  111. break;
  112. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  113. _fnCMD_GET_FILE_INFO(pInfo);
  114. break;
  115. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  116. _fnCMD_LOAD_FROM_FILE(pInfo);
  117. break;
  118. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  119. _fnCMD_SAVE_TO_FILE(pInfo);
  120. break;
  121. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  122. _fnCMD_IS_SUPPORT(pInfo);
  123. break;
  124. case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
  125. _fnCMD_RESIZE(pInfo);
  126. break;
  127. default:
  128. pInfo->result = ER_ILLCOMM; // 非法命令
  129. ASSERT(FALSE); // 调用者的程序设计有问题 :-)
  130. break;
  131. }
  132. // 执行命令成功返回1, 失败返回0
  133. return (pInfo->result==ER_SUCCESS)? 1:0;
  134. }
  135. // 命令解释函数 — 第二层解释函数
  136. //********************************************************************//
  137. // 操作命令解释函数---解释:CMD_IS_SUPPORT命令
  138. // 查询某个命令是否被支持
  139. void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
  140. {
  141. // 这个函数是为客户程序查询时使用,如果你实现了对某个命令的
  142. // 解释,可修改相应的case中的设置,使其返回ER_SUCCESS,这就
  143. // 表示你的模块已经支持该命令了。同时,现在的这个文件中已包
  144. // 含了对前四个命令的解释,你只需向还未支持的命令函数中添加
  145. // 代码即可。
  146. ASSERT(pInfo->result == ER_EMPTY);
  147. switch(pInfo->annexdata.cmAnnData)  
  148. {
  149. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  150. pInfo->result = ER_SUCCESS;
  151. break;
  152. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  153. pInfo->result = ER_SUCCESS;
  154. break;
  155. case CMD_GETWRITERMESS: // 获取作者们的留言
  156. pInfo->result = ER_SUCCESS;
  157. break;
  158. case CMD_GETBUILDID: // 获取图像模块内部版本号
  159. pInfo->result = ER_SUCCESS;
  160. break;
  161. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  162. pInfo->result = ER_SUCCESS;
  163. break;
  164. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  165. pInfo->result = ER_SUCCESS;
  166. break;
  167. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  168. pInfo->result = ER_SUCCESS;
  169. break;
  170. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  171. pInfo->result = ER_SUCCESS;
  172. break;
  173. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  174. pInfo->result = ER_SUCCESS;
  175. break;
  176. case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
  177. pInfo->result = ER_NOTSUPPORT;
  178. break;
  179. default:
  180. pInfo->result = ER_NOTSUPPORT;
  181. break;
  182. }
  183. }
  184. // 操作命令解释函数---解释:CMD_GETPROCTYPE命令
  185. // 获取本模块能处理的图像类型,如:BMP,PCX等等
  186. void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
  187. {
  188. // 这是预定义的函数代码,你可以不必修改的使用。
  189. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  190. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  191. ASSERT(pInfo->result == ER_EMPTY);
  192. // 复制能处理的类型字符串
  193. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType, 
  194. sizeof(ModuleProcessImgType));
  195. pInfo->result = ER_SUCCESS;
  196. }
  197. // 操作命令解释函数---解释:CMD_GETWRITER命令
  198. // 获取本模块的作者列表,多人时用逗号分隔
  199. void _fnCMD_GETWRITERS(INFOSTR *pInfo)
  200. {
  201. // 这是预定义的函数代码,你可以不必修改的使用。
  202. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  203. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  204. ASSERT(pInfo->result == ER_EMPTY);
  205. // 复制开发者名单串
  206. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList, 
  207. sizeof(WriterList));
  208. pInfo->result = ER_SUCCESS;
  209. }
  210. // 操作命令解释函数---解释:CMD_GETWRITERMESS命令
  211. // 获取作者们的留言
  212. void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
  213. {
  214. // 这是预定义的函数代码,你可以不必修改的使用。
  215. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  216. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  217. ASSERT(pInfo->result == ER_EMPTY);
  218. // 复制开发者们的留言字符串
  219. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess, 
  220. sizeof(WriterMess));
  221. pInfo->result = ER_SUCCESS;
  222. }
  223. // 操作命令解释函数---解释:CMD_GETBUILDID命令
  224. // 获取图像模块内部版本号
  225. void _fnCMD_GETBUILDID(INFOSTR *pInfo)
  226. {
  227. // 这是预定义的函数代码,你可以不必修改的使用。
  228. // 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
  229. ASSERT(pInfo->annexdata.dwAnnData == 0);
  230. ASSERT(pInfo->result == ER_EMPTY);
  231. // 填写内部版本号码
  232. pInfo->annexdata.dwAnnData = MODULE_BUILDID;
  233. pInfo->result = ER_SUCCESS;
  234. }
  235. // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
  236. // 判断指定文件是否是有效的JPG文件
  237. void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
  238. {
  239. ASSERT(pInfo);
  240. ASSERT(pInfo->result == ER_EMPTY);
  241. ASSERT(pInfo->annexdata.iAnnData == 0);
  242. ASSERT(::strlen(pInfo->filename));
  243. ASSERT(pInfo->state == PKST_NOTVER);
  244. WORD wMarker;
  245. HANDLE hFile;
  246. pInfo->result = ER_SUCCESS;
  247. pInfo->annexdata.iAnnData = 0;
  248. hFile = ::CreateFile(pInfo->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
  249. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  250. if(hFile == INVALID_HANDLE_VALUE)
  251. pInfo->result = ER_COMMINFOERR; //文件打开错
  252. else
  253. {
  254. DWORD dwBytes; 
  255. BOOL Correct = ::ReadFile(hFile, &wMarker, 2, &dwBytes, NULL);
  256. if(!Correct)
  257. {
  258. pInfo->result = ER_FILERWERR;
  259. TRACE("JPEG-读文件错误!");
  260. ::CloseHandle(hFile);
  261. return;
  262. }
  263. if(!CHECK_JPG_SOI(wMarker))
  264. pInfo->annexdata.iAnnData = 0;
  265. else
  266. {
  267. pInfo->annexdata.iAnnData = 1;
  268. pInfo->state = PKST_PASSVER;
  269. }
  270. CloseHandle(hFile);
  271. }
  272. }
  273. // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
  274. // 获取指定文件的信息
  275. void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
  276. {
  277. // 检验入口参数是否符合接口定义
  278. ASSERT(pInfo->result == ER_EMPTY);
  279. ASSERT(::strlen(pInfo->filename));
  280. ASSERT(pInfo->state == PKST_PASSVER);
  281. ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
  282. struct jpeg_decompress_struct cinfo;
  283. struct my_error_mgr jerr;
  284. FILE * infile=NULL;
  285. if ((infile = fopen(pInfo->filename, "rb")) == NULL) 
  286. {
  287. pInfo->result = ER_FILERWERR;
  288. return;
  289. }
  290. cinfo.err = jpeg_std_error(&jerr.pub);
  291. jerr.pub.error_exit = my_error_exit;
  292. if (setjmp(jerr.setjmp_buffer)) 
  293. {
  294. //如果代码执行到这里就说明JPEG解码出现错误
  295. jpeg_destroy_decompress(&cinfo);
  296. if (infile!=NULL)
  297. fclose(infile);
  298. pInfo->result = ER_BADIMAGE;
  299. return;
  300. }
  301. jpeg_create_decompress(&cinfo);
  302. jpeg_stdio_src(&cinfo, infile);
  303. jpeg_read_header(&cinfo, TRUE);
  304. fseek(infile,0,SEEK_END);
  305. DWORD dwSize = ftell(infile);
  306. fseek(infile,0,SEEK_SET);
  307. // jpeg_finish_decompress(&cinfo);
  308. jpeg_destroy_decompress(&cinfo);
  309. fclose(infile);
  310. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  311. lpImgInfoStr->imgtype = IMT_RESSTATIC;
  312. lpImgInfoStr->imgformat = IMF_JPEG;
  313. lpImgInfoStr->filesize = dwSize;
  314. lpImgInfoStr->width = cinfo.image_width;
  315. lpImgInfoStr->height = cinfo.image_height;
  316. lpImgInfoStr->bitcount = DWORD((cinfo.num_components == 3) ? 24 : 8);
  317. lpImgInfoStr->compression = CompressType(cinfo.jpeg_color_space);
  318. lpImgInfoStr->linesize = DIBSCANLINE_WIDTHBYTES(lpImgInfoStr->width*lpImgInfoStr->bitcount);
  319. lpImgInfoStr->imgnumbers = 1;
  320. lpImgInfoStr->imgchang = 0;
  321. HANDLE hFile; 
  322. FILETIME fLWT;
  323. SYSTEMTIME sLWT;
  324. hFile = ::CreateFile(pInfo->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
  325. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  326. if(::GetFileTime(hFile, NULL, NULL, &fLWT))
  327. {
  328. ::CloseHandle(hFile);
  329. FileTimeToSystemTime(&fLWT, &sLWT);
  330. lpImgInfoStr->year = sLWT.wYear;
  331. lpImgInfoStr->monday = sLWT.wMonth;
  332. lpImgInfoStr->monday <<= 8;
  333. lpImgInfoStr->monday |= sLWT.wDay;
  334. lpImgInfoStr->time = sLWT.wHour;
  335. lpImgInfoStr->time <<= 8;
  336. lpImgInfoStr->time |= sLWT.wMinute;
  337. lpImgInfoStr->time <<= 8;
  338. lpImgInfoStr->time |= sLWT.wSecond;
  339. lpImgInfoStr->time &= 0xffffff;
  340. pInfo->state = PKST_PASSINFO;
  341. pInfo->result = ER_SUCCESS;
  342. }
  343. else
  344. pInfo->result = ER_FILERWERR;
  345. }
  346. // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
  347. // 从指定图像文件中读取数据
  348. void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
  349. {
  350. ASSERT(pInfo->result == ER_EMPTY);
  351. ASSERT(::strlen(pInfo->filename));
  352. ASSERT(pInfo->state == PKST_PASSINFO);
  353. ASSERT(pInfo->imginfo.imgformat == IMF_JPEG);
  354. ASSERT(pInfo->pImgInfo == NULL);
  355. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  356. ASSERT(pInfo->pLineAddr != NULL);
  357. ASSERT(pInfo->_pbdata != NULL);
  358. struct jpeg_decompress_struct cinfo;
  359. struct my_error_mgr jerr;
  360. FILE * infile=NULL;
  361. JSAMPARRAY buffer;
  362. int row_stride;
  363. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9增加以下代码@@@@@@@@@@@@
  364. // 以图像的高度值作为进度总值
  365. RWPROGRESSSIZE = (int)pInfo->imginfo.height;
  366. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  367. if (pInfo->fpProgress)
  368. {
  369. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  370. { // 如果进度函数返回1,则说明用户想中断操作,返回。
  371. pInfo->result = ER_USERBREAK;
  372. return;
  373. }
  374. }
  375. if ((infile = fopen(pInfo->filename, "rb")) == NULL) 
  376. {
  377. pInfo->result = ER_FILERWERR;
  378. return;
  379. }
  380. cinfo.err = jpeg_std_error(&jerr.pub);
  381. jerr.pub.error_exit = my_error_exit;
  382. if (setjmp(jerr.setjmp_buffer)) 
  383. {
  384. //如果代码执行到这里就说明JPEG解码出现错误
  385. jpeg_destroy_decompress(&cinfo);
  386. if (infile!=NULL)
  387. fclose(infile);
  388. pInfo->result = ER_BADIMAGE;
  389. return;
  390. }
  391. jpeg_create_decompress(&cinfo);
  392. jpeg_stdio_src(&cinfo, infile);
  393. jpeg_read_header(&cinfo, TRUE);
  394. jpeg_start_decompress(&cinfo);
  395. row_stride = cinfo.output_width * cinfo.output_components;
  396. buffer = (*cinfo.mem->alloc_sarray)
  397. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
  398. LPBYTE pData;
  399. BYTE  red, green, blue,gray;
  400. DWORD widthCount;
  401. //JPEG只支持两种格式的图象
  402. if (cinfo.out_color_components == 3)//24位彩色图象
  403. {
  404. while (cinfo.output_scanline < cinfo.output_height) 
  405. {
  406. jpeg_read_scanlines(&cinfo, buffer, 1);
  407. pData = buffer[0];
  408. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9修改以下代码@@@@@@@@@@@@
  409. /*
  410. if(pInfo->fpProgress)
  411. {
  412. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.output_scanline * 100 / cinfo.output_height))
  413. {
  414. pInfo->result = ER_USERBREAK;
  415. return ;
  416. }
  417. }
  418. */
  419. // 为:
  420. if ((pInfo->fpProgress)&&(!(cinfo.output_scanline%RWPROGRESSSTEP)))
  421. {
  422. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.output_scanline))
  423. {
  424. pInfo->result = ER_USERBREAK;
  425. jpeg_destroy_decompress(&cinfo);
  426. fclose(infile);
  427. return ; // 用户中断操作
  428. }
  429. }
  430. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  431. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  432. {
  433. case DF_16_555:
  434. {
  435. WORD *pDesPixAddr555 = (WORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];
  436. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  437. {
  438. red = *pData++;
  439. green = *pData++;
  440. blue = *pData++; 
  441. *pDesPixAddr555++ = WORD((((WORD)red>>3)<<10)|(((WORD)green>>3)<<5)|((WORD)blue>>3));
  442. }
  443. }
  444. break;
  445. case DF_16_565:
  446. {
  447. WORD *pDesPixAddr565 = (WORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];
  448. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  449. {
  450. red = *pData++;
  451. green = *pData++; 
  452. blue = *pData++;
  453. *pDesPixAddr565++ = WORD((((WORD)red>>3)<<11)|(((WORD)green>>2)<<5)|((WORD)blue>>3));
  454. }
  455. }
  456. break;
  457. case DF_24:
  458. ::CopyMemory((PVOID)pInfo->pLineAddr[cinfo.output_scanline - 1], (PVOID)pData, cinfo.output_width * 3);
  459. break;
  460. case DF_32:
  461. {
  462. DWORD *pDesPixAddr888;
  463. DWORD pix32;
  464. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];// 目标缓冲区当前行第一个像素的地址
  465. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  466. {
  467. red = *pData++;
  468. green = *pData++; 
  469. blue = *pData++;
  470. pix32 = DWORD(((DWORD)red<<16)|((DWORD)green<<8)|(DWORD)blue);
  471. pix32 &= 0x00FFFFFF;
  472. *pDesPixAddr888++ = pix32;
  473. }
  474. }
  475. break;
  476. case DF_NULL:
  477. default:
  478. ASSERT(FALSE);
  479. pInfo->result = ER_ILLCOMM;
  480. jpeg_finish_decompress(&cinfo);
  481. jpeg_destroy_decompress(&cinfo);
  482. fclose(infile);
  483. return;
  484. break;
  485. }
  486. }
  487. pInfo->state = PKST_INFOANDBITS;
  488. pInfo->result = ER_SUCCESS;
  489. }
  490. else if(cinfo.out_color_components == 1)//256级灰度图象
  491. {
  492. while (cinfo.output_scanline < cinfo.output_height) 
  493. {
  494. jpeg_read_scanlines(&cinfo, buffer, 1);
  495. pData = buffer[0];
  496. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9修改以下代码@@@@@@@@@@@@
  497. /*
  498. if(pInfo->fpProgress)
  499. {
  500. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.output_scanline * 100 / cinfo.output_height))
  501. {
  502. pInfo->result = ER_USERBREAK;
  503. return ;
  504. }
  505. }
  506. */
  507. // 为:
  508. if ((pInfo->fpProgress)&&(!(cinfo.output_scanline%RWPROGRESSSTEP)))
  509. {
  510. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.output_scanline))
  511. {
  512. pInfo->result = ER_USERBREAK;
  513. jpeg_destroy_decompress(&cinfo);
  514. fclose(infile);
  515. return ; // 用户中断操作
  516. }
  517. }
  518. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  519. switch(_get_desformat(pInfo)) // 标准图像格式(目标格式)
  520. {
  521. case DF_16_555:
  522. {
  523. WORD *pDesPixAddr555 = (WORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];
  524. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  525. {
  526. gray = *pData++;
  527. *pDesPixAddr555++ = WORD((((WORD)gray>>3)<<10)|(((WORD)gray>>3)<<5)|((WORD)gray>>3));
  528. }
  529. }
  530. break;
  531. case DF_16_565:
  532. {
  533. WORD *pDesPixAddr565 = (WORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];
  534. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  535. {
  536. gray = *pData++;
  537. *pDesPixAddr565++ = WORD((((WORD)gray>>3)<<11)|(((WORD)gray>>2)<<5)|((WORD)gray>>3));
  538. }
  539. }
  540. break;
  541. case DF_24:
  542. {
  543. LPBYTE lpdes = (LPBYTE)pInfo->pLineAddr[cinfo.output_scanline - 1];
  544. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  545. {
  546. gray = *pData++;
  547. *lpdes++ = gray;
  548. *lpdes++ = gray;
  549. *lpdes++ = gray;
  550. }
  551. }
  552. break;
  553. case DF_32:
  554. {
  555. DWORD *pDesPixAddr888;
  556. DWORD pix32;
  557. pDesPixAddr888  = (DWORD*)pInfo->pLineAddr[cinfo.output_scanline - 1];// 目标缓冲区当前行第一个像素的地址
  558. for (widthCount=0;widthCount<cinfo.output_width;widthCount++)
  559. {
  560. gray = *pData++;
  561. pix32 = DWORD(((DWORD)gray<<16)|((DWORD)gray<<8)|(DWORD)gray);
  562. pix32 &= 0x00FFFFFF;
  563. *pDesPixAddr888++ = pix32;
  564. }
  565. }
  566. break;
  567. case DF_NULL:
  568. default:
  569. ASSERT(FALSE);
  570. pInfo->result = ER_ILLCOMM;
  571. jpeg_finish_decompress(&cinfo);
  572. jpeg_destroy_decompress(&cinfo);
  573. fclose(infile);
  574. return;
  575. break;
  576. }
  577. }
  578. pInfo->state = PKST_INFOANDBITS;
  579. pInfo->result = ER_SUCCESS;
  580. }
  581. else
  582. {
  583. pInfo->result = ER_BADIMAGE;
  584. }
  585. jpeg_finish_decompress(&cinfo);
  586. jpeg_destroy_decompress(&cinfo);
  587. fclose(infile);
  588. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9增加以下代码@@@@@@@@@@@@
  589. if (pInfo->fpProgress)
  590. (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
  591. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  592. }
  593. // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
  594. // 将数据保存到指定文件中
  595. void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
  596. {
  597. ASSERT(pInfo->result == ER_EMPTY);
  598. ASSERT(::strlen(pInfo->filename));
  599. ASSERT(pInfo->state == PKST_INFOANDBITS);
  600. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  601. ASSERT(pInfo->pLineAddr != NULL);
  602. ASSERT(pInfo->_pbdata != NULL);
  603. FILE *outfile;
  604. UINT width,height;
  605. struct jpeg_compress_struct cinfo;
  606. int row_stride; /* physical row widthPix in image buffer */
  607. struct my_error_mgr jerr;
  608. LPBYTE lpDataBuf = NULL;
  609. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  610. //JPEG仅支持8、24位位图
  611. if(lpImgInfoStr->bitcount == 1 || lpImgInfoStr->bitcount == 4 ||
  612. lpImgInfoStr->bitcount == 16 || lpImgInfoStr->bitcount == 32)
  613. {
  614. pInfo->result = ER_NOTSUPPORT;
  615. return;
  616. }
  617. width = lpImgInfoStr->width;
  618. height = lpImgInfoStr->height;
  619. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9增加以下代码@@@@@@@@@@@@
  620. // 此时imginfo中的数据可能与sDIBInfo不一样,以sDIBInfo为准
  621. RWPROGRESSSIZE = (int)::abs(pInfo->sDIBInfo.bmi.biHeight);
  622. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  623. if (pInfo->fpProgress)
  624. {
  625. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 0))
  626. {
  627. pInfo->result = ER_USERBREAK;
  628. return;
  629. }
  630. }
  631. if ((outfile = fopen((LPCTSTR)lpImgInfoStr->filename, "wb")) == NULL) 
  632. {
  633. pInfo->result = ER_FILERWERR;
  634. return;
  635. }
  636. cinfo.err = jpeg_std_error(&jerr.pub);
  637. jerr.pub.error_exit = my_error_exit;
  638. if (setjmp(jerr.setjmp_buffer)) 
  639. {
  640. jpeg_destroy_compress(&cinfo);
  641. if (outfile!=NULL)
  642. fclose(outfile);
  643. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9删除以下代码@@@@@@@@@@@@
  644. // 因为该变量在此之前是NULL
  645. /*
  646. if(lpDataBuf != NULL)
  647. delete [] lpDataBuf;
  648. */
  649. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  650. pInfo->result = ER_BADIMAGE;
  651. return;
  652. }
  653. jpeg_create_compress(&cinfo);
  654. jpeg_stdio_dest(&cinfo, outfile);
  655. cinfo.image_width = width; 
  656. cinfo.image_height = height;
  657. if(lpImgInfoStr->bitcount == 24)
  658. {
  659. lpDataBuf = new BYTE[width * height * 3];
  660. if(lpDataBuf == NULL)
  661. {
  662. pInfo->result = ER_MEMORYERR;
  663. jpeg_destroy_compress(&cinfo);
  664. if (outfile!=NULL)
  665. fclose(outfile);
  666. return;
  667. }
  668. GetRGBBuf(pInfo,lpDataBuf);
  669. cinfo.input_components = 3;
  670. cinfo.in_color_space = JCS_RGB; 
  671. else if(lpImgInfoStr->bitcount == 8)
  672. {
  673. lpDataBuf = new BYTE[width * height];
  674. if(lpDataBuf == NULL)
  675. {
  676. pInfo->result = ER_MEMORYERR;
  677. jpeg_destroy_compress(&cinfo);
  678. if (outfile!=NULL)
  679. fclose(outfile);
  680. return;
  681. }
  682. GetGRAYBuf(pInfo,lpDataBuf);
  683. cinfo.input_components = 1;
  684. cinfo.in_color_space = JCS_GRAYSCALE; 
  685. }
  686. jpeg_set_defaults(&cinfo);
  687. jpeg_set_quality(&cinfo, lpImgInfoStr->qualtify, TRUE);
  688. jpeg_start_compress(&cinfo, TRUE);
  689. row_stride = width * 3;
  690. LPBYTE outRow;
  691. if(lpImgInfoStr->bitcount == 24)
  692. {
  693. while (cinfo.next_scanline < cinfo.image_height) 
  694. {
  695. outRow = lpDataBuf + (cinfo.next_scanline * width * 3);
  696. jpeg_write_scanlines(&cinfo, &outRow, 1);
  697. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9修改以下代码@@@@@@@@@@@@
  698. //为了编码的速度,所以又注释掉了,orbit,2000-08-31
  699. /*
  700. if(pInfo->fpProgress)
  701. {
  702. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.next_scanline * 100 / cinfo.image_height))
  703. {
  704. pInfo->result = ER_USERBREAK;
  705. return;
  706. }
  707. }
  708. */
  709. // 为:
  710. if ((pInfo->fpProgress)&&(!(cinfo.next_scanline%RWPROGRESSSTEP)))
  711. {
  712. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.next_scanline))
  713. {
  714. pInfo->result = ER_USERBREAK;
  715. jpeg_destroy_compress(&cinfo);
  716. delete [] lpDataBuf;
  717. fclose(outfile);
  718. return ; // 用户中断操作
  719. }
  720. }
  721. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  722. }
  723. else if(lpImgInfoStr->bitcount == 8)
  724. {
  725. while (cinfo.next_scanline < cinfo.image_height) 
  726. {
  727. outRow = lpDataBuf + (cinfo.next_scanline * width);
  728. jpeg_write_scanlines(&cinfo, &outRow, 1);
  729. //@@@@@@@@@@@@@@@@@ YZ 于2000-12-9修改以下代码@@@@@@@@@@@@
  730. //为了编码的速度,所以又注释掉了,orbit,2000-08-31
  731. /*
  732. if(pInfo->fpProgress)
  733. {
  734. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.next_scanline * 100 / cinfo.image_height))
  735. {
  736. pInfo->result = ER_USERBREAK;
  737. return;
  738. }
  739. }
  740. */
  741. // 为:
  742. if ((pInfo->fpProgress)&&(!(cinfo.next_scanline%RWPROGRESSSTEP)))
  743. {
  744. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, cinfo.next_scanline))
  745. {
  746. pInfo->result = ER_USERBREAK;
  747. jpeg_destroy_compress(&cinfo);
  748. delete [] lpDataBuf;
  749. fclose(outfile);
  750. return ; // 用户中断操作
  751. }
  752. }
  753. //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  754. }
  755. }
  756. jpeg_finish_compress(&cinfo);
  757. fclose(outfile);
  758. jpeg_destroy_compress(&cinfo);
  759. delete [] lpDataBuf;
  760. if (pInfo->fpProgress)
  761. (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
  762. pInfo->result = ER_SUCCESS;
  763. }
  764. // 操作命令解释函数---解释:CMD_RESIZE命令
  765. // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
  766. void _fnCMD_RESIZE(INFOSTR *pInfo)
  767. {
  768. // 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像,
  769. // 比如WMF、EMF之类。
  770. // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
  771. // ----------------------------------------------------------------->
  772. pInfo->result = ER_NOTSUPPORT;
  773. }
  774. DESFORMAT _get_desformat(LPINFOSTR pInfo)
  775. {
  776. ASSERT(pInfo);
  777. // ASSERT(pInfo->state >= PKST_PASSVER);
  778. ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
  779. DESFORMAT result;
  780. switch(pInfo->sDIBInfo.bmi.biBitCount)
  781. {
  782. case 32:
  783. /******************************************************
  784. 32位掩码示意图
  785.     高               ->                 低
  786. 0000 0000   0000 0000   0000 0000   0000 0000  888格式
  787.             1111 1111  ------------------------R
  788.                         1111 1111 -------------G
  789.                                     1111 1111--B
  790. * Win95 系统只支持这一种格式
  791. ******************************************************/
  792. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  793. {
  794. result = DF_32;
  795. break;
  796. }
  797. if ((pInfo->sDIBInfo.rmask == 0xff0000)&&
  798. (pInfo->sDIBInfo.gmask == 0xff00)&&
  799. (pInfo->sDIBInfo.bmask == 0xff))
  800. result = DF_32;
  801. else
  802. {
  803. ASSERT(FALSE); // 只支持888格式
  804. result = DF_NULL;
  805. }
  806. break;
  807. case 24:
  808. result = DF_24;
  809. break;
  810. case 16:
  811. /*******************************************
  812. 16位掩码示意图
  813.   高字节      低字节
  814. 0000 0000   0000 0000 
  815.    1 1111--B // 555格式
  816.    11 111 -------G
  817.  111 11  --------------R
  818. 0
  819.    1 1111--B // 565格式
  820.   111   111 -------G
  821. 1111 1   --------------R
  822. * Win95 系统只支持以上两种格式
  823. *******************************************/
  824. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  825. {
  826. result = DF_16_555;
  827. break;
  828. }
  829. if ((pInfo->sDIBInfo.rmask == 0x7c00)&&
  830. (pInfo->sDIBInfo.gmask == 0x3e0)&&
  831. (pInfo->sDIBInfo.bmask == 0x1f))
  832. result = DF_16_555;
  833. else if ((pInfo->sDIBInfo.rmask == 0xf800)&&
  834. (pInfo->sDIBInfo.gmask == 0x7e0)&&
  835. (pInfo->sDIBInfo.bmask == 0x1f))
  836. result = DF_16_565;
  837. else
  838. result = DF_NULL;
  839. break;
  840. default:
  841. ASSERT(FALSE); // 不接受其它格式
  842. result = DF_NULL;
  843. break;
  844. }
  845. return result;
  846. }
  847. IMGCOMPRESS CompressType(J_COLOR_SPACE jcs)
  848. {
  849. IMGCOMPRESS rtn = ICS_MAX;
  850. switch(jcs)
  851. {
  852. case JCS_UNKNOWN:
  853. rtn = ICS_MAX;
  854. break;
  855. case JCS_GRAYSCALE:
  856. rtn = ICS_JPEGGRAYSCALE;
  857. break;
  858. case JCS_RGB:
  859. rtn = ICS_JPEGRGB;
  860. break;
  861. case JCS_YCbCr:
  862. rtn = ICS_JPEGYCbCr;
  863. break;
  864. case JCS_CMYK:
  865. rtn = ICS_JPEGCMYK;
  866. break;
  867. case JCS_YCCK:
  868. rtn = ICS_JPEGYCCK;
  869. break;
  870. default:
  871. break;
  872. }
  873. return rtn;
  874. }
  875. METHODDEF(void) my_error_exit (j_common_ptr cinfo)
  876. {
  877. my_error_ptr myerr = (my_error_ptr) cinfo->err;
  878. char buffer[JMSG_LENGTH_MAX];
  879. (*cinfo->err->format_message) (cinfo, buffer);
  880. // 此行被注释掉,以免破坏调用者界面。YZ 2000-11-15日
  881. // MessageBox(NULL,buffer,"JPEG Fatal Error",MB_ICONSTOP);
  882. longjmp(myerr->setjmp_buffer, 1);
  883. }
  884. ////////////////////////////////////////////////////////////////////////////////
  885. //将pInfo的数据转化为编码所用的格式(24位RGB格式)
  886. //lpRBGBuf---数据缓冲区,大小为:width*height*3 Bytes
  887. //orbit,2000-08-31
  888. ////////////////////////////////////////////////////////////////////////////////
  889. BOOL GetRGBBuf(LPINFOSTR pInfo,LPBYTE lpRBGBuf)
  890. {
  891. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  892. if(bmpInfo.biBitCount != 32)
  893. return FALSE;
  894. DWORD hei = bmpInfo.biHeight;
  895. DWORD wid = bmpInfo.biWidth;
  896. LPBYTE lp = lpRBGBuf,lpRow;
  897. for(DWORD row = hei - 1; row >= 1; row--)
  898. {
  899. lpRow = (LPBYTE)pInfo->pLineAddr[row];
  900. for(DWORD i = 0; i < wid; i++)
  901. {
  902. *lp++ = *(lpRow + 3); //red
  903. *lp++ = *(lpRow + 2); //green
  904. *lp++ = *(lpRow + 1); //blue
  905. lpRow += 4;
  906. }
  907. }
  908. return TRUE;
  909. }
  910. ////////////////////////////////////////////////////////////////////////////////
  911. //将pInfo的数据转化为编码所用的格式(8位灰度格式)
  912. //lpGRAYBuf---数据缓冲区,大小为:width*height Bytes
  913. //orbit,2000-08-31
  914. ////////////////////////////////////////////////////////////////////////////////
  915. BOOL GetGRAYBuf(LPINFOSTR pInfo,LPBYTE lpGRAYBuf)
  916. {
  917. BITMAPINFOHEADER bmpInfo = pInfo->sDIBInfo.bmi;
  918. if(bmpInfo.biBitCount != 32)
  919. return FALSE;
  920. DWORD hei = bmpInfo.biHeight;
  921. DWORD wid = bmpInfo.biWidth;
  922. LPBYTE lp = lpGRAYBuf,lpRow;
  923. BYTE red,blue,green;
  924. int tmp;
  925. for(DWORD row = hei - 1; row >= 1; row-- )
  926. {
  927. lpRow = (LPBYTE)pInfo->pLineAddr[row];
  928. for(DWORD i = 0; i < wid; i++)
  929. {
  930. red = *(lpRow + 3); //red
  931. green = *(lpRow + 2); //green
  932. blue = *(lpRow + 1); //blue
  933. tmp = (int)(.299 * (double)(red) + .587 * (double)(green) + .114 * (double)(blue));
  934. *lp++ = (BYTE)tmp;
  935. lpRow += 4;
  936. }
  937. }
  938. return TRUE;
  939. }