2
0

ilcompressjpeg.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: ilcompressjpeg.c /main/4 1996/01/08 12:14:02 lehors $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1991 Hewlett-Packard Co.
  27. ***
  28. *** RESTRICTED RIGHTS LEGEND
  29. *** Use, duplication, or disclosure by the U.S. Government is subject to
  30. *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
  31. *** Technical Data and Computer Software clause in DFARS 252.227-7013.
  32. *** Hewlett-Packard Company
  33. *** 3000 Hanover Street
  34. *** Palo Alto, CA 94304 U.S.A.
  35. *** Rights for non-DOD U.S. Government Departments and Agencies are as set
  36. *** forth in FAR 52.227-19(c)(1,2).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. #include "ilint.h"
  40. #include "ilpipelem.h"
  41. #include "ilcompress.h"
  42. #include "ilcodec.h"
  43. #include "ilerrors.h"
  44. #include "ilutiljpeg.h"
  45. #include "iljpgencode.h"
  46. /* ============================= JIF to Raw =================================== */
  47. /* This body of code supports converting JIF format JPEG to "raw" (stripped).
  48. */
  49. /* Private data for ilJIFToRawExecute() */
  50. typedef struct {
  51. ilJPEGData *pCompData; /* ptr to IL JPEG data */
  52. } ilJIFToRawPrivRec, *ilJIFToRawPrivPtr;
  53. /* ----------------------- ilJIFToRawDestroy ------------------------------ */
  54. /* Destroy() function for converting JIF format JPEG to "raw" JPEG.
  55. */
  56. static ilError ilJIFToRawDestroy (
  57. ilJIFToRawPrivPtr pPriv
  58. )
  59. {
  60. /* Free pCompData including associated tables */
  61. if (pPriv->pCompData) {
  62. _ilJPEGFreeTables (pPriv->pCompData);
  63. IL_FREE (pPriv->pCompData);
  64. }
  65. return IL_OK;
  66. }
  67. /* ----------------------- ilJIFToRawExecute ------------------------------ */
  68. /* Execute() function for converting JIF format JPEG to "raw" JPEG.
  69. */
  70. static ilError ilJIFToRawExecute (
  71. ilExecuteData *pData,
  72. unsigned long dstLine,
  73. unsigned long *pNLines
  74. )
  75. {
  76. ilJPEGDecodeStream streamRec;
  77. iljpgDataPtr pJPEGData;
  78. ilError error;
  79. int i;
  80. ilJPEGData *pCompData;
  81. ilImagePlaneInfo *pDstPlane;
  82. long dstOffset, nBytes;
  83. /* Parse the src data, which is a JIF data stream */
  84. streamRec.pData = pData->pSrcImage->plane[0].pPixels;
  85. streamRec.nBytesLeft = pData->compressed.nBytesToRead;
  86. if (error = iljpgDecodeJIF (&streamRec, &pJPEGData))
  87. return error;
  88. /* Point pCompData to tables decoded from JIF, and copy table indices. */
  89. pCompData = ((ilJIFToRawPrivPtr)pData->pPrivate)->pCompData;
  90. for (i = 0; i < 4; i++) {
  91. pCompData->QTables[i] = pJPEGData->QTables[i];
  92. pCompData->DCTables[i] = pJPEGData->DCTables[i];
  93. pCompData->ACTables[i] = pJPEGData->ACTables[i];
  94. }
  95. for (i = 0; i < ILJPG_MAX_COMPS; i++) {
  96. pCompData->sample[i].QTableIndex = pJPEGData->comp[i].QTableIndex;
  97. pCompData->sample[i].DCTableIndex = pJPEGData->comp[i].DCTableIndex;
  98. pCompData->sample[i].ACTableIndex = pJPEGData->comp[i].ACTableIndex;
  99. }
  100. /* Copy restartInterval from JIF info; it will be zero (0) if no DRI marker,
  101. implying no restart markers.
  102. */
  103. pCompData->restartInterval = pJPEGData->restartInterval;
  104. /* Free decode data but not tables; they will be freed by ilJIFToRawDestroy() */
  105. IL_FREE (pJPEGData);
  106. /* Write rest of data (actual JPEG data, after tables etc.) to next filter.
  107. Exclude the EOI marker if present (which it really should be).
  108. */
  109. nBytes = streamRec.nBytesLeft;
  110. if ((nBytes >= 2)
  111. && (streamRec.pData[nBytes-2] == ILJPGM_FIRST_BYTE)
  112. && (streamRec.pData[nBytes-1] == ILJPGM_EOI))
  113. nBytes -= 2; /* remove EOI marker */
  114. dstOffset = *pData->compressed.pDstOffset;
  115. pDstPlane = pData->pDstImage->plane;
  116. if (pDstPlane->bufferSize < (nBytes + dstOffset))
  117. if (!_ilReallocCompressedBuffer (pData->pDstImage, 0, (nBytes + dstOffset)))
  118. return IL_ERROR_MALLOC;
  119. bcopy ((char *)streamRec.pData,
  120. (char *)(pDstPlane->pPixels + dstOffset), nBytes);
  121. *pData->compressed.pNBytesWritten = nBytes;
  122. return IL_OK;
  123. }
  124. /* ----------------------- ilJIFToRaw ------------------------------ */
  125. /* Called by _ilCompressJPEG() when the pipe image is JIF format, to
  126. convert to "raw" JPEG format.
  127. */
  128. static ilBool ilJIFToRaw (
  129. ilPipe pipe,
  130. ilPipeInfo *pInfo,
  131. ilImageDes *pDes,
  132. ilImageFormat *pFormat
  133. )
  134. {
  135. ilJPEGData *pCompData;
  136. ilJIFToRawPrivPtr pPriv;
  137. ilDstElementData dstData;
  138. /* Allocate an IL raw JPEG data block; point to it for pipe element */
  139. if (!(pCompData = (ilJPEGData *)IL_MALLOC_ZERO (sizeof (ilJPEGData))))
  140. return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  141. dstData.producerObject = (ilObject)NULL;
  142. pDes->compInfo.JPEG.reserved |= IL_JPEGM_RAW; /* now writing raw JPEG */
  143. dstData.pDes = pDes;
  144. dstData.pFormat = pFormat;
  145. dstData.width = pInfo->width;
  146. dstData.height = pInfo->height;
  147. dstData.stripHeight = pInfo->height; /* write one strip = whole image */
  148. dstData.constantStrip = TRUE;
  149. dstData.pPalette = (unsigned short *)NULL;
  150. dstData.pCompData = (ilPtr)pCompData;
  151. pPriv = (ilJIFToRawPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  152. sizeof (ilJIFToRawPrivRec), 0, (ilSrcElementData *)NULL, &dstData,
  153. IL_NPF, IL_NPF, ilJIFToRawDestroy, ilJIFToRawExecute, 0);
  154. if (!pPriv)
  155. return FALSE;
  156. pPriv->pCompData = pCompData;
  157. return TRUE;
  158. }
  159. /* ============================= Raw to JIF =================================== */
  160. /* This body of code supports converting "raw" (stripped) format JPEG to JIF.
  161. */
  162. /* Private data for ilRawToJIFExecute() */
  163. typedef struct {
  164. ilJPEGData *pCompData; /* ptr to IL JPEG data */
  165. long width; /* width of image */
  166. long height; /* total # lines in image */
  167. long stripHeight; /* # lines per strip */
  168. ilBool nStripsWritten; /* inited to 0 by Init() */
  169. long nLinesWritten; /* inited to 0 by Init() */
  170. long dstOffset; /* inited to 0 by Init() */
  171. } ilRawToJIFPrivRec, *ilRawToJIFPrivPtr;
  172. /* ----------------------- ilRawToJIFInit ------------------------------ */
  173. /* Init() function for converting JIF format pipe image to raw format.
  174. */
  175. static ilError ilRawToJIFInit (
  176. ilRawToJIFPrivPtr pPriv,
  177. ilImageInfo *pSrcImage,
  178. ilImageInfo *pDstImage
  179. )
  180. {
  181. pPriv->nStripsWritten = 0;
  182. pPriv->nLinesWritten = 0;
  183. pPriv->dstOffset = 0;
  184. return IL_OK;
  185. }
  186. /* ----------------------- ilRawToJIFExecute ------------------------------ */
  187. /* Execute() function for converting "raw" JPEG to JIF format.
  188. */
  189. static ilError ilRawToJIFExecute (
  190. ilExecuteData *pData,
  191. unsigned long dstLine,
  192. unsigned long *pNLines
  193. )
  194. {
  195. ilJPEGEncodeStream streamRec;
  196. ilRawToJIFPrivPtr pPriv;
  197. iljpgDataRec data;
  198. ilImageInfo *pImage;
  199. ilError error;
  200. long nBytes, startOffset;
  201. ilBool lastStrip;
  202. pPriv = (ilRawToJIFPrivPtr)pData->pPrivate;
  203. /* Setup stream to point to dst image buffer; set size, offset also.
  204. "dstOffset" is offset into dst buffer; it is incremented by the # of
  205. bytes written on each strip. When done, it is size of JIF image written.
  206. */
  207. pImage = pData->pDstImage;
  208. streamRec.pBuffer = pImage->plane[0].pPixels;
  209. streamRec.pDst = streamRec.pBuffer + pPriv->dstOffset;
  210. streamRec.pPastEndBuffer = streamRec.pBuffer + pImage->plane[0].bufferSize;
  211. startOffset = ILJPG_ENCODE_OFFSET(&streamRec); /* stream offset before any writes */
  212. pImage = pData->pSrcImage; /* point to src (raw) image */
  213. /* If first strip write out the JIF header */
  214. if (pPriv->nStripsWritten == 0) {
  215. /* Setup iljpg data block: general info and tables from IL */
  216. _ilJPEGDataIn (pImage->pDes, pPriv->width, pPriv->height, &data);
  217. _ilJPEGTablesIn (pPriv->pCompData, &data);
  218. /* Set restart interval: if a single strip, it is the restart interval
  219. in the raw data (already set from above). If not a single strip, then
  220. the raw data must not have a restart interval or an error - can't code
  221. both of them! Otherwise restart interval is determined by strip size.
  222. */
  223. if (pPriv->stripHeight != pPriv->height) { /* not single strip */
  224. long mcuWidth, mcuHeight;
  225. if (data.restartInterval)
  226. return IL_ERROR_COMPRESSED_DATA; /* have restartInterval; error */
  227. mcuWidth = 8 * data.maxHoriFactor;
  228. mcuHeight = 8 * data.maxVertFactor;
  229. data.restartInterval = /* # of mcus across * # down */
  230. ((data.width + mcuWidth - 1) / mcuWidth) *
  231. ((pPriv->stripHeight + mcuHeight - 1) / mcuHeight);
  232. }
  233. /* Write JIF to output stream, from IL's comp data */
  234. if (error = iljpgEncodeJIF (&streamRec, &data, (iljpgJIFOffsetsPtr)NULL))
  235. return error;
  236. }
  237. /* Write data from this strip to output buffer, reallocating if necessary.
  238. Allocate 2 extra bytes for EOI or RSTn marker.
  239. */
  240. nBytes = pData->compressed.nBytesToRead;
  241. if ((streamRec.pDst + nBytes + 2) >= streamRec.pPastEndBuffer) {
  242. if (error = _ilReallocJPEGEncode (&streamRec, nBytes + 2))
  243. return error;
  244. }
  245. bcopy ((char *)(pImage->plane[0].pPixels + pData->compressed.srcOffset),
  246. (char *)streamRec.pDst, nBytes);
  247. streamRec.pDst += nBytes; /* bump past data just copied */
  248. /* If last strip, write 2 byte EOI marker else write 2 byte restart marker. */
  249. pPriv->nLinesWritten += *pNLines;
  250. lastStrip = (pPriv->nLinesWritten >= pPriv->height);
  251. if (lastStrip) {
  252. *streamRec.pDst++ = ILJPGM_FIRST_BYTE; /* last strip; write EOI marker */
  253. *streamRec.pDst++ = ILJPGM_EOI;
  254. }
  255. else {
  256. /* Not last strip; write RST marker, with modulo 8 strip count */
  257. *streamRec.pDst++ = ILJPGM_FIRST_BYTE;
  258. *streamRec.pDst++ = ILJPGM_RST0 | (pPriv->nStripsWritten & 7);
  259. }
  260. pPriv->nStripsWritten += 1;
  261. /* Store stream data into dst image; bump dst offset by # bytes written */
  262. pImage = pData->pDstImage;
  263. pImage->plane[0].pPixels = streamRec.pBuffer;
  264. pImage->plane[0].bufferSize = streamRec.pPastEndBuffer - streamRec.pBuffer;
  265. pPriv->dstOffset += ILJPG_ENCODE_OFFSET(&streamRec) - startOffset;
  266. /* If last strip, pass # bytes written to next filter (= current dst offset;
  267. note that dst offset set to 0 on first strip), and return # lines =
  268. height of image, as JIF is one big strip. If not last strip, return
  269. # lines as zero and next filter will not be called.
  270. */
  271. if (lastStrip) {
  272. *pNLines = pPriv->height;
  273. *pData->compressed.pNBytesWritten = pPriv->dstOffset;
  274. }
  275. else *pNLines = 0;
  276. return IL_OK;
  277. }
  278. /* ----------------------- ilRawToJIF ------------------------------ */
  279. /* Called by _ilCompressJPEG() when the pipe image is "raw" JPEG format,
  280. to convert to JIF format.
  281. */
  282. static ilBool ilRawToJIF (
  283. ilPipe pipe,
  284. ilPipeInfo *pInfo,
  285. ilImageDes *pDes,
  286. ilImageFormat *pFormat
  287. )
  288. {
  289. ilRawToJIFPrivPtr pPriv;
  290. ilDstElementData dstData;
  291. dstData.producerObject = (ilObject)NULL;
  292. pDes->compInfo.JPEG.reserved &= ~IL_JPEGM_RAW; /* now writing JIF, not raw JPEG */
  293. dstData.pDes = pDes;
  294. dstData.pFormat = pFormat;
  295. dstData.width = pInfo->width;
  296. dstData.height = pInfo->height;
  297. dstData.stripHeight = pInfo->height; /* write one strip = whole image */
  298. dstData.constantStrip = TRUE;
  299. dstData.pPalette = (unsigned short *)NULL;
  300. dstData.pCompData = (ilPtr)NULL;
  301. /* Add the filter. "Hold dst" flag set because filter will write to
  302. output buffer, returning # lines = 0 until last strip written, after which
  303. whole output buffer will be passed to next filter, # lines = height.
  304. */
  305. pPriv = (ilRawToJIFPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  306. sizeof (ilRawToJIFPrivRec), IL_ADD_PIPE_HOLD_DST, (ilSrcElementData *)NULL,
  307. &dstData, ilRawToJIFInit, IL_NPF, IL_NPF, ilRawToJIFExecute, 0);
  308. if (!pPriv)
  309. return FALSE;
  310. pPriv->pCompData = (ilJPEGData *)pInfo->pCompData;
  311. pPriv->width = pInfo->width;
  312. pPriv->height = pInfo->height;
  313. pPriv->stripHeight = pInfo->stripHeight; /* input strip height */
  314. return TRUE;
  315. }
  316. /* ============================= Compress Raw =================================== */
  317. /* This body of code supports compressing to JPEG "raw" format.
  318. */
  319. /* Private data for ilCompressJPEGExecute() */
  320. typedef struct {
  321. ilJPEGData *pCompData; /* ptr to IL's view of JPEG data */
  322. iljpgDataRec jpgData; /* data for iljpg functions */
  323. iljpgPtr jpgPriv; /* pointer to iljpg private data */
  324. } ilCompressJPEGPrivRec, *ilCompressJPEGPrivPtr;
  325. /* -------------------- ilCompressJPEGInit -------------------------- */
  326. /* Init() function for compressing to "raw" JPEG.
  327. */
  328. static ilError ilCompressJPEGInit (
  329. ilCompressJPEGPrivPtr pPriv,
  330. ilImageInfo *pSrcImage,
  331. ilImageInfo *pDstImage
  332. )
  333. {
  334. ilError error;
  335. /* Init iljpg package for compression */
  336. if (error = iljpgEncodeInit (&pPriv->jpgData, &pPriv->jpgPriv))
  337. return error;
  338. return IL_OK;
  339. }
  340. /* -------------------- ilCompressJPEGCleanup -------------------------- */
  341. /* Cleanup() function for compressing to "raw" JPEG.
  342. */
  343. static ilError ilCompressJPEGCleanup (
  344. ilCompressJPEGPrivPtr pPriv,
  345. ilBool aborting
  346. )
  347. {
  348. ilError error;
  349. /* Call iljpg package cleanup function */
  350. return iljpgEncodeCleanup (pPriv->jpgPriv);
  351. }
  352. /* ----------------------- ilCompressJPEGDestroy ------------------------------ */
  353. /* Destroy() function for compressing to "raw" JPEG.
  354. */
  355. static ilError ilCompressJPEGDestroy (
  356. ilCompressJPEGPrivPtr pPriv
  357. )
  358. {
  359. int i;
  360. ilPtr pTable;
  361. ilJPEGData *pCompData;
  362. /* Free pCompData and any non-default Q tables */
  363. if (pCompData = pPriv->pCompData) {
  364. for (i = 0; i < 4; i++) {
  365. if ((pTable = pCompData->QTables[i])
  366. && (pTable != iljpgLuminanceQTable)
  367. && (pTable != iljpgChrominanceQTable))
  368. IL_FREE (pTable);
  369. }
  370. IL_FREE (pCompData);
  371. }
  372. return IL_OK;
  373. }
  374. /* ----------------------- ilCompressJPEGExecute ------------------------------ */
  375. /* Execute() function for compressing to "raw" JPEG.
  376. */
  377. static ilError ilCompressJPEGExecute (
  378. ilExecuteData *pData,
  379. unsigned long dstLine,
  380. unsigned long *pNLines
  381. )
  382. {
  383. ilCompressJPEGPrivPtr pPriv;
  384. ilJPEGEncodeStream streamRec;
  385. ilImageInfo *pImage;
  386. ilImagePlaneInfo *pSrcPlane;
  387. long nBytes, startOffset;
  388. ilError error;
  389. int i;
  390. iljpgPtr pSrcPixels[IL_MAX_SAMPLES];
  391. long nSrcBytesPerRow[IL_MAX_SAMPLES];
  392. pPriv = (ilCompressJPEGPrivPtr)pData->pPrivate;
  393. /* Setup stream to point to dst image buffer; set size, offset also */
  394. pImage = pData->pDstImage;
  395. streamRec.pBuffer = pImage->plane[0].pPixels;
  396. streamRec.pDst = streamRec.pBuffer + *pData->compressed.pDstOffset;
  397. streamRec.pPastEndBuffer = streamRec.pBuffer + pImage->plane[0].bufferSize;
  398. startOffset = ILJPG_ENCODE_OFFSET(&streamRec); /* stream offset before any writes */
  399. /* Encode one strip, writing output to dst buffer (pointed to by streamRec).
  400. Input is from src buffer, starting at srcLine, divided by subsample factor
  401. (which is "inverse" of JPEG factors; = max factor / component factor).
  402. */
  403. pSrcPlane = pData->pSrcImage->plane;
  404. for (i = 0; i < pPriv->jpgData.nComps; i++, pSrcPlane++) {
  405. pSrcPixels[i] = pSrcPlane->pPixels + (pData->srcLine *
  406. pPriv->jpgData.comp[i].vertFactor / pPriv->jpgData.maxVertFactor) *
  407. pSrcPlane->nBytesPerRow;
  408. nSrcBytesPerRow[i] = pSrcPlane->nBytesPerRow;
  409. }
  410. if (error = iljpgEncodeExecute (pPriv->jpgPriv, &streamRec, *pNLines,
  411. pSrcPixels, nSrcBytesPerRow))
  412. return error;
  413. /* Set stream data back into dst image structure. Inform next filter of
  414. the # bytes written = current stream offset - start offset.
  415. */
  416. pImage->plane[0].pPixels = streamRec.pBuffer;
  417. pImage->plane[0].bufferSize = streamRec.pPastEndBuffer - streamRec.pBuffer;
  418. *pData->compressed.pNBytesWritten = ILJPG_ENCODE_OFFSET(&streamRec) - startOffset;
  419. return IL_OK;
  420. }
  421. /* ------------------------- _ilScaleQTable -------------------------------- */
  422. /* Malloc a new 64 byte table, copy given src Q table scaling by given Q factor
  423. and return ptr to new table, or null if error.
  424. */
  425. static ilPtr _ilScaleQTable (
  426. ilPtr pSrc, /* ptr to 64 byte Q table to scale */
  427. int Q /* IL Q factor: != 0, or no scale needed */
  428. )
  429. {
  430. ilPtr pTable;
  431. ilPtr pDst;
  432. int i, value;
  433. if (!(pTable = (ilPtr)IL_MALLOC (64)))
  434. return (ilPtr)NULL;
  435. /* Scale src to dst (pTable) by: dst = src * Qfactor / 50.
  436. I don't know where this came from, but it is how the old code worked.
  437. The old code however only allowed a max Q of 255; larger values became 255.
  438. Here we will allow the maximum value of a short.
  439. */
  440. for (i = 0, pDst = pTable; i < 64; i++) {
  441. value = (*pSrc++ * Q) / 50;
  442. if (value > 255)
  443. value = 255;
  444. else if (value < 1)
  445. value = 1;
  446. *pDst++ = value;
  447. }
  448. return pTable;
  449. }
  450. /* ----------------------- _ilCompressJPEG ------------------------------ */
  451. /* Called by ilCompress() when desired compression is JPEG. The image
  452. may already be JPEG-compressed, but possibly in the wrong format (JIF/raw).
  453. This function handles conversions between those cases, or does
  454. nothing if image is already in correct format.
  455. On entry, the image must be either JPEG-compressed or uncompressed.
  456. */
  457. IL_PRIVATE ilBool _ilCompressJPEG (
  458. ilPipe pipe,
  459. ilPipeInfo *pInfo,
  460. ilImageDes *pDes,
  461. ilImageFormat *pFormat,
  462. ilSrcElementData *pSrcData,
  463. ilPtr pEncodeData
  464. )
  465. {
  466. ilCompressJPEGPrivPtr pPriv;
  467. ilJPEGData *pCompData;
  468. ilDstElementData dstData;
  469. ilJPEGEncodeControl *pEncode;
  470. int i, tableIndex, luminanceMask;
  471. ilPtr pTable;
  472. ilBool mustConvert;
  473. long stripHeight, maxVert;
  474. static ilJPEGEncodeControl ilDefaultJpegEncodeControl = {
  475. 0, /* short mustbezero; */
  476. 0 /* short Q; */
  477. };
  478. /* Check given encode data; default to JIF format, Q of 0 if null.
  479. Unused part of mustbezero must be zero or error.
  480. */
  481. if (!pEncodeData)
  482. pEncode = &ilDefaultJpegEncodeControl;
  483. else pEncode = (ilJPEGEncodeControl *)pEncodeData;
  484. if (pEncode->mustbezero & ~IL_JPEGM_RAW)
  485. return ilDeclarePipeInvalid (pipe, IL_ERROR_PAR_NOT_ZERO);
  486. /* If already JPEG-compressed cvt to requested format (JIF/raw) if necessary */
  487. if (pDes->compression == IL_JPEG) {
  488. if (pDes->compInfo.JPEG.reserved & IL_JPEGM_RAW) /* src is raw */
  489. if (pEncode->mustbezero & IL_JPEGM_RAW) { /* raw->raw */
  490. pipe->context->error = IL_OK;
  491. return TRUE;
  492. }
  493. else { /* raw->JIF */
  494. return ilRawToJIF (pipe, pInfo, pDes, pFormat);
  495. }
  496. else /* src is JIF */
  497. if (pEncode->mustbezero & IL_JPEGM_RAW) { /* JIF->raw */
  498. return ilJIFToRaw (pipe, pInfo, pDes, pFormat);
  499. }
  500. else { /* JIF->JIF */
  501. pipe->context->error = IL_OK;
  502. return TRUE;
  503. }
  504. }
  505. /* Image is not JPEG; must be uncompressed. Check for supported image type.
  506. Set maxVert to max vert subsampling; luminanceMask to sample #.
  507. */
  508. switch (pDes->type) {
  509. case IL_GRAY:
  510. maxVert = 1;
  511. luminanceMask = 1; /* gray is luminance */
  512. break;
  513. case IL_RGB:
  514. maxVert = 1; /* no subsampling of RGB */
  515. luminanceMask = ~0; /* use luminance tables for all components */
  516. break;
  517. case IL_YCBCR:
  518. maxVert = 1;
  519. if (pDes->typeInfo.YCbCr.sample[1].subsampleVert > maxVert)
  520. maxVert = pDes->typeInfo.YCbCr.sample[1].subsampleVert;
  521. if (pDes->typeInfo.YCbCr.sample[2].subsampleVert > maxVert)
  522. maxVert = pDes->typeInfo.YCbCr.sample[2].subsampleVert;
  523. luminanceMask = 1; /* Y is luminance */
  524. break;
  525. default:
  526. return ilDeclarePipeInvalid (pipe, IL_ERROR_IMAGE_TYPE);
  527. }
  528. /* Force all samples to be 8 bit, 256 levels / sample */
  529. for (i = 0, mustConvert = FALSE; i < pDes->nSamplesPerPixel; i++) {
  530. if (pDes->nLevelsPerSample[i] != 256) {
  531. pDes->nLevelsPerSample[i] = 256;
  532. mustConvert = TRUE;
  533. }
  534. if (pFormat->nBitsPerSample[i] != 8) {
  535. pFormat->nBitsPerSample[i] = 8;
  536. mustConvert = TRUE;
  537. }
  538. }
  539. if (mustConvert)
  540. if (!ilConvert (pipe, pDes, pFormat, 0, (ilPtr)NULL))
  541. return FALSE;
  542. /* Convert to planar format if more than 1 sample/pixel. */
  543. if ((pDes->nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PLANES)) {
  544. pFormat->sampleOrder = IL_SAMPLE_PLANES;
  545. if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, (ilPtr)NULL))
  546. return FALSE;
  547. }
  548. /* Check pSrcData->stripHeight: make it a multiple of MCU. */
  549. maxVert *= 8; /* now height of an MCU */
  550. stripHeight = ((pSrcData->stripHeight + maxVert - 1) / maxVert) * maxVert;
  551. if (stripHeight <= 0)
  552. stripHeight = maxVert;
  553. if (stripHeight > pInfo->height)
  554. stripHeight = pInfo->height;
  555. pSrcData->stripHeight = stripHeight;
  556. /* Allocate an IL raw JPEG data block; point to it for pipe element */
  557. if (!(pCompData = (ilJPEGData *)IL_MALLOC_ZERO (sizeof (ilJPEGData))))
  558. return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  559. /* Add the pipe element */
  560. dstData.producerObject = (ilObject)NULL;
  561. pDes->compInfo.JPEG.reserved |= IL_JPEGM_RAW; /* now writing raw JPEG */
  562. pDes->compression = IL_JPEG;
  563. dstData.pDes = pDes;
  564. pFormat->sampleOrder = IL_SAMPLE_PIXELS; /* JPEG interleaved order */
  565. dstData.pFormat = pFormat;
  566. dstData.width = pInfo->width;
  567. dstData.height = pInfo->height;
  568. dstData.stripHeight = stripHeight;
  569. dstData.constantStrip = TRUE;
  570. dstData.pPalette = (unsigned short *)NULL;
  571. dstData.pCompData = (ilPtr)pCompData;
  572. pPriv = (ilCompressJPEGPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  573. sizeof (ilCompressJPEGPrivRec), 0, pSrcData, &dstData,
  574. ilCompressJPEGInit, ilCompressJPEGCleanup, ilCompressJPEGDestroy,
  575. ilCompressJPEGExecute, 0);
  576. if (!pPriv)
  577. return FALSE;
  578. /* Init tables to use: default luminance (index 0) or chrominance (index 1).
  579. If "Q" not zero, scale up Q tables; must destroy them in Destroy().
  580. */
  581. pPriv->pCompData = pCompData;
  582. pCompData->restartInterval = 0; /* no restart markers added */
  583. for (i = 0; i < pDes->nSamplesPerPixel; i++) {
  584. if ((1 << i) & luminanceMask) {
  585. pCompData->DCTables[0] = iljpgLuminanceDCTable;
  586. pCompData->ACTables[0] = iljpgLuminanceACTable;
  587. tableIndex = 0;
  588. pTable = iljpgLuminanceQTable;
  589. }
  590. else {
  591. pCompData->DCTables[1] = iljpgChrominanceDCTable;
  592. pCompData->ACTables[1] = iljpgChrominanceACTable;
  593. tableIndex = 1;
  594. pTable = iljpgChrominanceQTable;
  595. }
  596. if (!pCompData->QTables[tableIndex]) { /* no Q table here yet; make one */
  597. if (pEncode->Q) /* Q != 0; scale copy of Q table */
  598. if (!(pTable = _ilScaleQTable (pTable, pEncode->Q)))
  599. return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  600. pCompData->QTables[tableIndex] = pTable;
  601. }
  602. pCompData->sample[i].QTableIndex = pCompData->sample[i].DCTableIndex =
  603. pCompData->sample[i].ACTableIndex = tableIndex;
  604. }
  605. /* Init iljpg package data in private, based on IL view of JPEG comp data */
  606. _ilJPEGDataIn (pDes, pInfo->width, pInfo->height, &pPriv->jpgData);
  607. _ilJPEGTablesIn (pCompData, &pPriv->jpgData);
  608. /* Data is now compressed to "raw" format. Convert to JIF if requested */
  609. if (!(pEncode->mustbezero & IL_JPEGM_RAW)) {
  610. ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat); /* update pipe info */
  611. return ilRawToJIF (pipe, pInfo, pDes, pFormat);
  612. }
  613. return TRUE;
  614. }