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.

551 lines
13 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. */
  8. #pragma warning(disable:4005)
  9. #include "windows.h"
  10. // Workaround for redefinition of INT32
  11. #define XMD_H 1
  12. #include "jpegapi.h"
  13. #include "jmemsys.h"
  14. // #define INVERTBGR 0
  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. try
  28. {
  29. jpeg_compress_struct *spjcs = new jpeg_compress_struct;
  30. struct jpeg_error_mgr *jem = new jpeg_error_mgr;
  31. spjcs->err = jpeg_std_error(jem); // Init the error handler
  32. jpeg_create_compress(spjcs); // Init the compression object
  33. if (ColorSpace == JCS_GRAYSCALE)
  34. {
  35. spjcs->in_color_space = JCS_GRAYSCALE;
  36. spjcs->input_components = 1;
  37. }
  38. else
  39. {
  40. spjcs->in_color_space = JCS_RGBA;
  41. spjcs->input_components = 4;
  42. }
  43. jpeg_set_defaults(spjcs); // Init the compression engine with the defaults
  44. jpeg_set_quality(spjcs, tuQuality, TRUE);
  45. jpeg_set_colorspace(spjcs,ColorSpace);
  46. jpeg_mem_dest(spjcs, prgbJPEGHeaderBuf); // Init the "destination manager"
  47. spjcs->comps_in_scan = 0;
  48. spjcs->write_JFIF_header = FALSE;
  49. jpeg_write_tables(spjcs);
  50. jpeg_suppress_tables(spjcs, TRUE);
  51. *pcbOut = spjcs->bytes_in_buffer;
  52. *phJpegC = (HANDLE) spjcs;
  53. }
  54. catch( THROWN thrownHR )
  55. {
  56. hr = thrownHR.Hr();
  57. }
  58. return hr;
  59. }
  60. /* JPEGDecompressHeader()
  61. *
  62. * Arguments:
  63. * *prgbJPEGBuf : pointer to the JPEG header data as read from file
  64. * *phJpegD: pointer to Handle of the JPEG decompression object returned
  65. *
  66. * Returns:
  67. * HRESULT
  68. */
  69. HRESULT JPEGDecompressHeader(BYTE *prgbJPEGHeaderBuf, HANDLE *phJpegD, ULONG ulBufferSize)
  70. {
  71. HRESULT hr = S_OK;
  72. try
  73. {
  74. jpeg_decompress_struct * spjds = new jpeg_decompress_struct;
  75. struct jpeg_error_mgr *jem = new jpeg_error_mgr;
  76. spjds->err = jpeg_std_error(jem); // Init the error handler
  77. jpeg_create_decompress(spjds); // Init the decompression object
  78. // Now we need to "read" it into the decompression object...
  79. jpeg_mem_src(spjds, prgbJPEGHeaderBuf, ulBufferSize);
  80. jpeg_read_header(spjds, TRUE);
  81. spjds->out_color_space = JCS_RGBA;
  82. *phJpegD = (HANDLE) spjds;
  83. }
  84. catch( THROWN thrownHR )
  85. {
  86. hr = thrownHR.Hr();
  87. }
  88. return hr;
  89. }
  90. // DestroyJPEGCompress
  91. //
  92. // Release all the JPEG stuff from the handle we gave to the user
  93. //
  94. HRESULT DestroyJPEGCompressHeader(HANDLE hJpegC)
  95. {
  96. HRESULT hr = S_OK;
  97. try
  98. {
  99. struct jpeg_compress_struct *pjcs = (struct jpeg_compress_struct *)hJpegC;
  100. jpeg_destroy_compress(pjcs);
  101. delete pjcs->err;
  102. delete pjcs;
  103. }
  104. catch( THROWN thrownHR )
  105. {
  106. hr = thrownHR.Hr();
  107. }
  108. return hr;
  109. }
  110. // DestroyJPEGDecompressHeader
  111. //
  112. // Release all the JPEG stuff from the handle we gave to the user
  113. //
  114. HRESULT DestroyJPEGDecompressHeader(HANDLE hJpegD)
  115. {
  116. HRESULT hr = S_OK;
  117. try
  118. {
  119. struct jpeg_decompress_struct *pjds = (struct jpeg_decompress_struct *)hJpegD;
  120. jpeg_destroy_decompress(pjds);
  121. delete pjds->err;
  122. delete pjds;
  123. }
  124. catch( THROWN thrownHR )
  125. {
  126. hr = thrownHR.Hr();
  127. }
  128. return hr;
  129. }
  130. /* JPEGFromRGBA()
  131. *
  132. * Arguments:
  133. * prgbImage A raw image buffer (4 bytes/pixel, RGBA order)
  134. * cpxlAcross Width of the image, in pixels
  135. * cpxlDown Height of the image, in pixels
  136. * tuQuality "Quality" of the resulting JPEG (0..100, 100=best)
  137. * A memory buffer containing the complete JPEG compressed version of the
  138. * given image. NULL on error.
  139. *
  140. * Returns:
  141. * HRESULT
  142. */
  143. HRESULT JPEGFromRGBA(
  144. BYTE *prgbImage,
  145. BYTE *prgbJPEGBuf,
  146. UINT tuQuality,
  147. ULONG *pcbOut,
  148. HANDLE hJpegC,
  149. J_COLOR_SPACE ColorSpace,
  150. UINT nWidth,
  151. UINT nHeight
  152. )
  153. {
  154. HRESULT hr = S_OK;
  155. try
  156. {
  157. struct jpeg_compress_struct *pjcs = (jpeg_compress_struct *)hJpegC;
  158. JSAMPROW rgrow[1];
  159. //
  160. // On non X86 architectures use only C code
  161. //
  162. #if defined (_X86_)
  163. pjcs->dct_method = JDCT_ISLOW;
  164. #else
  165. pjcs->dct_method = JDCT_FLOAT;
  166. #endif
  167. pjcs->image_width = nWidth;
  168. pjcs->image_height = nHeight;
  169. pjcs->data_precision = 8; /* 8 bits / sample */
  170. pjcs->bytes_in_buffer = 0;
  171. pjcs->write_JFIF_header = FALSE;
  172. if (ColorSpace == JCS_GRAYSCALE)
  173. {
  174. pjcs->input_components = 1;
  175. }
  176. else
  177. {
  178. pjcs->input_components = 4;
  179. }
  180. jpeg_set_colorspace(pjcs,ColorSpace);
  181. jpeg_set_quality(pjcs, tuQuality, TRUE);
  182. jpeg_suppress_tables(pjcs, TRUE);
  183. jpeg_mem_dest(pjcs, prgbJPEGBuf); // Init the "destination manager"
  184. jpeg_start_compress(pjcs, FALSE);
  185. rgrow[0] = (JSAMPROW)prgbImage;
  186. while (pjcs->next_scanline < nHeight )
  187. {
  188. jpeg_write_scanlines(pjcs, rgrow, 1);
  189. rgrow[0] += nWidth * pjcs->input_components; //input_components is the equivalent of # of bytes
  190. }
  191. jpeg_finish_compress(pjcs); // Finish up compressing
  192. *pcbOut = pjcs->bytes_in_buffer;
  193. }
  194. catch( THROWN thrownHR )
  195. {
  196. hr = thrownHR.Hr();
  197. }
  198. return hr;
  199. }
  200. /* RGBAFromJPEG()
  201. *
  202. * Arguments:
  203. * prgbJPEG: A JPEG data stream, as returned by JPEGFromRGBA()
  204. * A memory buffer containing the reconstructed image in RGBA format.
  205. * NULL on error.
  206. *
  207. * Returns:
  208. * HRESULT
  209. */
  210. HRESULT RGBAFromJPEG(BYTE *prgbJPEG, BYTE *prgbImage, HANDLE hJpegD, ULONG ulBufferSize, BYTE bJPEGConversionType, ULONG *pulReturnedNumChannels, UINT nWidth, UINT nHeight )
  211. {
  212. HRESULT hr = S_OK;
  213. try
  214. {
  215. struct jpeg_decompress_struct *pjds;
  216. jpeg_decompress_struct * spjds = new jpeg_decompress_struct;
  217. struct jpeg_error_mgr *jem;
  218. jpeg_error_mgr * spjem = new jpeg_error_mgr;
  219. if ( hJpegD == NULL )
  220. {
  221. spjds->err = jpeg_std_error(spjem); // Init the error handler
  222. jpeg_create_decompress(spjds); // Init the decompression object in the case
  223. pjds = spjds; // that the headers are with the tiles.
  224. jem = spjem;
  225. }
  226. else if ( hJpegD == NULL )
  227. {
  228. // This should never happen. The decompression header was not set up return an
  229. // error indication by setting the return value to kpvNil.
  230. return E_FAIL;
  231. }
  232. else
  233. {
  234. pjds = (struct jpeg_decompress_struct *)hJpegD;
  235. }
  236. JSAMPROW rgrow[1];
  237. // Set the various image parameters.
  238. pjds->data_precision = 8;
  239. pjds->image_width = nWidth;
  240. pjds->image_height = nHeight;
  241. jpeg_mem_src(pjds, prgbJPEG, ulBufferSize); // Init the "source manager"
  242. jpeg_read_header(pjds, TRUE);
  243. switch (bJPEGConversionType)
  244. {
  245. case 1:
  246. pjds->out_color_space = JCS_RGBA;
  247. if (pjds->jpeg_color_space != JCS_RGBA)
  248. {
  249. if ( 4 == pjds->num_components)
  250. pjds->jpeg_color_space = JCS_YCbCrA;
  251. else
  252. pjds->jpeg_color_space = JCS_YCbCr;
  253. }
  254. *pulReturnedNumChannels = 4;
  255. break;
  256. case 2:
  257. pjds->out_color_space = JCS_RGBA;
  258. if ( 4 == pjds->num_components)
  259. pjds->jpeg_color_space = JCS_YCbCrA;
  260. else
  261. pjds->jpeg_color_space = JCS_YCbCr;
  262. pjds->jpeg_color_space = JCS_YCbCrA;
  263. *pulReturnedNumChannels = 4;
  264. break;
  265. default:
  266. pjds->out_color_space = JCS_UNKNOWN;
  267. pjds->jpeg_color_space = JCS_UNKNOWN;
  268. *pulReturnedNumChannels = pjds->num_components;
  269. }
  270. //
  271. // On non X86 architectures use only C code
  272. //
  273. #if defined (_X86_)
  274. pjds->dct_method = JDCT_ISLOW;
  275. #else
  276. pjds->dct_method = JDCT_FLOAT;
  277. #endif
  278. jpeg_start_decompress(pjds);
  279. rgrow[0] = (JSAMPROW)prgbImage;
  280. while (pjds->output_scanline < pjds->output_height)
  281. {
  282. jpeg_read_scanlines(pjds, rgrow, 1);
  283. rgrow[0] += pjds->output_width * *pulReturnedNumChannels;
  284. }
  285. jpeg_finish_decompress(pjds); // Finish up decompressing
  286. if (hJpegD == NULL)
  287. jpeg_destroy_decompress(pjds); //Destroy the decompression object if it
  288. //was locally allocated as in when the header
  289. //is part of the tile.
  290. delete spjem;
  291. delete spjds;
  292. }
  293. catch( THROWN thrownHR )
  294. {
  295. hr = thrownHR.Hr();
  296. }
  297. return hr;
  298. }
  299. HRESULT
  300. GetJPEGHeaderFields(
  301. HANDLE hJpegD,
  302. UINT *pWidth,
  303. UINT *pHeight,
  304. INT *pNumComponents,
  305. J_COLOR_SPACE *pColorSpace
  306. )
  307. {
  308. struct jpeg_decompress_struct *pjds;
  309. pjds = (struct jpeg_decompress_struct *)hJpegD;
  310. if (hJpegD) {
  311. *pWidth = pjds->image_width;
  312. *pHeight = pjds->image_height;
  313. *pNumComponents = pjds->num_components;
  314. *pColorSpace = pjds->jpeg_color_space;
  315. }
  316. return S_OK;
  317. }
  318. BOOL
  319. WINAPI
  320. Win32DIBFromJPEG(
  321. BYTE *prgbJPEG,
  322. ULONG ulBufferSize,
  323. LPBITMAPINFO pbmi,
  324. HBITMAP *phBitmap,
  325. PVOID *ppvBits
  326. )
  327. {
  328. BITMAPINFO bmi;
  329. struct jpeg_decompress_struct *pjds;
  330. jpeg_decompress_struct * spjds = new jpeg_decompress_struct;
  331. struct jpeg_error_mgr *jem;
  332. jpeg_error_mgr * spjem = new jpeg_error_mgr;
  333. // Only 24bpp for now
  334. const UINT uiReturnedNumChannels = 3;
  335. //
  336. spjds->err = jpeg_std_error(spjem); // Init the error handler
  337. jpeg_create_decompress(spjds); // Init the decompression object in the case
  338. pjds = spjds; // that the headers are with the tiles.
  339. jem = spjem;
  340. JSAMPROW rgrow[1];
  341. // Set the various image parameters.
  342. try {
  343. jpeg_buf_src(pjds, prgbJPEG, ulBufferSize); // Init the "source manager"
  344. jpeg_read_header(pjds, TRUE);
  345. } catch (...) {
  346. //
  347. // for some reason we crashed, so return the exception code
  348. //
  349. #ifdef DEBUG
  350. OutputDebugString("JPEG DIB crashed");
  351. #endif
  352. return FALSE;
  353. }
  354. // Set parameter for decompression
  355. // Defaults are OK for this occasssion
  356. // Specify the JCS_BGR output colorspace
  357. pjds->out_color_space = JCS_BGR;
  358. // pjds->out_color_space = JCS_RGB;
  359. //
  360. // Create DIB bits
  361. //
  362. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  363. pbmi->bmiHeader.biWidth = pjds->image_width;
  364. pbmi->bmiHeader.biHeight = -((int)pjds->image_height); // Top Down bitmap
  365. pbmi->bmiHeader.biPlanes = 1;
  366. pbmi->bmiHeader.biBitCount = 24; // BUGBUG careful
  367. pbmi->bmiHeader.biCompression = BI_RGB;
  368. pbmi->bmiHeader.biSizeImage = 0;
  369. pbmi->bmiHeader.biXPelsPerMeter = 0;
  370. pbmi->bmiHeader.biYPelsPerMeter = 0;
  371. pbmi->bmiHeader.biClrUsed = 0;
  372. pbmi->bmiHeader.biClrImportant = 0;
  373. *phBitmap = ::CreateDIBSection (NULL,
  374. pbmi,
  375. DIB_RGB_COLORS,
  376. ppvBits,
  377. NULL,
  378. 0);
  379. //
  380. // On non X86 architectures use only C code
  381. //
  382. #if defined (_X86_)
  383. pjds->dct_method = JDCT_ISLOW;
  384. #else
  385. pjds->dct_method = JDCT_FLOAT;
  386. #endif
  387. jpeg_start_decompress(pjds);
  388. rgrow[0] = (JSAMPROW)*ppvBits;
  389. while (pjds->output_scanline < pjds->output_height)
  390. {
  391. jpeg_read_scanlines(pjds, rgrow, 1);
  392. // Invert BGR --> RGB
  393. #ifdef INVERTBGR
  394. RGBTRIPLE *pTriplet;
  395. pTriplet = (RGBTRIPLE *) rgrow[0];
  396. for (int iPixel = 0;
  397. iPixel < (int)pjds->output_width;
  398. iPixel++,pTriplet++) {
  399. BYTE bTemp;
  400. bTemp = pTriplet->rgbtBlue;
  401. pTriplet->rgbtBlue = pTriplet->rgbtRed;
  402. pTriplet->rgbtRed = bTemp;
  403. }
  404. #endif
  405. rgrow[0] = (JSAMPROW) ALIGNIT(rgrow[0] + pjds->output_width * uiReturnedNumChannels,DWORD);
  406. }
  407. jpeg_finish_decompress(pjds); // Finish up decompressing
  408. jpeg_destroy_decompress(pjds); //Destroy the decompression object
  409. delete spjem;
  410. delete spjds;
  411. return TRUE;
  412. }
  413. BOOL
  414. WINAPI
  415. JPEGFromWin32DIB(
  416. HBITMAP hBitmap,
  417. BYTE *prgbJPEG,
  418. ULONG ulBufferSize,
  419. LPBITMAPINFO pbmi,
  420. PVOID *ppvBits
  421. )
  422. {
  423. return TRUE;
  424. }