Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

689 lines
17 KiB

  1. /***********************************************************************
  2. *
  3. * JPEG decompression utility functions
  4. *
  5. * Implement (1) JPEG memory data source
  6. * (2) JPEG error manager using setjmp/longjmp
  7. *
  8. * Author : Indy Zhu [indyz]
  9. * Date : 5/20/98
  10. *
  11. ***********************************************************************/
  12. #include <stdio.h>
  13. // #include <stdlib.h>
  14. #include <setjmp.h>
  15. // Workaround for redefinition of INT32
  16. #define XMD_H 1
  17. extern "C"
  18. {
  19. // Header file for JPEG library
  20. #include "jpeglib.h"
  21. }
  22. #include <windows.h>
  23. #include "jpegutil.h"
  24. //
  25. // Buf source manager definition
  26. //
  27. typedef struct _buf_source_mgr
  28. {
  29. struct jpeg_source_mgr pub;
  30. // Fields specific to buf_source_mgr
  31. LPBYTE pJPEGBlob;
  32. DWORD dwSize;
  33. } buf_source_mgr;
  34. //
  35. // Jump error manager definition
  36. //
  37. typedef struct _jmp_error_mgr
  38. {
  39. struct jpeg_error_mgr pub;
  40. // Private fields for jump error manager
  41. jmp_buf stackContext;
  42. } jmp_error_mgr;
  43. /******************************************************************************\
  44. *
  45. * init_source()
  46. *
  47. * Arguments:
  48. *
  49. * Return Value:
  50. *
  51. * Status
  52. *
  53. * History:
  54. *
  55. * 11/4/1998 Original Version
  56. *
  57. \******************************************************************************/
  58. static void init_source(j_decompress_ptr pDecompInfo)
  59. {
  60. // No working necessary here
  61. }
  62. /******************************************************************************\
  63. *
  64. * fill_input_buffer()
  65. *
  66. * Arguments:
  67. *
  68. * Return Value:
  69. *
  70. * Status
  71. *
  72. * History:
  73. *
  74. * 11/4/1998 Original Version
  75. *
  76. \******************************************************************************/
  77. static boolean fill_input_buffer(j_decompress_ptr pDecompInfo)
  78. {
  79. buf_source_mgr *pBufSrcMgr;
  80. // Recover buf source manager itself
  81. pBufSrcMgr = (buf_source_mgr *)pDecompInfo->src;
  82. // buf_source_mgr can only fire one shot
  83. pBufSrcMgr->pub.next_input_byte = pBufSrcMgr->pJPEGBlob;
  84. pBufSrcMgr->pub.bytes_in_buffer = pBufSrcMgr->dwSize;
  85. return(TRUE);
  86. }
  87. /******************************************************************************\
  88. *
  89. * skip_input_data()
  90. *
  91. * Arguments:
  92. *
  93. * Return Value:
  94. *
  95. * Status
  96. *
  97. * History:
  98. *
  99. * 11/4/1998 Original Version
  100. *
  101. \******************************************************************************/
  102. static void skip_input_data(j_decompress_ptr pDecompInfo, long lBytes)
  103. {
  104. buf_source_mgr *pBufSrcMgr;
  105. // For buf source manager, it is very easy to implement
  106. if (lBytes > 0) {
  107. pBufSrcMgr = (buf_source_mgr *)pDecompInfo->src;
  108. pBufSrcMgr->pub.next_input_byte += lBytes;
  109. pBufSrcMgr->pub.bytes_in_buffer -= lBytes;
  110. }
  111. }
  112. /******************************************************************************\
  113. *
  114. * term_source()
  115. *
  116. * Arguments:
  117. *
  118. * Return Value:
  119. *
  120. * Status
  121. *
  122. * History:
  123. *
  124. * 11/4/1998 Original Version
  125. *
  126. \******************************************************************************/
  127. static void term_source(j_decompress_ptr pDecompInfo)
  128. {
  129. }
  130. /******************************************************************************\
  131. *
  132. * jpeg_buf_src()
  133. *
  134. * Arguments:
  135. *
  136. * Return Value:
  137. *
  138. * Status
  139. *
  140. * History:
  141. *
  142. * 11/4/1998 Original Version
  143. *
  144. \******************************************************************************/
  145. static void jpeg_buf_src(j_decompress_ptr pDecompInfo,
  146. LPBYTE pJPEGBlob, DWORD dwSize)
  147. {
  148. buf_source_mgr *pBufSrcMgr;
  149. // Allocate memory for the buf source manager
  150. pBufSrcMgr = (buf_source_mgr *)
  151. (pDecompInfo->mem->alloc_small)((j_common_ptr)pDecompInfo,
  152. JPOOL_PERMANENT,
  153. sizeof(buf_source_mgr));
  154. // Record the pJPEGBlob
  155. pBufSrcMgr->pJPEGBlob = pJPEGBlob;
  156. pBufSrcMgr->dwSize = dwSize;
  157. // Fill in the function pointers
  158. pBufSrcMgr->pub.init_source = init_source;
  159. pBufSrcMgr->pub.fill_input_buffer = fill_input_buffer;
  160. pBufSrcMgr->pub.skip_input_data = skip_input_data;
  161. pBufSrcMgr->pub.resync_to_restart = jpeg_resync_to_restart;
  162. pBufSrcMgr->pub.term_source = term_source;
  163. // Initialize the pointer into the buffer
  164. pBufSrcMgr->pub.bytes_in_buffer = 0;
  165. pBufSrcMgr->pub.next_input_byte = NULL;
  166. // Ask the decompression context to remember it
  167. pDecompInfo->src = (struct jpeg_source_mgr *)pBufSrcMgr;
  168. }
  169. /******************************************************************************\
  170. *
  171. * jmp_error_exit()
  172. *
  173. * Arguments:
  174. *
  175. * Return Value:
  176. *
  177. * Status
  178. *
  179. * History:
  180. *
  181. * 11/4/1998 Original Version
  182. *
  183. \******************************************************************************/
  184. static void jmp_error_exit(j_common_ptr pDecompInfo)
  185. {
  186. jmp_error_mgr *pJmpErrorMgr;
  187. // Get the jump error manager back
  188. pJmpErrorMgr = (jmp_error_mgr *)pDecompInfo->err;
  189. // Display the error message
  190. #ifdef _DEBUG
  191. (pDecompInfo->err->output_message)(pDecompInfo);
  192. #endif
  193. // Recover the original stack
  194. longjmp(pJmpErrorMgr->stackContext, 1);
  195. }
  196. /******************************************************************************\
  197. *
  198. * jpeg_jmp_error()
  199. *
  200. * Arguments:
  201. *
  202. * Return Value:
  203. *
  204. * Status
  205. *
  206. * History:
  207. *
  208. * 11/4/1998 Original Version
  209. *
  210. \******************************************************************************/
  211. struct jpeg_error_mgr *jpeg_jmp_error(jmp_error_mgr *pJmpErrorMgr)
  212. {
  213. // Initialize the public part
  214. jpeg_std_error(&pJmpErrorMgr->pub);
  215. // Set up jump error manager exit method
  216. pJmpErrorMgr->pub.error_exit = jmp_error_exit;
  217. return((jpeg_error_mgr *)pJmpErrorMgr);
  218. }
  219. /******************************************************************************\
  220. *
  221. * GetJPEGDimensions()
  222. *
  223. * Arguments:
  224. *
  225. * Return Value:
  226. *
  227. * Status
  228. *
  229. * History:
  230. *
  231. * 11/4/1998 Original Version
  232. *
  233. \******************************************************************************/
  234. int GetJPEGDimensions(LPBYTE pJPEGBlob, DWORD dwSize,
  235. LONG *pWidth, LONG *pHeight, WORD *pChannel)
  236. {
  237. int ret;
  238. struct jpeg_decompress_struct decompInfo;
  239. jmp_error_mgr jpegErrMgr;
  240. // Step 1 : Initialize JPEG session data-structure
  241. decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
  242. jpeg_create_decompress(&decompInfo);
  243. // Reserve the state of the current stack
  244. if (setjmp(jpegErrMgr.stackContext)) {
  245. // JPEG lib will longjump here when there is an error
  246. jpeg_destroy_decompress(&decompInfo);
  247. return(JPEGERR_INTERNAL_ERROR);
  248. }
  249. // Step 2 : Specify the source of the compressed data
  250. jpeg_buf_src(&decompInfo, pJPEGBlob, dwSize);
  251. // Step 3 : Read JPEG file header information
  252. ret = jpeg_read_header(&decompInfo, TRUE);
  253. // Release the decompression context
  254. jpeg_destroy_decompress(&decompInfo);
  255. // Fill in the dimension info for the caller
  256. *pWidth = decompInfo.image_width;
  257. *pHeight = decompInfo.image_height;
  258. *pChannel = decompInfo.num_components;
  259. if (ret != JPEG_HEADER_OK) {
  260. return(JPEGERR_INTERNAL_ERROR);
  261. }
  262. return(JPEGERR_NO_ERROR);
  263. }
  264. /******************************************************************************\
  265. *
  266. * DecompProgressJPEG()
  267. *
  268. * Arguments:
  269. *
  270. * Assumption : The JPEG is 24bits.
  271. * pDIBPixel is the pixel buffer of a DIB
  272. *
  273. * Return Value:
  274. *
  275. * Status
  276. *
  277. * History:
  278. *
  279. * 11/4/1998 Original Version
  280. *
  281. \******************************************************************************/
  282. short __stdcall
  283. DecompProgressJPEG(
  284. LPBYTE pJPEGBlob,
  285. DWORD dwSize,
  286. LPBYTE pDIBPixel,
  287. DWORD dwBytesPerScanLine,
  288. JPEGCallbackProc pProgressCB,
  289. PVOID pCBContext)
  290. {
  291. struct jpeg_decompress_struct decompInfo;
  292. jmp_error_mgr jpegErrMgr;
  293. LPBYTE pCurScanBuf;
  294. JSAMPLE sampleTemp;
  295. LPBYTE pCurPixel;
  296. DWORD i;
  297. //
  298. // Callback related variables
  299. //
  300. ULONG ulImageSize;
  301. ULONG ulOffset;
  302. ULONG ulNewScanlines;
  303. ULONG ulCBInterval;
  304. BOOL bRet = FALSE;
  305. // Step 1 : Initialize JPEG session data-structure
  306. decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
  307. jpeg_create_decompress(&decompInfo);
  308. // Reserve the state of the current stack
  309. if (setjmp(jpegErrMgr.stackContext)) {
  310. // JPEG lib will longjump here when there is an error
  311. jpeg_destroy_decompress(&decompInfo);
  312. return(JPEGERR_INTERNAL_ERROR);
  313. }
  314. // Step 2 : Specify the source of the compressed data
  315. jpeg_buf_src(&decompInfo, pJPEGBlob, dwSize);
  316. // Step 3 : Read JPEG file header information
  317. if (jpeg_read_header(&decompInfo, TRUE) != JPEG_HEADER_OK) {
  318. jpeg_destroy_decompress(&decompInfo);
  319. return(JPEGERR_INTERNAL_ERROR);
  320. }
  321. // Step 4 : Set parameter for decompression
  322. // Defaults are OK for this occasssion
  323. // Step 5 : Start the real action
  324. jpeg_start_decompress(&decompInfo);
  325. //
  326. // Prepare for the final decompression
  327. //
  328. pCurScanBuf = pDIBPixel +
  329. (decompInfo.image_height - 1) * dwBytesPerScanLine;
  330. if (pProgressCB) {
  331. ulImageSize = decompInfo.image_height * dwBytesPerScanLine;
  332. ulCBInterval = decompInfo.image_height / 10;
  333. ulOffset = 0;
  334. ulNewScanlines = 0;
  335. }
  336. // Step 6 : Acquire the scan line
  337. while (decompInfo.output_scanline < decompInfo.output_height) {
  338. jpeg_read_scanlines(&decompInfo, &pCurScanBuf, 1);
  339. // Famous swapping for the unique format of Windows
  340. pCurPixel = pCurScanBuf;
  341. for (i = 0; i < decompInfo.image_width;
  342. i++, pCurPixel += decompInfo.num_components) {
  343. sampleTemp = *pCurPixel;
  344. *pCurPixel = *(pCurPixel + 2);
  345. *(pCurPixel + 2) = sampleTemp;
  346. }
  347. pCurScanBuf -= dwBytesPerScanLine;
  348. //
  349. // Fire the callback when possible and necessary
  350. //
  351. if (pProgressCB) {
  352. ulNewScanlines++;
  353. ulOffset += dwBytesPerScanLine;
  354. if ((ulNewScanlines == ulCBInterval) ||
  355. (decompInfo.output_scanline == decompInfo.output_height)) {
  356. bRet = pProgressCB(
  357. ulImageSize, ulNewScanlines,
  358. ulNewScanlines * dwBytesPerScanLine,
  359. pDIBPixel, pCBContext);
  360. if (! bRet) {
  361. break;
  362. }
  363. }
  364. }
  365. }
  366. // Step 7 : Finish the job
  367. jpeg_finish_decompress(&decompInfo);
  368. // Step 8 : Garbage collection
  369. jpeg_destroy_decompress(&decompInfo);
  370. if (bRet) {
  371. return(JPEGERR_NO_ERROR);
  372. } else {
  373. return(JPEGERR_CALLBACK_ERROR);
  374. }
  375. }
  376. /******************************************************************************\
  377. *
  378. * DecompTransferJPEG()
  379. *
  380. * Arguments:
  381. *
  382. * ppDIBPixel - *ppDIBPixel will change between callback if multiple buffer is
  383. * used, but dwBufSize is assumed to be constant.
  384. *
  385. * Return Value:
  386. *
  387. * Status
  388. *
  389. * History:
  390. *
  391. * 1/20/1999 Original Version
  392. *
  393. \******************************************************************************/
  394. short __stdcall
  395. DecompTransferJPEG(
  396. LPBYTE pJPEGBlob,
  397. DWORD dwSize,
  398. LPBYTE *ppDIBPixel,
  399. DWORD dwBufSize,
  400. DWORD dwBytesPerScanLine,
  401. JPEGCallbackProc pProgressCB,
  402. PVOID pCBContext)
  403. {
  404. struct jpeg_decompress_struct decompInfo;
  405. jmp_error_mgr jpegErrMgr;
  406. LPBYTE pCurScanLine;
  407. JSAMPLE sampleTemp;
  408. LPBYTE pCurPixel;
  409. DWORD i;
  410. //
  411. // Callback related variables
  412. //
  413. ULONG ulImageSize;
  414. ULONG ulOffset = 0;
  415. ULONG ulBufferLeft;
  416. BOOL bRet = FALSE;
  417. //
  418. // Parameter checking
  419. //
  420. if ((! ppDIBPixel) || (! *ppDIBPixel) || (! pProgressCB)) {
  421. return (JPEGERR_INTERNAL_ERROR);
  422. }
  423. // Step 1 : Initialize JPEG session data-structure
  424. decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
  425. jpeg_create_decompress(&decompInfo);
  426. // Reserve the state of the current stack
  427. if (setjmp(jpegErrMgr.stackContext)) {
  428. // JPEG lib will longjump here when there is an error
  429. jpeg_destroy_decompress(&decompInfo);
  430. return(JPEGERR_INTERNAL_ERROR);
  431. }
  432. // Step 2 : Specify the source of the compressed data
  433. jpeg_buf_src(&decompInfo, pJPEGBlob, dwSize);
  434. // Step 3 : Read JPEG file header information
  435. if (jpeg_read_header(&decompInfo, TRUE) != JPEG_HEADER_OK) {
  436. jpeg_destroy_decompress(&decompInfo);
  437. return(JPEGERR_INTERNAL_ERROR);
  438. }
  439. // Step 4 : Set parameter for decompression
  440. // Defaults are OK for this occasssion
  441. // Step 5 : Start the real action
  442. jpeg_start_decompress(&decompInfo);
  443. //
  444. // Prepare for the final decompression
  445. //
  446. ulImageSize = decompInfo.image_height * dwBytesPerScanLine;
  447. ulBufferLeft = dwBufSize;
  448. pCurScanLine = *ppDIBPixel;
  449. // Step 6 : Acquire the scan line
  450. while (decompInfo.output_scanline < decompInfo.output_height) {
  451. jpeg_read_scanlines(&decompInfo, &pCurScanLine, 1);
  452. // Famous swapping for the unique format of Windows
  453. pCurPixel = pCurScanLine;
  454. for (i = 0; i < decompInfo.image_width;
  455. i++, pCurPixel += decompInfo.num_components) {
  456. sampleTemp = *pCurPixel;
  457. *pCurPixel = *(pCurPixel + 2);
  458. *(pCurPixel + 2) = sampleTemp;
  459. }
  460. pCurScanLine += dwBytesPerScanLine;
  461. ulBufferLeft -= dwBytesPerScanLine;
  462. //
  463. // Fire the callback when possible and necessary
  464. //
  465. if ((ulBufferLeft < dwBytesPerScanLine) ||
  466. (decompInfo.output_scanline == decompInfo.output_height)) {
  467. bRet = pProgressCB(
  468. ulImageSize,
  469. ulOffset,
  470. dwBufSize - ulBufferLeft,
  471. *ppDIBPixel, pCBContext);
  472. if (! bRet) {
  473. break;
  474. }
  475. //
  476. // Reset the buffer, which may have been switched by the callback
  477. //
  478. ulBufferLeft = dwBufSize;
  479. pCurScanLine = *ppDIBPixel;
  480. ulOffset = decompInfo.output_scanline * dwBytesPerScanLine;
  481. }
  482. }
  483. // Step 7 : Finish the job
  484. jpeg_finish_decompress(&decompInfo);
  485. // Step 8 : Garbage collection
  486. jpeg_destroy_decompress(&decompInfo);
  487. if (bRet) {
  488. return(JPEGERR_NO_ERROR);
  489. } else {
  490. return(JPEGERR_CALLBACK_ERROR);
  491. }
  492. }
  493. /******************************************************************************\
  494. *
  495. * DecompJPEG()
  496. *
  497. * Arguments:
  498. *
  499. * Assumption : The JPEG is 24bits.
  500. * pDIBPixel is the pixel buffer of a DIB
  501. *
  502. * Return Value:
  503. *
  504. * Status
  505. *
  506. * History:
  507. *
  508. * 11/4/1998 Original Version
  509. *
  510. \******************************************************************************/
  511. SHORT __stdcall
  512. DecompJPEG(
  513. LPBYTE pJPEGBlob,
  514. DWORD dwSize,
  515. LPBYTE pDIBPixel,
  516. DWORD dwBytesPerScanLine)
  517. {
  518. struct jpeg_decompress_struct decompInfo;
  519. jmp_error_mgr jpegErrMgr;
  520. LPBYTE pCurScanBuf;
  521. JSAMPLE sampleTemp;
  522. LPBYTE pCurPixel;
  523. DWORD i;
  524. // Step 1 : Initialize JPEG session data-structure
  525. decompInfo.err = jpeg_jmp_error(&jpegErrMgr);
  526. jpeg_create_decompress(&decompInfo);
  527. // Reserve the state of the current stack
  528. if (setjmp(jpegErrMgr.stackContext)) {
  529. // JPEG lib will longjump here when there is an error
  530. jpeg_destroy_decompress(&decompInfo);
  531. return(-1);
  532. }
  533. // Step 2 : Specify the source of the compressed data
  534. jpeg_buf_src(&decompInfo, pJPEGBlob, dwSize);
  535. // Step 3 : Read JPEG file header information
  536. if (jpeg_read_header(&decompInfo, TRUE) != JPEG_HEADER_OK) {
  537. jpeg_destroy_decompress(&decompInfo);
  538. return(-1);
  539. }
  540. // Step 4 : Set parameter for decompression
  541. // Defaults are OK for this occasssion
  542. // Step 5 : Start the real action
  543. jpeg_start_decompress(&decompInfo);
  544. pCurScanBuf = pDIBPixel +
  545. (decompInfo.image_height - 1) * dwBytesPerScanLine;
  546. // Step 6 : Acquire the scan line
  547. while (decompInfo.output_scanline < decompInfo.output_height) {
  548. jpeg_read_scanlines(&decompInfo, &pCurScanBuf, 1);
  549. // Famous swapping for the unique format of Windows
  550. pCurPixel = pCurScanBuf;
  551. for (i = 0; i < decompInfo.image_width;
  552. i++, pCurPixel += decompInfo.num_components) {
  553. sampleTemp = *pCurPixel;
  554. *pCurPixel = *(pCurPixel + 2);
  555. *(pCurPixel + 2) = sampleTemp;
  556. }
  557. pCurScanBuf -= dwBytesPerScanLine;
  558. }
  559. // Step 7 : Finish the job
  560. jpeg_finish_decompress(&decompInfo);
  561. // Step 8 : Garbage collection
  562. jpeg_destroy_decompress(&decompInfo);
  563. return(0);
  564. }