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.

391 lines
9.8 KiB

  1. /* jpegapi.cpp -- interface layer for painless JPEG compression of NIFty images.
  2. * Written by Ajai Sehgal 3/10/96
  3. * (c) Copyright Microsoft Corporation
  4. *
  5. * 08-27-1997 (kurtgeis) Pushed exception handling into library. Changed
  6. * all entry points to return HRESULTs. Added width and heigth to parameters.
  7. * 04-20-2001 (bobday) Removed exception handling. If we have problems, I
  8. * say we fix the problems! (or check for the proper error conditions)
  9. */
  10. #pragma warning(disable:4005)
  11. #include "stdafx.h"
  12. #include "jpegapi.h"
  13. #include "jmemsys.h"
  14. #define I_LIKE_CPP_EH 0 // turn this on if we ever find a reason for it
  15. /********************************************************************************/
  16. /* JPEGCompressHeader()
  17. *
  18. * Arguments:
  19. * tuQuality "Quality" of the resulting JPEG (0..100, 100=best)
  20. *
  21. * Returns:
  22. * HRESULT
  23. */
  24. HRESULT JPEGCompressHeader(BYTE *prgbJPEGHeaderBuf, UINT tuQuality, ULONG *pcbOut, HANDLE *phJpegC, J_COLOR_SPACE ColorSpace)
  25. {
  26. HRESULT hr = S_OK;
  27. jpeg_compress_struct *spjcs = NULL;
  28. #if I_LIKE_CPP_EH
  29. try
  30. {
  31. #endif
  32. spjcs = new jpeg_compress_struct;
  33. struct jpeg_error_mgr *jem = new jpeg_error_mgr;
  34. spjcs->err = jpeg_std_error(jem); // Init the error handler
  35. jpeg_create_compress(spjcs); // Init the compression object
  36. if (ColorSpace == JCS_GRAYSCALE)
  37. {
  38. spjcs->in_color_space = JCS_GRAYSCALE;
  39. spjcs->input_components = 1;
  40. }
  41. else
  42. {
  43. spjcs->in_color_space = JCS_RGBA;
  44. spjcs->input_components = 4;
  45. }
  46. jpeg_set_defaults(spjcs); // Init the compression engine with the defaults
  47. jpeg_set_quality(spjcs, tuQuality, TRUE);
  48. jpeg_set_colorspace(spjcs,ColorSpace);
  49. jpeg_mem_dest(spjcs, prgbJPEGHeaderBuf); // Init the "destination manager"
  50. spjcs->comps_in_scan = 0;
  51. spjcs->write_JFIF_header = FALSE;
  52. jpeg_write_tables(spjcs);
  53. jpeg_suppress_tables(spjcs, TRUE);
  54. *pcbOut = spjcs->bytes_in_buffer;
  55. *phJpegC = (HANDLE) spjcs;
  56. #if I_LIKE_CPP_EH
  57. }
  58. catch( THROWN thrownHR )
  59. {
  60. hr = thrownHR.Hr();
  61. }
  62. catch( ... )
  63. {
  64. if ( spjcs ) delete spjcs;
  65. hr = E_OUTOFMEMORY;
  66. }
  67. #endif
  68. return hr;
  69. }
  70. /* JPEGDecompressHeader()
  71. *
  72. * Arguments:
  73. * *prgbJPEGBuf : pointer to the JPEG header data as read from file
  74. * *phJpegD: pointer to Handle of the JPEG decompression object returned
  75. *
  76. * Returns:
  77. * HRESULT
  78. */
  79. HRESULT JPEGDecompressHeader(BYTE *prgbJPEGHeaderBuf, HANDLE *phJpegD, ULONG ulBufferSize)
  80. {
  81. HRESULT hr = S_OK;
  82. jpeg_decompress_struct * spjds = NULL;
  83. #if I_LIKE_CPP_EH
  84. try
  85. {
  86. #endif
  87. spjds = new jpeg_decompress_struct;
  88. struct jpeg_error_mgr *jem = new jpeg_error_mgr;
  89. spjds->err = jpeg_std_error(jem); // Init the error handler
  90. jpeg_create_decompress(spjds); // Init the decompression object
  91. // Now we need to "read" it into the decompression object...
  92. jpeg_mem_src(spjds, prgbJPEGHeaderBuf, ulBufferSize);
  93. jpeg_read_header(spjds, FALSE);
  94. spjds->out_color_space = JCS_RGBA;
  95. *phJpegD = (HANDLE) spjds;
  96. #if I_LIKE_CPP_EH
  97. }
  98. catch( THROWN thrownHR )
  99. {
  100. hr = thrownHR.Hr();
  101. }
  102. catch( ... )
  103. {
  104. if ( spjds ) delete spjds;
  105. hr = E_OUTOFMEMORY;
  106. }
  107. #endif
  108. return hr;
  109. }
  110. // DestroyJPEGCompress
  111. //
  112. // Release all the JPEG stuff from the handle we gave to the user
  113. //
  114. HRESULT DestroyJPEGCompressHeader(HANDLE hJpegC)
  115. {
  116. HRESULT hr = S_OK;
  117. try
  118. {
  119. struct jpeg_compress_struct *pjcs = (struct jpeg_compress_struct *)hJpegC;
  120. jpeg_destroy_compress(pjcs);
  121. delete pjcs->err;
  122. delete pjcs;
  123. }
  124. catch( THROWN thrownHR )
  125. {
  126. hr = thrownHR.Hr();
  127. }
  128. return hr;
  129. }
  130. // DestroyJPEGDecompressHeader
  131. //
  132. // Release all the JPEG stuff from the handle we gave to the user
  133. //
  134. HRESULT DestroyJPEGDecompressHeader(HANDLE hJpegD)
  135. {
  136. HRESULT hr = S_OK;
  137. #if I_LIKE_CPP_EH
  138. try
  139. {
  140. #endif
  141. struct jpeg_decompress_struct *pjds = (struct jpeg_decompress_struct *)hJpegD;
  142. jpeg_destroy_decompress(pjds);
  143. delete pjds->err;
  144. delete pjds;
  145. #if I_LIKE_CPP_EH
  146. }
  147. catch( THROWN thrownHR )
  148. {
  149. hr = thrownHR.Hr();
  150. }
  151. #endif
  152. return hr;
  153. }
  154. /* JPEGFromRGBA()
  155. *
  156. * Arguments:
  157. * prgbImage A raw image buffer (4 bytes/pixel, RGBA order)
  158. * cpxlAcross Width of the image, in pixels
  159. * cpxlDown Height of the image, in pixels
  160. * tuQuality "Quality" of the resulting JPEG (0..100, 100=best)
  161. * A memory buffer containing the complete JPEG compressed version of the
  162. * given image. NULL on error.
  163. *
  164. * Returns:
  165. * HRESULT
  166. */
  167. HRESULT JPEGFromRGBA(BYTE *prgbImage, BYTE *prgbJPEGBuf, UINT tuQuality, ULONG *pcbOut, HANDLE hJpegC, J_COLOR_SPACE ColorSpace, UINT nWidth, UINT nHeight )
  168. {
  169. HRESULT hr = S_OK;
  170. #if I_LIKE_CPP_EH
  171. try
  172. {
  173. #endif
  174. struct jpeg_compress_struct *pjcs = (jpeg_compress_struct *)hJpegC;
  175. JSAMPROW rgrow[1];
  176. //
  177. // On non X86 architectures use only C code
  178. //
  179. #if defined (_X86_)
  180. pjcs->dct_method = JDCT_ISLOW;
  181. #else
  182. pjcs->dct_method = JDCT_FLOAT;
  183. #endif
  184. pjcs->image_width = nWidth;
  185. pjcs->image_height = nHeight;
  186. pjcs->data_precision = 8; /* 8 bits / sample */
  187. pjcs->bytes_in_buffer = 0;
  188. pjcs->write_JFIF_header = FALSE;
  189. if (ColorSpace == JCS_GRAYSCALE)
  190. {
  191. pjcs->input_components = 1;
  192. }
  193. else
  194. {
  195. pjcs->input_components = 4;
  196. }
  197. jpeg_set_colorspace(pjcs,ColorSpace);
  198. jpeg_set_quality(pjcs, tuQuality, TRUE);
  199. jpeg_suppress_tables(pjcs, TRUE);
  200. jpeg_mem_dest(pjcs, prgbJPEGBuf); // Init the "destination manager"
  201. jpeg_start_compress(pjcs, FALSE);
  202. rgrow[0] = (JSAMPROW)prgbImage;
  203. while (pjcs->next_scanline < nHeight )
  204. {
  205. jpeg_write_scanlines(pjcs, rgrow, 1);
  206. rgrow[0] += nWidth * pjcs->input_components; //input_components is the equivalent of # of bytes
  207. }
  208. jpeg_finish_compress(pjcs); // Finish up compressing
  209. *pcbOut = pjcs->bytes_in_buffer;
  210. #if I_LIKE_CPP_EH
  211. }
  212. catch( THROWN thrownHR )
  213. {
  214. hr = thrownHR.Hr();
  215. }
  216. #endif
  217. return hr;
  218. }
  219. /* RGBAFromJPEG()
  220. *
  221. * Arguments:
  222. * prgbJPEG: A JPEG data stream, as returned by JPEGFromRGBA()
  223. * A memory buffer containing the reconstructed image in RGBA format.
  224. * NULL on error.
  225. *
  226. * Returns:
  227. * HRESULT
  228. */
  229. HRESULT RGBAFromJPEG(BYTE *prgbJPEG, BYTE *prgbImage, HANDLE hJpegD, ULONG ulBufferSize, BYTE bJPEGConversionType, ULONG *pulReturnedNumChannels, UINT nWidth, UINT nHeight )
  230. {
  231. HRESULT hr = S_OK;
  232. jpeg_decompress_struct * spjds = NULL;
  233. #if I_LIKE_CPP_EH
  234. try
  235. {
  236. #endif
  237. struct jpeg_decompress_struct *pjds;
  238. spjds = new jpeg_decompress_struct;
  239. jpeg_error_mgr * spjem = new jpeg_error_mgr;
  240. if ( hJpegD == NULL )
  241. {
  242. spjds->err = jpeg_std_error(spjem); // Init the error handler
  243. jpeg_create_decompress(spjds); // Init the decompression object in the case
  244. pjds = spjds; // that the headers are with the tiles.
  245. }
  246. else
  247. {
  248. pjds = (struct jpeg_decompress_struct *)hJpegD;
  249. }
  250. JSAMPROW rgrow[1];
  251. // Set the various image parameters.
  252. pjds->data_precision = 8;
  253. pjds->image_width = nWidth;
  254. pjds->image_height = nHeight;
  255. jpeg_mem_src(pjds, prgbJPEG, ulBufferSize); // Init the "source manager"
  256. jpeg_read_header(pjds, TRUE);
  257. switch (bJPEGConversionType)
  258. {
  259. case 1:
  260. pjds->out_color_space = JCS_RGBA;
  261. if (pjds->jpeg_color_space != JCS_RGBA)
  262. {
  263. if ( 4 == pjds->num_components)
  264. pjds->jpeg_color_space = JCS_YCbCrALegacy;
  265. else
  266. pjds->jpeg_color_space = JCS_YCbCr;
  267. }
  268. *pulReturnedNumChannels = 4;
  269. break;
  270. case 2:
  271. pjds->out_color_space = JCS_RGBA;
  272. if ( 4 == pjds->num_components)
  273. pjds->jpeg_color_space = JCS_YCbCrA;
  274. else
  275. pjds->jpeg_color_space = JCS_YCbCr;
  276. pjds->jpeg_color_space = JCS_YCbCrA;
  277. *pulReturnedNumChannels = 4;
  278. break;
  279. default:
  280. pjds->out_color_space = JCS_UNKNOWN;
  281. pjds->jpeg_color_space = JCS_UNKNOWN;
  282. *pulReturnedNumChannels = pjds->num_components;
  283. }
  284. //
  285. // On non X86 architectures use only C code
  286. //
  287. #if defined (_X86_)
  288. pjds->dct_method = JDCT_ISLOW;
  289. #else
  290. pjds->dct_method = JDCT_FLOAT;
  291. #endif
  292. jpeg_start_decompress(pjds);
  293. rgrow[0] = (JSAMPROW)prgbImage;
  294. while (pjds->output_scanline < pjds->output_height)
  295. {
  296. jpeg_read_scanlines(pjds, rgrow, 1);
  297. rgrow[0] += pjds->output_width * *pulReturnedNumChannels;
  298. }
  299. jpeg_finish_decompress(pjds); // Finish up decompressing
  300. if (hJpegD == NULL)
  301. jpeg_destroy_decompress(pjds); //Destroy the decompression object if it
  302. //was locally allocated as in when the header
  303. //is part of the tile.
  304. delete spjem;
  305. delete spjds;
  306. #if I_LIKE_CPP_EH
  307. }
  308. catch( THROWN thrownHR )
  309. {
  310. hr = thrownHR.Hr();
  311. }
  312. catch( ... )
  313. {
  314. if ( spjds ) delete spjds;
  315. hr = E_OUTOFMEMORY;
  316. }
  317. #endif
  318. return hr;
  319. }