ilXycbcr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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: ilXycbcr.c /main/3 1995/10/23 15:41:23 rswiston $ */
  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 "ilXint.h"
  41. #include <math.h>
  42. #include "ilpipelem.h"
  43. #include "ilerrors.h"
  44. /* Number of bits of Y and Cb/Cr used to dither before a table lookup to
  45. convert to a dithered pixel. The number of levels dithered to (nLY/CbCr) is
  46. 1<<DYCBCR_NBITS_Y/CBCR. The YCbCr->RGB lookup table is "nLY * nLCbCr * nLCbCr"
  47. longs in size.
  48. */
  49. #define DYCBCR_NBITS_Y 6
  50. #define DYCBCR_NBITS_CBCR 4
  51. /* Tables generated by /il/util/gendithertables.c */
  52. static unsigned int _il2x2DitherKernel[4] = {42, 234, 170, 106};
  53. /* Private data for YCbCr to dithered pixel filter */
  54. typedef struct {
  55. unsigned long pixels[1 << (DYCBCR_NBITS_Y + DYCBCR_NBITS_CBCR + DYCBCR_NBITS_CBCR)];
  56. } ilDitherYCbCrPrivRec, *ilDitherYCbCrPrivPtr;
  57. /* ---------------------- ilFastYCbCrDitherExecute ------------------------ */
  58. /* Execute() function: dither from subsampled-by-2 YCbCr to 8 bit pixels.
  59. */
  60. static ilError ilFastYCbCrDitherExecute (
  61. ilExecuteData *pData,
  62. long dstLine,
  63. long *pNLines
  64. )
  65. {
  66. ilDitherYCbCrPrivPtr pPriv;
  67. ilImagePlaneInfo *pPlane;
  68. long nLinesDiv2, halfWidth;
  69. long CbRowBytes, CrRowBytes;
  70. ilPtr pYLine, pCbLine, pCrLine, pDstLine;
  71. unsigned long *pTable;
  72. long YRowBytes, dstRowBytes, nPixelsDiv2, CbCr, temp0, temp1;
  73. ilPtr pY, pCb, pCr, pDst;
  74. /* This filter handles a pipe image of YCbCr subsampled by 2 in Cb/Cr only.
  75. The # of lines of Cb/Cr is therefore 1/2 the # of lines of Y.
  76. Note: can only handle images with even width/height; checked elsewhere.
  77. */
  78. pPlane = pData->pSrcImage->plane;
  79. YRowBytes = pPlane->nBytesPerRow;
  80. pYLine = pPlane->pPixels;
  81. pPlane++;
  82. CbRowBytes = pPlane->nBytesPerRow;
  83. pCbLine = pPlane->pPixels;
  84. pPlane++;
  85. CrRowBytes = pPlane->nBytesPerRow;
  86. pCrLine = pPlane->pPixels;
  87. if (pData->srcLine) {
  88. pYLine += pData->srcLine * YRowBytes;
  89. pCbLine += (pData->srcLine >> 1) * CbRowBytes;
  90. pCrLine += (pData->srcLine >> 1) * CrRowBytes;
  91. }
  92. pPlane = pData->pDstImage->plane;
  93. dstRowBytes = pPlane->nBytesPerRow;
  94. pDstLine = pPlane->pPixels + dstLine * dstRowBytes;
  95. pPriv = (ilDitherYCbCrPrivPtr)pData->pPrivate;
  96. halfWidth = pData->pSrcImage->width >> 1; /* 1/2 # of lines, pixels per line */
  97. nLinesDiv2 = *pNLines >> 1;
  98. pTable = pPriv->pixels;
  99. /* Do 4 pixels at a time, using 4 Ys for each
  100. Cb,Cr pair: get Cb,Cr into upper bits of "CbCr", then add in each Y
  101. and use result to index into table that yields 4 dithered pixels:
  102. <left><right><below><below right>.
  103. */
  104. while (nLinesDiv2-- > 0) {
  105. pY = pYLine;
  106. pYLine += YRowBytes << 1; /* skip 2 lines; read 2 lines each loop */
  107. pCb = pCbLine;
  108. pCbLine += CbRowBytes;
  109. pCr = pCrLine;
  110. pCrLine += CrRowBytes;
  111. pDst = pDstLine;
  112. pDstLine += dstRowBytes << 1; /* skip 2 lines; write 2 lines each loop */
  113. nPixelsDiv2 = halfWidth;
  114. while (nPixelsDiv2-- > 0) {
  115. temp0 = *pCb++;
  116. CbCr = *pCr++;
  117. temp0 >>= (8 - DYCBCR_NBITS_CBCR);
  118. CbCr >>= (8 - DYCBCR_NBITS_CBCR);
  119. CbCr += temp0 << DYCBCR_NBITS_CBCR;
  120. CbCr <<= DYCBCR_NBITS_Y; /* CbCr now in upper bits w/ room for Y */
  121. temp0 = pY[YRowBytes]; /* do pixel and pixel below */
  122. temp1 = *pY++;
  123. temp0 = CbCr + (temp0 >> (8-DYCBCR_NBITS_Y));
  124. pDst[dstRowBytes] = pTable[temp0] >> 8;
  125. temp1 = CbCr + (temp1 >> (8-DYCBCR_NBITS_Y));
  126. *pDst++ = pTable[temp1] >> 24;
  127. temp0 = pY[YRowBytes]; /* do pixel and pixel below */
  128. temp1 = *pY++;
  129. temp0 = CbCr + (temp0 >> (8-DYCBCR_NBITS_Y));
  130. pDst[dstRowBytes] = pTable[temp0];
  131. temp1 = CbCr + (temp1 >> (8-DYCBCR_NBITS_Y));
  132. *pDst++ = pTable[temp1] >> 16;
  133. }
  134. }
  135. return IL_OK;
  136. }
  137. /* -------------------- ilFastYCbCrDitherDoubleExecute ---------------------- */
  138. /* Execute() function: dither and double the given # of src lines.
  139. */
  140. static ilError ilFastYCbCrDitherDoubleExecute (
  141. ilExecuteData *pData,
  142. long dstLine,
  143. long *pNLines
  144. )
  145. {
  146. ilDitherYCbCrPrivPtr pPriv;
  147. ilImagePlaneInfo *pPlane;
  148. long nLinesDiv2, halfWidth;
  149. long CbRowBytes, CrRowBytes, dstRowBytes;
  150. ilPtr pYLine, pCbLine, pCrLine;
  151. unsigned long *pTable;
  152. long YRowBytes, nPixelsDiv2, CbCr, temp0, temp1;
  153. long dstRowShorts, dstRowShortsTimes2, dstRowShortsTimes3;
  154. ilPtr pY, pCb, pCr;
  155. unsigned short *pDst;
  156. unsigned short *pDstLine;
  157. /* This filter handles a pipe image of YCbCr subsampled by 2 in Cb/Cr only.
  158. The # of lines of Cb/Cr is therefore 1/2 the # of lines of Y.
  159. Note: can only handle images with even width/height; checked elsewhere.
  160. */
  161. pPlane = pData->pSrcImage->plane;
  162. YRowBytes = pPlane->nBytesPerRow;
  163. pYLine = pPlane->pPixels;
  164. pPlane++;
  165. CbRowBytes = pPlane->nBytesPerRow;
  166. pCbLine = pPlane->pPixels;
  167. pPlane++;
  168. CrRowBytes = pPlane->nBytesPerRow;
  169. pCrLine = pPlane->pPixels;
  170. if (pData->srcLine) {
  171. pYLine += pData->srcLine * YRowBytes;
  172. pCbLine += (pData->srcLine >> 1) * CbRowBytes;
  173. pCrLine += (pData->srcLine >> 1) * CrRowBytes;
  174. }
  175. /* Access dst buffer as shorts */
  176. pPlane = pData->pDstImage->plane;
  177. dstRowBytes = pPlane->nBytesPerRow;
  178. pDstLine = (unsigned short *)(pPlane->pPixels + dstLine * dstRowBytes);
  179. dstRowShorts = dstRowBytes >> 1;
  180. dstRowShortsTimes2 = dstRowShorts * 2;
  181. dstRowShortsTimes3 = dstRowShorts * 3;
  182. pPriv = (ilDitherYCbCrPrivPtr)pData->pPrivate;
  183. halfWidth = pData->pSrcImage->width >> 1; /* 1/2 # of lines, pixels per line */
  184. nLinesDiv2 = *pNLines >> 1;
  185. *pNLines <<= 1; /* write 2x # of src lines */
  186. pTable = pPriv->pixels;
  187. /* Do 4 src pixels at a time, using 4 Ys for each Cb,Cr pair: get Cb,Cr into
  188. upper bits of "CbCr", then add in each Y and use result to index into table
  189. that yields 4 dithered pixels: <left><right><below><below right>.
  190. To double, output those 4 pixels as shown above; 1 src pixel becomes 4 dst.
  191. */
  192. while (nLinesDiv2-- > 0) {
  193. pY = pYLine;
  194. pYLine += YRowBytes << 1; /* skip 2 lines; read 2 lines each loop */
  195. pCb = pCbLine;
  196. pCbLine += CbRowBytes;
  197. pCr = pCrLine;
  198. pCrLine += CrRowBytes;
  199. pDst = pDstLine;
  200. pDstLine += dstRowShorts << 2; /* skip 4 lines; write 4 lines each loop */
  201. nPixelsDiv2 = halfWidth;
  202. while (nPixelsDiv2-- > 0) {
  203. temp0 = *pCb++;
  204. CbCr = *pCr++;
  205. temp0 >>= (8 - DYCBCR_NBITS_CBCR);
  206. CbCr >>= (8 - DYCBCR_NBITS_CBCR);
  207. CbCr += temp0 << DYCBCR_NBITS_CBCR;
  208. CbCr <<= DYCBCR_NBITS_Y; /* CbCr now in upper bits w/ room for Y */
  209. temp0 = pY[YRowBytes]; /* do pixel and pixel below */
  210. temp1 = *pY++;
  211. temp0 = CbCr + (temp0 >> (8-DYCBCR_NBITS_Y));
  212. temp0 = pTable[temp0];
  213. pDst[dstRowShortsTimes3] = (unsigned short)temp0;
  214. pDst[dstRowShortsTimes2] = (unsigned short)(temp0 >> 16);
  215. temp1 = CbCr + (temp1 >> (8-DYCBCR_NBITS_Y));
  216. temp1 = pTable[temp1];
  217. pDst[dstRowShorts] = (unsigned short)temp1;
  218. *pDst++ = (unsigned short)(temp1 >> 16);
  219. temp0 = pY[YRowBytes]; /* do pixel and pixel below */
  220. temp1 = *pY++;
  221. temp0 = CbCr + (temp0 >> (8-DYCBCR_NBITS_Y));
  222. temp0 = pTable[temp0];
  223. pDst[dstRowShortsTimes3] = (unsigned short)temp0;
  224. pDst[dstRowShortsTimes2] = (unsigned short)(temp0 >> 16);
  225. temp1 = CbCr + (temp1 >> (8-DYCBCR_NBITS_Y));
  226. temp1 = pTable[temp1];
  227. pDst[dstRowShorts] = (unsigned short)temp1;
  228. *pDst++ = (unsigned short)(temp1 >> 16);
  229. }
  230. }
  231. return IL_OK;
  232. }
  233. /* ---------------------------- ilSetupYCbCrDitherTables ----------------------- */
  234. /* Setup *pTable as necessary for the YCbCr to RGB (dither) conversion.
  235. */
  236. static void ilSetupYCbCrDitherTables (
  237. ilYCbCrInfo *pYCbCr,
  238. int nBitsR,
  239. int nBitsG,
  240. int nBitsB,
  241. ilPtr pMapPixels,
  242. unsigned long *pTable
  243. )
  244. {
  245. int nTableEntries, nLevelsY, nLevelsCbCr;
  246. int Y, Cb, Cr, refY, refCb, refCr;
  247. int R, G, B, pixel, i, temp, kernel;
  248. double Lr, Lg, Lb;
  249. double ditherR, ditherG, ditherB, ditherY, ditherCbCr;
  250. #define CVT_TO_RGB { \
  251. int tY = Y - pYCbCr->sample[0].refBlack;\
  252. int tCb = Cb - pYCbCr->sample[1].refBlack;\
  253. int tCr = Cr - pYCbCr->sample[2].refBlack;\
  254. R = tCr * (2 - 2 * Lr) + tY;\
  255. B = tCb * (2 - 2 * Lb) + tY;\
  256. G = (tY - Lb * B - Lr * R) / Lg;\
  257. if (R < 0) R = 0; else if (R > 255) R = 255;\
  258. if (G < 0) G = 0; else if (G > 255) G = 255;\
  259. if (B < 0) B = 0; else if (B > 255) B = 255;\
  260. }
  261. #define YCBCR_DEBUG_TABLE 1
  262. #ifdef YCBCR_DEBUG_TABLE
  263. /* Set pMapPixels to identity, for debugging */
  264. ilByte debugMapPixels[256];
  265. int tmp;
  266. int doDebug = FALSE;
  267. if (doDebug) {
  268. for (tmp = 0; tmp < 256; tmp++)
  269. debugMapPixels[tmp] = tmp;
  270. pMapPixels = debugMapPixels;
  271. }
  272. #endif
  273. /* Build the YCbCr to dither-RGB lookup table. The table is indexed by
  274. a YCbCr value <Cb><Cr><Y>, where <Y> is "DYCBCR_NBITS_Y" bits
  275. in size and <Cb><Cr> are each "DYCBCR_NBITS_CBCR" in size. Indexed that way
  276. the table yields either four dithered pixels or a long 24 X pixel.
  277. Each table entry is calculated by converting the YCbCr value to
  278. its RGB equivalent and either dithering to form 4 pixels or a single
  279. long X pixel.
  280. */
  281. nLevelsY = 1 << DYCBCR_NBITS_Y;
  282. nLevelsCbCr = 1 << DYCBCR_NBITS_CBCR;
  283. Lr = ((double)pYCbCr->lumaRed / (double)10000);
  284. Lg = ((double)pYCbCr->lumaGreen / (double)10000);
  285. Lb = ((double)pYCbCr->lumaBlue / (double)10000);
  286. ditherR = ((1 << nBitsR) - 1) * (double)256 / (double)255;
  287. ditherG = ((1 << nBitsG) - 1) * (double)256 / (double)255;
  288. ditherB = ((1 << nBitsB) - 1) * (double)256 / (double)255;
  289. for (refCb = 0; refCb < nLevelsCbCr; refCb++) {
  290. Cb = (255 * refCb) / (nLevelsCbCr - 1);
  291. for (refCr = 0; refCr < nLevelsCbCr; refCr++) {
  292. Cr = (255 * refCr) / (nLevelsCbCr - 1);
  293. for (refY = 0; refY < nLevelsY; refY++) {
  294. Y = (255 * refY) / (nLevelsY - 1);
  295. /* Store 4 dithered pixels, the result of dithering RGB with
  296. a 2x2 kernel. See /ilc/ildither.c for equivalent code.
  297. */
  298. #define DITHER
  299. #ifdef COLORSLAM
  300. CVT_TO_RGB
  301. pixel = R >> (8 - nBitsR);
  302. pixel <<= nBitsG;
  303. pixel |= G >> (8 - nBitsG);
  304. pixel <<= nBitsB;
  305. pixel |= B >> (8 - nBitsB);
  306. pixel = pMapPixels[pixel];
  307. *pTable++ = (pixel << 24) | (pixel << 16) | (pixel << 8) | pixel;
  308. #else
  309. #ifdef DIFFUSION
  310. {
  311. int temp1, temp2;
  312. int halfR = (1 << (7 - nBitsR)) - 1;
  313. int halfG = (1 << (7 - nBitsG)) - 1;
  314. int halfB = (1 << (7 - nBitsB)) - 1;
  315. int maskR = ~((1 << (8 - nBitsR)) - 1);
  316. int maskG = ~((1 << (8 - nBitsG)) - 1);
  317. int maskB = ~((1 << (8 - nBitsB)) - 1);
  318. CVT_TO_RGB
  319. for (i = 0, pixel = 0; i < 4; i++) {
  320. temp1 = R + halfR;
  321. if (temp1 > 255) temp1 = 255; else if (temp1 < 0) temp1 = 0;
  322. R += R - (temp1 & maskR);
  323. temp = temp1 >> (8 - nBitsR);
  324. temp1 = G + halfG;
  325. if (temp1 > 255) temp1 = 255; else if (temp1 < 0) temp1 = 0;
  326. G += G - (temp1 & maskG);
  327. temp <<= nBitsG;
  328. temp |= temp1 >> (8 - nBitsG);
  329. temp1 = B + halfB;
  330. if (temp1 > 255) temp1 = 255; else if (temp1 < 0) temp1 = 0;
  331. B += B - (temp1 & maskB);
  332. temp <<= nBitsB;
  333. temp |= temp1 >> (8 - nBitsB);
  334. pixel <<= 8;
  335. pixel |= pMapPixels[temp];
  336. }
  337. *pTable++ = pixel;
  338. }
  339. #else
  340. #ifdef DITHER
  341. CVT_TO_RGB
  342. R = (double)R * ditherR;
  343. G = (double)G * ditherG;
  344. B = (double)B * ditherB;
  345. for (i = 0, pixel = 0; i < 4; i++) {
  346. kernel = _il2x2DitherKernel[i];
  347. temp = (R + kernel) >> 8;
  348. temp <<= nBitsG;
  349. temp |= (G + kernel) >> 8;
  350. temp <<= nBitsB;
  351. temp |= (B + kernel) >> 8;
  352. pixel <<= 8;
  353. pixel |= pMapPixels[temp];
  354. }
  355. *pTable++ = pixel;
  356. #endif
  357. #endif
  358. #endif
  359. }
  360. }
  361. }
  362. }
  363. /* ------------------------ _ilFastYCbCrDither ---------------------------- */
  364. /* Called by ilConvertForXWrite() to do fast dithered display of YCbCr.
  365. The pipe image must be planar, subsampled by 2 in Cb/Cr, 1 in Y.
  366. "pMapPixels" points to 256 bytes from the XWC map image, which are folded
  367. into the lookup table used for this function.
  368. */
  369. IL_PRIVATE ilBool _ilFastYCbCrDither (
  370. ilPipe pipe,
  371. ilImageDes *pDes,
  372. ilPipeInfo *pInfo,
  373. int nBitsRed,
  374. int nBitsGreen,
  375. int nBitsBlue,
  376. ilBool doDouble,
  377. ilPtr pMapPixels
  378. )
  379. {
  380. ilImageDes des;
  381. ilDitherYCbCrPrivPtr pPriv;
  382. ilDstElementData dstData;
  383. ilSrcElementData srcData;
  384. /* Add a filter to convert subsampled YCbCr to a dithered palette image.
  385. Force a single strip; image is at least 2 by 2
  386. */
  387. srcData.consumerImage = (ilObject)NULL;
  388. srcData.stripHeight = pInfo->height;
  389. srcData.constantStrip = TRUE;
  390. srcData.minBufferHeight = 0;
  391. dstData.producerObject = (ilObject)NULL;
  392. dstData.pDes = IL_DES_GRAY; /* arbitrary; not really used */
  393. dstData.pFormat = IL_FORMAT_BYTE;
  394. dstData.width = pInfo->width;
  395. dstData.height = pInfo->height;
  396. dstData.stripHeight = srcData.stripHeight;
  397. if (doDouble) {
  398. dstData.width *= 2;
  399. dstData.height *= 2;
  400. dstData.stripHeight *= 2;
  401. }
  402. dstData.constantStrip = pInfo->constantStrip;
  403. dstData.pPalette = (unsigned short *)NULL;
  404. pPriv = (ilDitherYCbCrPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  405. sizeof(ilDitherYCbCrPrivRec), 0, &srcData, &dstData, IL_NPF, IL_NPF, IL_NPF,
  406. (doDouble) ? ilFastYCbCrDitherDoubleExecute : ilFastYCbCrDitherExecute, 0);
  407. if (!pPriv)
  408. return FALSE;
  409. /* Init the table in private */
  410. ilSetupYCbCrDitherTables (&pDes->typeInfo.YCbCr, nBitsRed, nBitsGreen, nBitsBlue,
  411. pMapPixels, pPriv->pixels);
  412. return TRUE;
  413. }