ilycbcr.c 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358
  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: ilycbcr.c /main/5 1996/06/19 12:20:22 ageorge $ */
  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. /* /ilc/ilycbcr.c : Code for handling IL_YCBCR images, including
  40. conversions to/from RGB, and subsampling - upsampling is in /ilc/ilupsample.c
  41. */
  42. #include <stdlib.h>
  43. #include "ilint.h"
  44. #include "ilpipelem.h"
  45. #include "ilconvert.h"
  46. #include "ilerrors.h"
  47. /* ========================== Sub/Upsample Code ================================== */
  48. #define NSUBSAMPLES 3 /* hardwired to 3 samples: Y, Cb, Cr */
  49. /* Sub/Upsubsample factors as shifts (1=0, 2=1, 4=2) - others not supported. */
  50. typedef struct {
  51. unsigned int horiz, vert;
  52. } ilSubsampleShiftRec, *ilSubsampleShiftPtr;
  53. /* Private for sub/upsampling filters. */
  54. typedef struct {
  55. int nSamples; /* # of samples (components) to process */
  56. ilSubsampleShiftRec shift[NSUBSAMPLES]; /* upsample mul as shift value */
  57. } ilSubsamplePrivRec, *ilSubsamplePrivPtr;
  58. /* ========================== Subsample Code =================================== */
  59. /* -------------------------- ilExecuteSubsample ------------------------------- */
  60. /* Execute(): subsample as necessary "pPriv->nSamples" planes of the source image.
  61. The source image must be planar, byte/pixel.
  62. */
  63. static ilError ilExecuteSubsample (
  64. ilExecuteData *pData,
  65. long dstLine,
  66. long *pNLines /* ignored on input */
  67. )
  68. {
  69. ilSubsamplePrivPtr pPriv;
  70. ilImagePlaneInfo *pSrcPlane, *pDstPlane;
  71. int nSamples;
  72. ilPtr pSrcLine, pDstLine;
  73. long height, width;
  74. long srcRowInc, dstRowBytes;
  75. long nDstLinesM1, nDstPixelsM1Init;
  76. ilSubsampleShiftPtr pShift;
  77. long nDstPixelsM1, srcRowBytes, i;
  78. ilPtr pSrc, pDst;
  79. unsigned int pixel;
  80. /* Get width and height of _upsampled_ image; exit if zero. */
  81. pPriv = (ilSubsamplePrivPtr)pData->pPrivate;
  82. height = *pNLines;
  83. if (height <= 0)
  84. return IL_OK;
  85. width = pData->pSrcImage->width;
  86. if (width <= 0)
  87. return IL_OK;
  88. /* Loop on samples (components), upsample/translate each plane separately.
  89. Note that "srcLine" is shifted - indexing into plane based on vert subsample.
  90. */
  91. for (pSrcPlane = pData->pSrcImage->plane, pDstPlane = pData->pDstImage->plane,
  92. pShift = pPriv->shift, nSamples = pPriv->nSamples;
  93. nSamples-- > 0;
  94. pSrcPlane++, pDstPlane++, pShift++) {
  95. /* Get # dst lines/pixels across - 1; skip plane if none */
  96. nDstLinesM1 = height >> pShift->vert;
  97. if (nDstLinesM1 <= 0)
  98. continue;
  99. nDstLinesM1--;
  100. nDstPixelsM1Init = width >> pShift->horiz;
  101. if (nDstPixelsM1Init <= 0)
  102. continue;
  103. nDstPixelsM1Init--;
  104. /* Point to src/dst; note dstLine scaled down by vert subsample shift.
  105. Set srcRowInc to srcRowBytes scaled up by vertical shift.
  106. */
  107. srcRowBytes = pSrcPlane->nBytesPerRow;
  108. pSrcLine = pSrcPlane->pPixels + pData->srcLine * srcRowBytes;
  109. srcRowInc = srcRowBytes << pShift->vert;
  110. dstRowBytes = pDstPlane->nBytesPerRow;
  111. pDstLine = pDstPlane->pPixels + (dstLine >> pShift->vert) * dstRowBytes;
  112. switch (pShift->horiz) { /* NOTE: vert shift must be the same! */
  113. /* 0 = no subsampling; just copy plane info */
  114. case 0:
  115. pSrc = pSrcLine;
  116. pDst = pDstLine;
  117. do {
  118. bcopy ((char *)pSrc, (char *)pDst, width);
  119. pSrc += srcRowBytes;
  120. pDst += dstRowBytes;
  121. } while (--nDstLinesM1 >= 0);
  122. break;
  123. /* 1 = 1/4 of pixels (half in each dimension). Take the average of 4
  124. pixels: (x,y), (x+1,y), (x,y+1), (x+1,y+1), for each even x,y.
  125. */
  126. case 1:
  127. do {
  128. pSrc = pSrcLine;
  129. pSrcLine += srcRowInc;
  130. pDst = pDstLine;
  131. pDstLine += dstRowBytes;
  132. nDstPixelsM1 = nDstPixelsM1Init;
  133. do {
  134. pixel = *pSrc;
  135. pixel += *(pSrc + 1);
  136. pixel += *(pSrc + srcRowBytes);
  137. pixel += *(pSrc + srcRowBytes + 1);
  138. pSrc += 2; /* two pixels to the right */
  139. *pDst++ = pixel >> 2; /* store 1/4 sum of 4 pixels */
  140. } while (--nDstPixelsM1 >= 0);
  141. } while (--nDstLinesM1 >= 0);
  142. break;
  143. /* 2 = 1/16 of pixels (1/4 in each dimension). Take the average of 16 pixels,
  144. a block below and to the right of (x,y), x,y = multiple of 4.
  145. */
  146. case 2:
  147. do {
  148. pSrc = pSrcLine;
  149. pSrcLine += srcRowInc;
  150. pDst = pDstLine;
  151. pDstLine += dstRowBytes;
  152. nDstPixelsM1 = nDstPixelsM1Init;
  153. do {
  154. pixel = 0;
  155. i = 3;
  156. do {
  157. pixel += *pSrc;
  158. pixel += *(pSrc + 1);
  159. pixel += *(pSrc + 2);
  160. pixel += *(pSrc + 3);
  161. pSrc += srcRowBytes;
  162. } while (--i >= 0);
  163. *pDst++ = pixel >> 4; /* store 1/16 sum of 16 pixels */
  164. pSrc += -srcRowInc + 4; /* back to top line, 4 to right */
  165. } while (--nDstPixelsM1 >= 0);
  166. } while (--nDstLinesM1 >= 0);
  167. break;
  168. } /* END switch subsample shift */
  169. } /* END each plane */
  170. return IL_OK;
  171. }
  172. /* ---------------------------- ilSubsampleYCbCr ----------------------------- */
  173. /* Subsample the pipe image which must be a fully upsampled YCbCr image.
  174. pFormat points to the source format; on return, *pFormat is updated
  175. to the dst format. *pDes to the _destination_ des, i.e. has subsample values.
  176. */
  177. IL_PRIVATE ilBool _ilSubsampleYCbCr (
  178. ilPipe pipe,
  179. ilPipeInfo *pInfo,
  180. ilImageDes *pDes,
  181. ilImageFormat *pFormat
  182. )
  183. {
  184. ilSubsamplePrivPtr pSubPriv;
  185. ilSubsamplePrivRec priv;
  186. ilSubsampleShiftRec *pShift;
  187. ilYCbCrSampleInfo *pSample;
  188. int sample;
  189. ilDstElementData dstData;
  190. ilSrcElementData srcData;
  191. /* Only 8 bit planar YCbCr current handled; cvt if not that format. */
  192. if ((pFormat->sampleOrder != IL_SAMPLE_PLANES)
  193. || (pFormat->nBitsPerSample[0] != 8)
  194. || (pFormat->nBitsPerSample[1] != 8)
  195. || (pFormat->nBitsPerSample[2] != 8)) {
  196. *pFormat = *IL_FORMAT_3BYTE_PLANE;
  197. if (!ilConvert (pipe, (ilImageDes *)NULL, pFormat, 0, NULL))
  198. return FALSE;
  199. }
  200. /* Determine subsample values: only 1 (no subsampling), 2 (1/4 = 1/2 in each
  201. dimension) or 4 (1/16) allowed; same both vertical/horizontal.
  202. */
  203. priv.nSamples = NSUBSAMPLES;
  204. pSample = pDes->typeInfo.YCbCr.sample;
  205. pShift = priv.shift;
  206. for (sample = 0; sample < NSUBSAMPLES; sample++, pShift++, pSample++) {
  207. if (pSample->subsampleHoriz != pSample->subsampleVert)
  208. return ilDeclarePipeInvalid (pipe, IL_ERROR_SUBSAMPLE);
  209. switch ((unsigned int)pSample->subsampleHoriz) {
  210. case 1: pShift->horiz = 0; break;
  211. case 2: pShift->horiz = 1; break;
  212. case 4: pShift->horiz = 2; break;
  213. default: return ilDeclarePipeInvalid (pipe, IL_ERROR_SUBSAMPLE);
  214. }
  215. pShift->vert = pShift->horiz; /* same subsampling both dimensions */
  216. }
  217. /* Init dstData, add subsample filter. */
  218. dstData.producerObject = (ilObject)NULL;
  219. dstData.pDes = pDes;
  220. dstData.pFormat = pFormat;
  221. dstData.width = pInfo->width;
  222. dstData.height = pInfo->height;
  223. dstData.stripHeight = 0;
  224. dstData.constantStrip = FALSE;
  225. dstData.pPalette = (unsigned short *)NULL;
  226. /* Demand constant strips, a multiple of maximum subsample (4). */
  227. srcData.consumerImage = (ilObject)NULL;
  228. srcData.stripHeight = 8; /* Arbitrary, but must be multiple of 4 */
  229. srcData.constantStrip = TRUE;
  230. srcData.minBufferHeight = 0;
  231. pSubPriv = (ilSubsamplePrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  232. sizeof (ilSubsamplePrivRec), 0, &srcData,
  233. &dstData, IL_NPF, IL_NPF, IL_NPF, ilExecuteSubsample, NULL, 0);
  234. if (!pSubPriv)
  235. return FALSE;
  236. *pSubPriv = priv; /* copy priv to priv ptr */
  237. return TRUE;
  238. }
  239. /* ======================= YCbCr to RGB Code =================================== */
  240. /* Lookup tables for YCbCr to RGB conversion. Each table is indexed by Y, Cb or Cr,
  241. and contains two values; one the upper short (1st) the other in the lower (2nd);
  242. the upper short values are used to compute green.
  243. Y G cvt: Y factor = (1 - Lb - Lr)/Lg scale for refBlack/White
  244. Cb G cvt: Cb factor = -Lb*(2 - 2*Lb)/Lg Cb scale * (2 - 2 * Lr)
  245. Cr G cvt: Cr factor = -Lr*(2 - 2*Lr)/Lg Cr scale * (2 - 2 * Lb)
  246. */
  247. typedef struct {
  248. long YTrans[256]; /* values indexed by Y, as above */
  249. long CbTrans[256]; /* values indexed by Cb, as above */
  250. long CrTrans[256]; /* values indexed by Cr, as above */
  251. } ilRGBTransRec, *ilRGBTransPtr;
  252. /* Private for RGB to YCbCr filter. */
  253. typedef struct {
  254. ilRGBTransPtr pTrans; /* ptr to all the translate tables */
  255. long y; /* for dither only: current Y */
  256. } ilYCbCrToRGBPrivRec, *ilYCbCrToRGBPrivPtr;
  257. /* Pointer to "std" translation table: works for "std" YCbCr values -
  258. those in IL_DES_YCBCR.
  259. */
  260. static ilRGBTransPtr _ilStdYCbCrTransPtr = (ilRGBTransPtr)NULL;
  261. /* --------------------------- ilDestroyTransTable --------------------- */
  262. /* Destroy function: used only if pPriv->pTrans points to locally malloc'd
  263. translate table, i.e. not using std values and table.
  264. */
  265. static ilError ilDestroyTransTable (
  266. ilYCbCrToRGBPrivPtr pPriv
  267. )
  268. {
  269. IL_FREE (pPriv->pTrans);
  270. return IL_OK;
  271. }
  272. /* --------------------- ilExecutePlanarYCbCrToRGB ----------------------------- */
  273. /* Execute(): convert _planar_ src YCbCr to _pixel_ dst RGB.
  274. NOTE: the YCbCr image must have been upsampled, i.e. thru ilExecuteUpsample().
  275. */
  276. static ilError ilExecutePlanarYCbCrToRGB (
  277. ilExecuteData *pData,
  278. long dstLine,
  279. long *pNLines
  280. )
  281. {
  282. ilPtr pYLine, pCbLine, pCrLine, pDstLine;
  283. ilRGBTransPtr pTrans;
  284. ilPtr pY, pCb, pCr, pDst;
  285. long YTrans, CbTrans, CrTrans, pixel, nPixelsM1;
  286. int Y;
  287. long nPixelsM1Init, nLinesM1;
  288. long YRowBytes, CbRowBytes, CrRowBytes, dstRowBytes;
  289. ilImagePlaneInfo *pPlane;
  290. /* Set nPixels/LinesM1 to # pixels / lines - 1; exit if either 0. */
  291. nPixelsM1Init = pData->pSrcImage->width;
  292. if (nPixelsM1Init <= 0)
  293. return 0;
  294. nPixelsM1Init--;
  295. nLinesM1 = *pNLines;
  296. if (nLinesM1 <= 0)
  297. return 0;
  298. nLinesM1--;
  299. /* Point pY/Cb/CrLine to 1st line in src planes; pDstLine to 1st line in dst.
  300. Get bytes/row for each of them.
  301. */
  302. pPlane = pData->pSrcImage->plane;
  303. YRowBytes = pPlane->nBytesPerRow;
  304. pYLine = pPlane->pPixels + pData->srcLine * YRowBytes;
  305. pPlane++;
  306. CbRowBytes = pPlane->nBytesPerRow;
  307. pCbLine = pPlane->pPixels + pData->srcLine * CbRowBytes;
  308. pPlane++;
  309. CrRowBytes = pPlane->nBytesPerRow;
  310. pCrLine = pPlane->pPixels + pData->srcLine * CrRowBytes;
  311. pPlane = pData->pDstImage->plane;
  312. dstRowBytes = pPlane->nBytesPerRow;
  313. pDstLine = pPlane->pPixels + dstLine * dstRowBytes;
  314. /* Convert planar YCbCr to pixel RGB. */
  315. pTrans = ((ilYCbCrToRGBPrivPtr)pData->pPrivate)->pTrans;
  316. do {
  317. pY = pYLine;
  318. pYLine += YRowBytes;
  319. pCb = pCbLine;
  320. pCbLine += CbRowBytes;
  321. pCr = pCrLine;
  322. pCrLine += CrRowBytes;
  323. pDst = pDstLine;
  324. pDstLine += dstRowBytes;
  325. nPixelsM1 = nPixelsM1Init;
  326. do {
  327. YTrans = pTrans->YTrans[*pY++];
  328. CrTrans = pTrans->CrTrans[*pCr++];
  329. Y = ((short)YTrans);
  330. CbTrans = pTrans->CbTrans[*pCb++];
  331. pixel = Y + ((short)CrTrans);
  332. if (pixel >> 8) goto plClipR;
  333. plRClipped: *pDst++ = pixel; /* store red */
  334. pixel = YTrans >> 16;
  335. pixel += CbTrans >> 16;
  336. pixel += CrTrans >> 16;
  337. if (pixel >> 8) goto plClipG;
  338. plGClipped: *pDst++ = pixel; /* store green */
  339. pixel = Y + ((short)CbTrans);
  340. if (pixel >> 8) goto plClipB;
  341. plBClipped: *pDst++ = pixel; /* store blue */
  342. } while (--nPixelsM1 >= 0);
  343. } while (--nLinesM1 >= 0);
  344. return IL_OK;
  345. /* goto point for when R, G or B out of range: clamp pixel and go back and continue.
  346. This is done to avoid taking a branch in the most common case: not out of range.
  347. */
  348. plClipR: if (pixel > 255) pixel = 255; else pixel = 0;
  349. goto plRClipped;
  350. plClipG: if (pixel > 255) pixel = 255; else pixel = 0;
  351. goto plGClipped;
  352. plClipB: if (pixel > 255) pixel = 255; else pixel = 0;
  353. goto plBClipped;
  354. }
  355. /* --------------------- ilExecutePixelYCbCrToRGB ----------------------------- */
  356. /* Execute(): convert _pixel_ src YCbCr to _pixel_ dst RGB.
  357. NOTE: the YCbCr image must have been upsampled, i.e. thru ilExecuteUpsample().
  358. */
  359. static ilError ilExecutePixelYCbCrToRGB (
  360. ilExecuteData *pData,
  361. long dstLine,
  362. long *pNLines
  363. )
  364. {
  365. ilPtr pSrcLine, pDstLine;
  366. ilRGBTransPtr pTrans;
  367. ilPtr pSrc, pDst;
  368. long YTrans, CbTrans, CrTrans, pixel, nPixelsM1;
  369. int Y;
  370. long nPixelsM1Init, nLinesM1;
  371. long srcRowBytes, dstRowBytes;
  372. ilImagePlaneInfo *pPlane;
  373. /* Set nPixels/LinesM1 to # pixels / lines - 1; exit if either 0. */
  374. nPixelsM1Init = pData->pSrcImage->width;
  375. if (nPixelsM1Init <= 0)
  376. return 0;
  377. nPixelsM1Init--;
  378. nLinesM1 = *pNLines;
  379. if (nLinesM1 <= 0)
  380. return 0;
  381. nLinesM1--;
  382. /* Point pY/Cb/CrLine to 1st line in src planes; pDstLine to 1st line in dst.
  383. Get bytes/row for each of them.
  384. */
  385. pPlane = pData->pSrcImage->plane;
  386. srcRowBytes = pPlane->nBytesPerRow;
  387. pSrcLine = pPlane->pPixels + pData->srcLine * srcRowBytes;
  388. pPlane = pData->pDstImage->plane;
  389. dstRowBytes = pPlane->nBytesPerRow;
  390. pDstLine = pPlane->pPixels + dstLine * dstRowBytes;
  391. /* Convert pixel YCbCr to pixel RGB. */
  392. pTrans = ((ilYCbCrToRGBPrivPtr)pData->pPrivate)->pTrans;
  393. do {
  394. pSrc = pSrcLine;
  395. pSrcLine += srcRowBytes;
  396. pDst = pDstLine;
  397. pDstLine += dstRowBytes;
  398. nPixelsM1 = nPixelsM1Init;
  399. do {
  400. YTrans = pTrans->YTrans[*pSrc++];
  401. CbTrans = pTrans->CbTrans[*pSrc++];
  402. Y = ((short)YTrans);
  403. CrTrans = pTrans->CrTrans[*pSrc++];
  404. pixel = Y + ((short)CrTrans);
  405. if (pixel >> 8) goto piClipR;
  406. piRClipped: *pDst++ = pixel; /* store red */
  407. pixel = YTrans >> 16;
  408. pixel += CbTrans >> 16;
  409. pixel += CrTrans >> 16;
  410. if (pixel >> 8) goto piClipG;
  411. piGClipped: *pDst++ = pixel; /* store green */
  412. pixel = Y + ((short)CbTrans);
  413. if (pixel >> 8) goto piClipB;
  414. piBClipped: *pDst++ = pixel; /* store blue */
  415. } while (--nPixelsM1 >= 0);
  416. } while (--nLinesM1 >= 0);
  417. return IL_OK;
  418. /* goto point for when R, G or B out of range: clamp pixel and go back and continue.
  419. This is done to avoid taking a branch in the most common case: not out of range.
  420. */
  421. piClipR: if (pixel > 255) pixel = 255; else pixel = 0;
  422. goto piRClipped;
  423. piClipG: if (pixel > 255) pixel = 255; else pixel = 0;
  424. goto piGClipped;
  425. piClipB: if (pixel > 255) pixel = 255; else pixel = 0;
  426. goto piBClipped;
  427. }
  428. /* ------------------------- ilGetYCbCrConvertTable -------------------------- */
  429. /* Returns a pointer to the YCbCr conversion table (ilRGBTransRec); either
  430. "_ilStdYCbCrTransPtr" or a ptr to a table that caller must destroy, or
  431. null if a malloc error occurs.
  432. */
  433. static ilRGBTransPtr ilGetYCbCrConvertTable (
  434. ilImageDes *pDes
  435. )
  436. {
  437. ilRGBTransPtr pTrans;
  438. const ilYCbCrInfo *pYCbCr, *pStdYCbCr;
  439. double Lr, Lg, Lb, scaledY;
  440. double factor, gFactor;
  441. int i, refBlack, upper, lower;
  442. ilBool isStd;
  443. struct {
  444. int refBlack;
  445. double scale;
  446. } sample [3];
  447. /* If luma and refBlack/White info same as std IL_DES_YCBCR, then reuse
  448. the table at _ilStdYCbCrTransPtr; create it here if does not exist yet.
  449. */
  450. pYCbCr = &pDes->typeInfo.YCbCr;
  451. pStdYCbCr = &IL_DES_YCBCR->typeInfo.YCbCr;
  452. if ((pYCbCr->sample[0].refBlack == pStdYCbCr->sample[0].refBlack)
  453. && (pYCbCr->sample[0].refWhite == pStdYCbCr->sample[0].refWhite)
  454. && (pYCbCr->sample[1].refBlack == pStdYCbCr->sample[1].refBlack)
  455. && (pYCbCr->sample[1].refWhite == pStdYCbCr->sample[1].refWhite)
  456. && (pYCbCr->sample[2].refBlack == pStdYCbCr->sample[2].refBlack)
  457. && (pYCbCr->sample[2].refWhite == pStdYCbCr->sample[2].refWhite)
  458. && (pYCbCr->lumaRed == pStdYCbCr->lumaRed)
  459. && (pYCbCr->lumaGreen == pStdYCbCr->lumaGreen)
  460. && (pYCbCr->lumaBlue == pStdYCbCr->lumaBlue)) {
  461. isStd = TRUE;
  462. pTrans = _ilStdYCbCrTransPtr; /* alloc below if not there yet */
  463. }
  464. else {
  465. isStd = FALSE;
  466. pTrans = (ilRGBTransPtr)NULL; /* allocate it below */
  467. }
  468. /* Build translate tables. First, from pg 3 of Appendix O of TIFF spec:
  469. R = Cr * (2 - 2 * Lr) + Y
  470. B = Cb * (2 - 2 * Lb) + Y
  471. G = (Y - Lb * B - Lr * R) / Lg
  472. Get green in terms of Cb and Cr:
  473. G = (Y - Lb*B - Lr*R) / Lg
  474. G = (Y - Lb*(Cb * (2 - 2*Lb) + Y) - Lr*(Cr * (2 - 2*Lr) + Y)) / Lg
  475. G = (Y - Lb*Cb*(2 - 2*Lb) - Lb*Y - Lr*Cr*(2 - 2*Lr) - Lr*Y) / Lg
  476. G = (Y - Lb*Y - Lr*Y - Cb*Lb*(2 - 2*Lb) - Cr*Lr*(2 - 2*Lr)) / Lg
  477. G = (Y * (1 - Lb - Lr) - Cb*Lb*(2 - 2*Lb) - Cr*Lr*(2 - 2*Lr)) / Lg
  478. G = Y * (1 - Lb - Lr)/Lg + Cb * -Lb*(2 - 2*Lb)/Lg + Cr * -Lr*(2 - 2*Lr)/Lg
  479. */
  480. if (!pTrans) { /* non-std or std table not build yet */
  481. pTrans = (ilRGBTransPtr)IL_MALLOC (sizeof (ilRGBTransRec));
  482. if (!pTrans)
  483. return pTrans;
  484. /* The Y, Cb and Cr components must be scaled up based on refBlack/White.
  485. Factor that scaling in everywhere Y/Cb/Cr are looked up.
  486. First get the scale and refBlack for each sample.
  487. */
  488. for (i = 0; i < 3; i++) {
  489. sample[i].refBlack = pYCbCr->sample[i].refBlack;
  490. sample[i].scale = ((i == 0) ? 255 : 127) /
  491. (pYCbCr->sample[i].refWhite - pYCbCr->sample[i].refBlack);
  492. }
  493. /* Calc the Cb/Cr lookup tables, factoring in their scale factors. */
  494. Lr = ((double)pYCbCr->lumaRed / (double)10000);
  495. Lg = ((double)pYCbCr->lumaGreen / (double)10000);
  496. Lb = ((double)pYCbCr->lumaBlue / (double)10000);
  497. /* Y translation: lower is scaled Y, upper is value added to get green */
  498. gFactor = (1 - Lb - Lr) / Lg;
  499. for (i = 0; i < 256; i++) {
  500. scaledY = sample[0].scale * i - sample[0].refBlack;
  501. upper = scaledY * gFactor + 0.5;
  502. lower = scaledY;
  503. pTrans->YTrans[i] = (upper << 16) | (lower & 0xffff);
  504. }
  505. /* Cb: lower is added to Y to get blue, upper added to get green */
  506. factor = (2 - 2 * Lb) * sample[1].scale;
  507. gFactor = -Lb * (2 - 2 * Lb) / Lg;
  508. refBlack = sample[1].refBlack;
  509. for (i = 0; i < 256; i++) {
  510. upper = (i - refBlack) * gFactor + 0.5;
  511. lower = (i - refBlack) * factor + 0.5;
  512. pTrans->CbTrans[i] = (upper << 16) | (lower & 0xffff);
  513. }
  514. /* Cr: lower is added to Y to get red, upper added to get green */
  515. factor = (2 - 2 * Lr) * sample[2].scale;
  516. gFactor = -Lr * (2 - 2 * Lr) / Lg;
  517. refBlack = sample[2].refBlack;
  518. for (i = 0; i < 256; i++) {
  519. upper = (i - refBlack) * gFactor + 0.5;
  520. lower = (i - refBlack) * factor + 0.5;
  521. pTrans->CrTrans[i] = (upper << 16) | (lower & 0xffff);
  522. }
  523. /* If creating "std" conversion table for first time, set ptr to it */
  524. if (isStd)
  525. _ilStdYCbCrTransPtr = pTrans;
  526. } /* END build table */
  527. return pTrans;
  528. }
  529. /* ---------------------------- ilConvertYCbCrToRGB ----------------------------- */
  530. /* Convert from source type (pDes->type) == IL_YCBCR to RBB.
  531. pFormat points to the source format; on return, *pFormat is updated
  532. to the dst format, *pDes to the dst descriptor.
  533. */
  534. IL_PRIVATE ilBool _ilConvertYCbCrToRGB (
  535. ilPipe pipe,
  536. ilPipeInfo *pInfo,
  537. ilImageDes *pDes,
  538. ilImageFormat *pFormat
  539. )
  540. {
  541. ilDstElementData dstData;
  542. ilError (*executeFunction)(), (*destroyFunction)();
  543. ilYCbCrToRGBPrivPtr pPriv;
  544. ilRGBTransPtr pTrans;
  545. if ((pFormat->nBitsPerSample[0] != 8)
  546. || (pFormat->nBitsPerSample[1] != 8)
  547. || (pFormat->nBitsPerSample[2] != 8))
  548. return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
  549. /* Handle planar/pixel src format with different executeFunction, but in
  550. either case output RGB in 3 byte pixel format.
  551. */
  552. if (pFormat->sampleOrder == IL_SAMPLE_PIXELS)
  553. executeFunction = ilExecutePixelYCbCrToRGB;
  554. else {
  555. executeFunction = ilExecutePlanarYCbCrToRGB;
  556. *pFormat = *IL_FORMAT_3BYTE_PIXEL;
  557. }
  558. /* Get translation table or error; destroy it if not the "std" one */
  559. pTrans = ilGetYCbCrConvertTable (pDes);
  560. if (!pTrans)
  561. return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  562. destroyFunction = (pTrans == _ilStdYCbCrTransPtr) ? IL_NPF : ilDestroyTransTable;
  563. /* Add element to the pipe, init private */
  564. dstData.producerObject = (ilObject)NULL;
  565. *pDes = *IL_DES_RGB;
  566. dstData.pDes = pDes;
  567. dstData.pFormat = pFormat;
  568. dstData.width = pInfo->width;
  569. dstData.height = pInfo->height;
  570. dstData.stripHeight = 0;
  571. dstData.constantStrip = FALSE;
  572. dstData.pPalette = (unsigned short *)NULL;
  573. pPriv = (ilYCbCrToRGBPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  574. sizeof(ilYCbCrToRGBPrivRec), 0, (ilSrcElementData *)NULL, &dstData,
  575. IL_NPF, IL_NPF, destroyFunction, executeFunction, NULL, 0);
  576. if (!pPriv) {
  577. if (destroyFunction) /* local copy of pTrans; free it */
  578. IL_FREE (pTrans);
  579. return FALSE;
  580. }
  581. pPriv->pTrans = pTrans;
  582. return TRUE;
  583. }
  584. /* ======================= Dither YCbCr Code =================================== */
  585. /* Defines for # bits of RGB to dither to. NOTE! however that these are not
  586. arbitrary; # bits of red must = # bits of green, because the pre-dither-mul'd
  587. value of "Y" is the same for both.
  588. */
  589. #define YCBCR2_NR_BITS 2 /* # of bits of R/G/B to dither to */
  590. #define YCBCR2_NG_BITS 3
  591. #define YCBCR2_NB_BITS 2
  592. #define YCBCR2_MAX_R ((1 << YCBCR2_NR_BITS) - 1) /* max value for R/G/B */
  593. #define YCBCR2_MAX_G ((1 << YCBCR2_NG_BITS) - 1)
  594. #define YCBCR2_MAX_B ((1 << YCBCR2_NB_BITS) - 1)
  595. /* Private for RGB to dithered pixel filter. */
  596. typedef struct {
  597. ilRGBTransRec trans; /* YCbCr->dither-mul'd values tables */
  598. ilPtr pTranslate; /* ptr to ilMap() lookup table pixels */
  599. unsigned short *pPalette; /* ptr to palette to destroy or null */
  600. long y; /* Init(): current Y within dst image */
  601. ilByte translate [256]; /* identity image if no mapImage given */
  602. } ilYCbCr2DitherPrivRec, *ilYCbCr2DitherPrivPtr;
  603. /* Init() function: init the counter of "y" within private */
  604. static ilError ilYCbCr2DitherInit (
  605. ilYCbCr2DitherPrivPtr pPriv,
  606. ilImageInfo *pSrcImage,
  607. ilImageInfo *pDstImage
  608. )
  609. {
  610. pPriv->y = 0;
  611. return IL_OK;
  612. }
  613. /* Destroy function: destroy pTrans if not std and pPalette if not null */
  614. static ilError ilYCbCr2DitherDestroy (
  615. ilYCbCr2DitherPrivPtr pPriv
  616. )
  617. {
  618. if (pPriv->pPalette)
  619. IL_FREE (pPriv->pPalette);
  620. return IL_OK;
  621. }
  622. /* ---------------------- ilYCbCr2DitherExecute ------------------------ */
  623. /* Execute() function: dither from subsampled-by-2 YCbCr to 8 bit pixels.
  624. Dithering is done to RGB levels of 484 (232 in bits).
  625. */
  626. static ilError ilYCbCr2DitherExecute (
  627. ilExecuteData *pData,
  628. long dstLine,
  629. long *pNLines
  630. )
  631. {
  632. ilYCbCr2DitherPrivPtr pPriv;
  633. ilImagePlaneInfo *pPlane;
  634. long nLinesDiv2, halfWidthM1, y;
  635. long CbRowBytes, CrRowBytes;
  636. ilPtr pYLine, pCbLine, pCrLine, pDstLine;
  637. int *pKernelRowEnd;
  638. long nPixelsDiv2M1;
  639. ilPtr pCb, pCr;
  640. long YRowBytes, dstRowBytes;
  641. long Y, Cb, Cr, YTrans, CbTrans, CrTrans, comp, pixel;
  642. ilPtr pY, pDst;
  643. ilRGBTransPtr pTrans;
  644. ilPtr pTranslate;
  645. int *pKernel, kernel;
  646. #define YCBCR2_KERNEL_SIZE 8 /* size of dither kernel used */
  647. /* This filter handles a pipe image of YCbCr subsampled by 2 in Cb/Cr only.
  648. The # of lines of Cb/Cr is therefore 1/2 the # of lines of Y.
  649. Note: can only handle images with even width/height; checked elsewhere.
  650. */
  651. pPlane = pData->pSrcImage->plane;
  652. YRowBytes = pPlane->nBytesPerRow;
  653. pYLine = pPlane->pPixels;
  654. pPlane++;
  655. CbRowBytes = pPlane->nBytesPerRow;
  656. pCbLine = pPlane->pPixels;
  657. pPlane++;
  658. CrRowBytes = pPlane->nBytesPerRow;
  659. pCrLine = pPlane->pPixels;
  660. if (pData->srcLine) {
  661. pYLine += pData->srcLine * YRowBytes;
  662. pCbLine += (pData->srcLine >> 1) * CbRowBytes;
  663. pCrLine += (pData->srcLine >> 1) * CrRowBytes;
  664. }
  665. pPlane = pData->pDstImage->plane;
  666. dstRowBytes = pPlane->nBytesPerRow;
  667. pDstLine = pPlane->pPixels + dstLine * dstRowBytes;
  668. pPriv = (ilYCbCr2DitherPrivPtr)pData->pPrivate;
  669. halfWidthM1 = pData->pSrcImage->width >> 1; /* 1/2 # of pixels - 1 */
  670. nLinesDiv2 = *pNLines >> 1;
  671. if ((halfWidthM1 <= 0) || (nLinesDiv2 <= 0))
  672. return IL_OK;
  673. halfWidthM1 -= 1;
  674. y = pPriv->y;
  675. pPriv->y += *pNLines;
  676. pTrans = &pPriv->trans;
  677. pTranslate = pPriv->pTranslate;
  678. /* Do 4 pixels at a time, using 4 Ys (below L, L, below R, R) for each Cb,Cr pair.
  679. For each Y, do one pixel: get "comp" (RGB) as done in other YCbCr->RGB
  680. filters, except that all values are pre-multiplied by what the dither tables
  681. would yield if the lookup to _ilMul4/8[] was done. "pixel" is then used as
  682. an index into pTranslate table to get pixel to write to dst.
  683. See comments in ilGetYCbCrDitherTable() for details.
  684. */
  685. while (nLinesDiv2-- > 0) {
  686. pY = pYLine;
  687. pYLine += YRowBytes << 1; /* skip 2 lines; read 2 lines each loop */
  688. pCb = pCbLine;
  689. pCbLine += CbRowBytes;
  690. pCr = pCrLine;
  691. pCrLine += CrRowBytes;
  692. pDst = pDstLine;
  693. pDstLine += dstRowBytes << 1; /* skip 2 lines; write 2 lines each loop */
  694. nPixelsDiv2M1 = halfWidthM1;
  695. /* Point to even row within kernel based on "y"; point to end of row */
  696. pKernel = (int *)&_ilDitherKernel[(y & 6) * YCBCR2_KERNEL_SIZE];
  697. y += 2;
  698. pKernelRowEnd = pKernel + 8;
  699. /* Dither 4 pixels, using one set of Cb,Cr and 4 Y's. */
  700. do {
  701. CrTrans = pTrans->CrTrans[*pCr++];
  702. CbTrans = pTrans->CbTrans[*pCb++];
  703. Cr = ((short)CrTrans);
  704. CrTrans >>= 16;
  705. Cb = ((short)CbTrans);
  706. CbTrans >>= 16;
  707. CbTrans += CrTrans; /* add Cb, Cr contributions to green */
  708. /* Do pixel below */
  709. YTrans = pTrans->YTrans[pY[YRowBytes]];
  710. kernel = pKernel[YCBCR2_KERNEL_SIZE];
  711. Y = ((short)YTrans);
  712. Y += kernel; /* pre-add kernel to Y */
  713. pixel = (Y + Cr) >> 8;
  714. if (pixel >> YCBCR2_NR_BITS) goto d0ClipR;
  715. d0RClipped: comp = ((YTrans >> 16) + CbTrans + kernel) >> 8;
  716. if (comp >> YCBCR2_NG_BITS) goto d0ClipG;
  717. d0GClipped: pixel = (pixel << YCBCR2_NG_BITS) + comp;
  718. comp = (Y + Cb) >> 8;
  719. if (comp >> YCBCR2_NB_BITS) goto d0ClipB;
  720. d0BClipped: pixel = (pixel << YCBCR2_NB_BITS) + comp;
  721. pDst[dstRowBytes] = pTranslate[pixel];
  722. /* Do pixel, move pKernel, pY, pDst one to the right */
  723. YTrans = pTrans->YTrans[*pY++];
  724. kernel = *pKernel++;
  725. Y = ((short)YTrans);
  726. Y += kernel;
  727. pixel = (Y + Cr) >> 8;
  728. if (pixel >> YCBCR2_NR_BITS) goto d1ClipR;
  729. d1RClipped: comp = ((YTrans >> 16) + CbTrans + kernel) >> 8;
  730. if (comp >> YCBCR2_NG_BITS) goto d1ClipG;
  731. d1GClipped: pixel = (pixel << YCBCR2_NG_BITS) + comp;
  732. comp = (Y + Cb) >> 8;
  733. if (comp >> YCBCR2_NB_BITS) goto d1ClipB;
  734. d1BClipped: pixel = (pixel << YCBCR2_NB_BITS) + comp;
  735. *pDst++ = pTranslate[pixel];
  736. /* Same as above two steps for one pixel to the right */
  737. YTrans = pTrans->YTrans[pY[YRowBytes]];
  738. kernel = pKernel[YCBCR2_KERNEL_SIZE];
  739. Y = ((short)YTrans);
  740. Y += kernel; /* pre-add kernel to Y */
  741. pixel = (Y + Cr) >> 8;
  742. if (pixel >> YCBCR2_NR_BITS) goto d2ClipR;
  743. d2RClipped: comp = ((YTrans >> 16) + CbTrans + kernel) >> 8;
  744. if (comp >> YCBCR2_NG_BITS) goto d2ClipG;
  745. d2GClipped: pixel = (pixel << YCBCR2_NG_BITS) + comp;
  746. comp = (Y + Cb) >> 8;
  747. if (comp >> YCBCR2_NB_BITS) goto d2ClipB;
  748. d2BClipped: pixel = (pixel << YCBCR2_NB_BITS) + comp;
  749. pDst[dstRowBytes] = pTranslate[pixel];
  750. /* Do pixel, move pKernel, pY, pDst one to the right */
  751. YTrans = pTrans->YTrans[*pY++];
  752. kernel = *pKernel++;
  753. Y = ((short)YTrans);
  754. Y += kernel;
  755. pixel = (Y + Cr) >> 8;
  756. if (pixel >> YCBCR2_NR_BITS) goto d3ClipR;
  757. d3RClipped: comp = ((YTrans >> 16) + CbTrans + kernel) >> 8;
  758. if (comp >> YCBCR2_NG_BITS) goto d3ClipG;
  759. d3GClipped: pixel = (pixel << YCBCR2_NG_BITS) + comp;
  760. comp = (Y + Cb) >> 8;
  761. if (comp >> YCBCR2_NB_BITS) goto d3ClipB;
  762. d3BClipped: pixel = (pixel << YCBCR2_NB_BITS) + comp;
  763. *pDst++ = pTranslate[pixel];
  764. /* If pKernel off end of row, reset back (-8) to beginning of row */
  765. if (pKernel >= pKernelRowEnd)
  766. pKernel -= YCBCR2_KERNEL_SIZE;
  767. } while (--nPixelsDiv2M1 >= 0);
  768. }
  769. return IL_OK;
  770. /* goto point for when R, G or B out of range: clamp pixel and go back and continue.
  771. This is done to avoid taking a branch in the most common case: not out of range.
  772. */
  773. d0ClipR: if (pixel > YCBCR2_MAX_R) pixel = YCBCR2_MAX_R; else pixel = 0;
  774. goto d0RClipped;
  775. d0ClipG: if (comp > YCBCR2_MAX_G) comp = YCBCR2_MAX_G; else comp = 0;
  776. goto d0GClipped;
  777. d0ClipB: if (comp > YCBCR2_MAX_B) comp = YCBCR2_MAX_B; else comp = 0;
  778. goto d0BClipped;
  779. d1ClipR: if (pixel > YCBCR2_MAX_R) pixel = YCBCR2_MAX_R; else pixel = 0;
  780. goto d1RClipped;
  781. d1ClipG: if (comp > YCBCR2_MAX_G) comp = YCBCR2_MAX_G; else comp = 0;
  782. goto d1GClipped;
  783. d1ClipB: if (comp > YCBCR2_MAX_B) comp = YCBCR2_MAX_B; else comp = 0;
  784. goto d1BClipped;
  785. d2ClipR: if (pixel > YCBCR2_MAX_R) pixel = YCBCR2_MAX_R; else pixel = 0;
  786. goto d2RClipped;
  787. d2ClipG: if (comp > YCBCR2_MAX_G) comp = YCBCR2_MAX_G; else comp = 0;
  788. goto d2GClipped;
  789. d2ClipB: if (comp > YCBCR2_MAX_B) comp = YCBCR2_MAX_B; else comp = 0;
  790. goto d2BClipped;
  791. d3ClipR: if (pixel > YCBCR2_MAX_R) pixel = YCBCR2_MAX_R; else pixel = 0;
  792. goto d3RClipped;
  793. d3ClipG: if (comp > YCBCR2_MAX_G) comp = YCBCR2_MAX_G; else comp = 0;
  794. goto d3GClipped;
  795. d3ClipB: if (comp > YCBCR2_MAX_B) comp = YCBCR2_MAX_B; else comp = 0;
  796. goto d3BClipped;
  797. }
  798. /* ------------------------- ilSetupYCbCrDitherTable -------------------------- */
  799. /* Setup the given YCbCr conversion table with values for converting YCbCr->RGB
  800. with the dither values pre-multiplied into them.
  801. */
  802. static void ilSetupYCbCrDitherTable (
  803. ilRGBTransPtr pTrans,
  804. ilImageDes *pDes
  805. )
  806. {
  807. ilYCbCrInfo *pYCbCr;
  808. double Lr, Lg, Lb, scaledY;
  809. double factor, gFactor, rbDither, gDither;
  810. int i, refBlack, upper, lower;
  811. struct {
  812. int refBlack;
  813. double scale;
  814. } sample [3];
  815. /* This function sets up the given translation table, similar to
  816. ilGetYCbCrConvertTable(); see that function for more details. The difference
  817. is that the multiplications done for dithering (i.e. by table lookup into
  818. _ilMul4/8[]) are done into the values stored in the table.
  819. For example, red is obtained from Y and Cr by:
  820. red = (short)YTrans[Y] + (short)CrTrans[Cr] (1)
  821. then red is dithered down to 4 levels by:
  822. red = (pMul4[red] + kernel) >> 8; (2)
  823. where "pMul4[i]" = i * (nLevels(4) - 1) * 256 / 255"; see /ilc/ildither.c
  824. But if the values in the low-order short of YTrans and CrTrans are
  825. premultiplied by "(nLevels - 1) * 256 / 255" then the lookup into pMul4[]
  826. can be skipped, and step (2) above can be skipped.
  827. */
  828. pYCbCr = &pDes->typeInfo.YCbCr;
  829. for (i = 0; i < 3; i++) {
  830. sample[i].refBlack = pYCbCr->sample[i].refBlack;
  831. sample[i].scale = ((i == 0) ? 255 : 127) /
  832. (pYCbCr->sample[i].refWhite - pYCbCr->sample[i].refBlack);
  833. }
  834. /* Calc the Cb/Cr lookup tables, factoring in their scale factors. */
  835. Lr = ((double)pYCbCr->lumaRed / (double)10000);
  836. Lg = ((double)pYCbCr->lumaGreen / (double)10000);
  837. Lb = ((double)pYCbCr->lumaBlue / (double)10000);
  838. /* Calc the RGB dither multiply factors; R and B must be the same! */
  839. rbDither = ((1 << YCBCR2_NR_BITS) - 1) * 256 / 255;
  840. gDither = ((1 << YCBCR2_NG_BITS) - 1) * 256 / 255;
  841. /* Y translation: lower is scaled Y, upper is value added to get green */
  842. gFactor = (1 - Lb - Lr) / Lg;
  843. for (i = 0; i < 256; i++) {
  844. scaledY = sample[0].scale * i - sample[0].refBlack;
  845. upper = scaledY * gFactor * gDither + 0.5;
  846. lower = scaledY * rbDither;
  847. pTrans->YTrans[i] = (upper << 16) | (lower & 0xffff);
  848. }
  849. /* Cb: lower is added to Y to get blue, upper added to get green */
  850. factor = (2 - 2 * Lb) * sample[1].scale;
  851. gFactor = -Lb * (2 - 2 * Lb) / Lg;
  852. refBlack = sample[1].refBlack;
  853. for (i = 0; i < 256; i++) {
  854. upper = (i - refBlack) * gFactor * gDither + 0.5;
  855. lower = (i - refBlack) * factor * rbDither + 0.5;
  856. pTrans->CbTrans[i] = (upper << 16) | (lower & 0xffff);
  857. }
  858. /* Cr: lower is added to Y to get red, upper added to get green */
  859. factor = (2 - 2 * Lr) * sample[2].scale;
  860. gFactor = -Lr * (2 - 2 * Lr) / Lg;
  861. refBlack = sample[2].refBlack;
  862. for (i = 0; i < 256; i++) {
  863. upper = (i - refBlack) * gFactor * gDither + 0.5;
  864. lower = (i - refBlack) * factor * rbDither + 0.5;
  865. pTrans->CrTrans[i] = (upper << 16) | (lower & 0xffff);
  866. }
  867. }
  868. /* ---------------------------- _ilDitherYCbCr ----------------------------- */
  869. /* Does conversions of some forms of YCbCr to dithered IL_PALETTE.
  870. Returns "true" if conversion handled, else "false" if not handled or if error.
  871. The pipe image must be an uncompressed YCbCr image.
  872. */
  873. IL_PRIVATE ilBool _ilDitherYCbCr (
  874. ilPipe pipe,
  875. ilPipeInfo *pInfo,
  876. ilImageDes *pDes,
  877. ilImageFormat *pFormat,
  878. int option,
  879. ilConvertToPaletteInfo *pData
  880. )
  881. {
  882. ilSrcElementData srcData;
  883. ilDstElementData dstData;
  884. ilPtr pTranslate;
  885. ilYCbCr2DitherPrivPtr pPriv;
  886. unsigned short *pPalette;
  887. ilImageDes des;
  888. /* Check for case handled here: 8x8 area dither, levels 484 specified; pipe
  889. image is 8 bit/comp YCbCr, subsampled by 2, even width and height.
  890. */
  891. if (((option != IL_CONVERT_TO_PALETTE) && (option != 0))
  892. || !pData
  893. || (pData->method != IL_AREA_DITHER)
  894. || (pData->levels[0] != 4)
  895. || (pData->levels[1] != 8)
  896. || (pData->levels[0] != 4)
  897. || (pData->kernelSize != 8)
  898. || (pFormat->sampleOrder == IL_SAMPLE_PIXELS)
  899. || (pFormat->nBitsPerSample[0] != 8)
  900. || (pFormat->nBitsPerSample[1] != 8)
  901. || (pFormat->nBitsPerSample[2] != 8)
  902. || (pDes->typeInfo.YCbCr.sample[0].subsampleHoriz != 1)
  903. || (pDes->typeInfo.YCbCr.sample[0].subsampleVert != 1)
  904. || (pDes->typeInfo.YCbCr.sample[1].subsampleHoriz != 2)
  905. || (pDes->typeInfo.YCbCr.sample[1].subsampleVert != 2)
  906. || (pDes->typeInfo.YCbCr.sample[2].subsampleHoriz != 2)
  907. || (pDes->typeInfo.YCbCr.sample[2].subsampleVert != 2)
  908. || ((pInfo->width | pInfo->height) & 1)) { /* width or height odd */
  909. pipe->context->error = 0; /* can't handle; not an error */
  910. return FALSE;
  911. }
  912. /* If mapImage given, validate it and point to its pixels. If not given,
  913. pTranslate becomes null and will point to "identity" mapImage below.
  914. */
  915. pTranslate = (ilPtr)NULL;
  916. if (pData->mapImage) {
  917. ilImageInfo *pInfo;
  918. if (!ilQueryClientImage (pData->mapImage, &pInfo, 0)
  919. || (pInfo->width != 256) || (pInfo->height != 1)
  920. || (pInfo->pDes->compression != IL_UNCOMPRESSED)
  921. || (pInfo->pDes->nSamplesPerPixel != 1)
  922. || (pInfo->pFormat->nBitsPerSample[0] != 8))
  923. return ilDeclarePipeInvalid (pipe, IL_ERROR_MAP_IMAGE);
  924. pTranslate = pInfo->plane[0].pPixels;
  925. }
  926. /* alloc pPalette unless not palette dst; init with ramp if not choosing */
  927. pPalette = (unsigned short *)NULL;
  928. if (pData->dstType == IL_PALETTE) {
  929. int red, green, blue;
  930. int redLevel, greenLevel, blueLevel;
  931. unsigned short *pPal;
  932. pPalette = (unsigned short *)IL_MALLOC_ZERO (3 * 256 * sizeof(unsigned short));
  933. if (!pPalette)
  934. return ilDeclarePipeInvalid (pipe, IL_ERROR_MALLOC);
  935. pPal = pPalette;
  936. for (red = 0; red < pData->levels[0]; red++) {
  937. redLevel = 65535 * red / (pData->levels[0] - 1);
  938. for (green = 0; green < pData->levels[1]; green++) {
  939. greenLevel = 65535 * green / (pData->levels[1] - 1);
  940. for (blue = 0; blue < pData->levels[2]; blue++) {
  941. blueLevel = 65535 * blue / (pData->levels[2] - 1);
  942. pPal [0] = redLevel;
  943. pPal [256] = greenLevel;
  944. pPal [512] = blueLevel;
  945. pPal++;
  946. }
  947. }
  948. }
  949. }
  950. /* Add element to the pipe, init private. Accept strips as they are;
  951. presumably they will be even # lines because image is subsampled.
  952. */
  953. srcData.consumerImage = (ilObject)NULL;
  954. srcData.stripHeight = pInfo->stripHeight;
  955. srcData.constantStrip = FALSE;
  956. srcData.minBufferHeight = 0;
  957. dstData.producerObject = (ilObject)NULL;
  958. des = *IL_DES_GRAY;
  959. des.type = pData->dstType;
  960. if (des.type == IL_PALETTE) {
  961. des.flags = IL_DITHERED_PALETTE;
  962. des.typeInfo.palette.levels[0] = pData->levels[0];
  963. des.typeInfo.palette.levels[1] = pData->levels[1];
  964. des.typeInfo.palette.levels[2] = pData->levels[2];
  965. }
  966. dstData.pDes = &des;
  967. dstData.pFormat = IL_FORMAT_BYTE;
  968. dstData.width = pInfo->width;
  969. dstData.height = pInfo->height;
  970. dstData.stripHeight = 0;
  971. dstData.constantStrip = FALSE;
  972. dstData.pPalette = pPalette;
  973. pPriv = (ilYCbCr2DitherPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  974. sizeof(ilYCbCr2DitherPrivRec), 0, &srcData, &dstData,
  975. ilYCbCr2DitherInit, IL_NPF, ilYCbCr2DitherDestroy, ilYCbCr2DitherExecute, NULL, 0);
  976. if (!pPriv) {
  977. return FALSE;
  978. }
  979. /* Init pPriv; point pTranslate to identity image if no mapImage given */
  980. if (pTranslate)
  981. pPriv->pTranslate = pTranslate;
  982. else {
  983. int i;
  984. pPriv->pTranslate = pPriv->translate;
  985. for (i = 0; i < 256; i++)
  986. pPriv->translate[i] = i;
  987. }
  988. pPriv->pPalette = pPalette;
  989. /* Init tables for YCbCr->RGB conversion plus dithering */
  990. ilSetupYCbCrDitherTable (&pPriv->trans, pDes);
  991. /* Update pipe info and return */
  992. ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
  993. return TRUE;
  994. }
  995. /* ======================= RGB To YCbCr Code =================================== */
  996. /* # of bits of fixed point precision for interim values during conversion */
  997. #define PR2Y 16
  998. /* Private for RGB to YCbCr filter. For each component to be calculated (Y/Cb/Cr),
  999. a table indexed by the src component (R/G/B) which gives the contribution
  1000. for that src component, in fixed point: <32-PR2Y bits>.<PR2Y bits>
  1001. */
  1002. typedef struct {
  1003. long YR[256], YG[256], YB[256]; /* component lookup tables */
  1004. long CbR[256], CbG[256], CbB[256];
  1005. long CrR[256], CrG[256], CrB[256];
  1006. long YRefBlack, CbRefBlack, CrRefBlack; /* component reference black */
  1007. } ilRGBToYCbCrPrivRec, *ilRGBToYCbCrPrivPtr;
  1008. /* Macro to do floor/ceiling of given value: makes it 0..255.
  1009. Shift right by 8; if not zero, is < 0 or > 255; handle those cases.
  1010. */
  1011. #define BYTE_RANGE(_pixel) { \
  1012. if (_pixel & ~0xff) \
  1013. if ((_pixel) < 0) _pixel = 0; \
  1014. else _pixel = 255; \
  1015. }
  1016. /* ----------------------- ilExecuteRGBToYCbCr -------------------------------- */
  1017. /* Execute(): convert _pixel_ src RGB to _planar_ dst YCbCr.
  1018. */
  1019. static ilError ilExecuteRGBToYCbCr (
  1020. ilExecuteData *pData,
  1021. long dstLine,
  1022. long *pNLines
  1023. )
  1024. {
  1025. ilRGBToYCbCrPrivPtr pPriv;
  1026. ilPtr pSrcLine, pYLine, pCbLine, pCrLine;
  1027. ilPtr pSrc, pY, pCb, pCr;
  1028. long nPixelsM1;
  1029. long YRefBlack, CbRefBlack, CrRefBlack;
  1030. long nPixelsM1Init, nLinesM1;
  1031. long YRowBytes, CbRowBytes, CrRowBytes, srcRowBytes;
  1032. ilImagePlaneInfo *pPlane;
  1033. long R, G, B, pixel;
  1034. /* Set nPixels/LinesM1 to # pixels / lines - 1; exit if either 0. */
  1035. pPriv = (ilRGBToYCbCrPrivPtr)pData->pPrivate;
  1036. nPixelsM1Init = pData->pSrcImage->width;
  1037. if (nPixelsM1Init <= 0)
  1038. return 0;
  1039. nPixelsM1Init--;
  1040. nLinesM1 = *pNLines;
  1041. if (nLinesM1 <= 0)
  1042. return 0;
  1043. nLinesM1--;
  1044. /* Point pSrcLine to first line of src RGB (pixel-order) data; point
  1045. pY/Cb/CrLine to 1st line in dst YCbCr (planar-order) data planes.
  1046. Get bytes/row for each of them.
  1047. */
  1048. pPlane = pData->pSrcImage->plane;
  1049. srcRowBytes = pPlane->nBytesPerRow;
  1050. pSrcLine = pPlane->pPixels + pData->srcLine * srcRowBytes;
  1051. pPlane = pData->pDstImage->plane;
  1052. YRowBytes = pPlane->nBytesPerRow;
  1053. pYLine = pPlane->pPixels + dstLine * YRowBytes;
  1054. pPlane++;
  1055. CbRowBytes = pPlane->nBytesPerRow;
  1056. pCbLine = pPlane->pPixels + dstLine * CbRowBytes;
  1057. pPlane++;
  1058. CrRowBytes = pPlane->nBytesPerRow;
  1059. pCrLine = pPlane->pPixels + dstLine * CrRowBytes;
  1060. /* Load component refBlack values, plus 1/2 shift (precision) amt for rounding
  1061. into values, shifted up so it can be added before right shift.
  1062. */
  1063. YRefBlack = (pPriv->YRefBlack << PR2Y) + (1 << (PR2Y - 1));
  1064. CbRefBlack = (pPriv->CbRefBlack << PR2Y) + (1 << (PR2Y - 1));
  1065. CrRefBlack = (pPriv->CrRefBlack << PR2Y) + (1 << (PR2Y - 1));
  1066. /* Convert pixel RGB to planar YCbCr. */
  1067. do {
  1068. pSrc = pSrcLine;
  1069. pSrcLine += srcRowBytes;
  1070. pY = pYLine;
  1071. pYLine += YRowBytes;
  1072. pCb = pCbLine;
  1073. pCbLine += CbRowBytes;
  1074. pCr = pCrLine;
  1075. pCrLine += CrRowBytes;
  1076. nPixelsM1 = nPixelsM1Init;
  1077. do {
  1078. R = *pSrc++;
  1079. G = *pSrc++;
  1080. B = *pSrc++;
  1081. pixel = (pPriv->YR[R] + pPriv->YG[G] + pPriv->YB[B] + YRefBlack) >> PR2Y;
  1082. if (pixel >> 8) goto YClip;
  1083. YClipped: *pY++ = pixel;
  1084. pixel = (pPriv->CbR[R] + pPriv->CbG[G] + pPriv->CbB[B] + CbRefBlack) >> PR2Y;
  1085. if (pixel >> 8) goto CbClip;
  1086. CbClipped: *pCb++ = pixel;
  1087. pixel = (pPriv->CrR[R] + pPriv->CrG[G] + pPriv->CrB[B] + CrRefBlack) >> PR2Y;
  1088. if (pixel >> 8) goto CrClip;
  1089. CrClipped: *pCr++ = pixel;
  1090. } while (--nPixelsM1 >= 0);
  1091. } while (--nLinesM1 >= 0);
  1092. return IL_OK;
  1093. /* goto point for when Y/Cb/Cr out of range: clamp pixel and go back and continue.
  1094. This is done to avoid taking a branch in the most common case: not out of range.
  1095. */
  1096. YClip: if (pixel > 255) pixel = 255; else pixel = 0;
  1097. goto YClipped;
  1098. CbClip: if (pixel > 255) pixel = 255; else pixel = 0;
  1099. goto CbClipped;
  1100. CrClip: if (pixel > 255) pixel = 255; else pixel = 0;
  1101. goto CrClipped;
  1102. }
  1103. /* ---------------------------- ilConvertRGBToYCbCr ----------------------------- */
  1104. /* Convert from source type (pDes->type) == RGB to YCbCr.
  1105. pFormat points to the source format; on return, *pFormat is updated
  1106. to the dst format. pNewDes points to the dst dest; *pDes to the src (pipe) des;
  1107. on return it is updated to the new descriptor.
  1108. */
  1109. IL_PRIVATE ilBool _ilConvertRGBToYCbCr (
  1110. ilPipe pipe,
  1111. ilPipeInfo *pInfo,
  1112. ilImageDes *pDes,
  1113. const ilImageDes *pNewDes,
  1114. ilImageFormat *pFormat
  1115. )
  1116. {
  1117. ilRGBToYCbCrPrivPtr pPriv;
  1118. ilYCbCrInfo *pYCbCr;
  1119. ilDstElementData dstData;
  1120. double Lr, Lg, Lb, range;
  1121. long YR, YG, YB;
  1122. long CbR, CbG, CbB;
  1123. long CrR, CrG, CrB;
  1124. int i;
  1125. /* Get format = planar order, 8 bits / pixel, or error */
  1126. if ((pFormat->nBitsPerSample[0] != 8)
  1127. || (pFormat->nBitsPerSample[1] != 8)
  1128. || (pFormat->nBitsPerSample[2] != 8)
  1129. || (pFormat->sampleOrder != IL_SAMPLE_PIXELS)) {
  1130. if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
  1131. return FALSE;
  1132. }
  1133. /* Add filter to write 3 planar YCbCr format image. Update pDes: std YCbCr but
  1134. with caller's sample refBlack/White and lumaRed/Green/Blue.
  1135. */
  1136. *pDes = *IL_DES_YCBCR;
  1137. pDes->typeInfo.YCbCr.sample[0].refBlack = pNewDes->typeInfo.YCbCr.sample[0].refBlack;
  1138. pDes->typeInfo.YCbCr.sample[0].refWhite = pNewDes->typeInfo.YCbCr.sample[0].refWhite;
  1139. pDes->typeInfo.YCbCr.sample[1].refBlack = pNewDes->typeInfo.YCbCr.sample[1].refBlack;
  1140. pDes->typeInfo.YCbCr.sample[1].refWhite = pNewDes->typeInfo.YCbCr.sample[1].refWhite;
  1141. pDes->typeInfo.YCbCr.sample[2].refBlack = pNewDes->typeInfo.YCbCr.sample[2].refBlack;
  1142. pDes->typeInfo.YCbCr.sample[2].refWhite = pNewDes->typeInfo.YCbCr.sample[2].refWhite;
  1143. pDes->typeInfo.YCbCr.lumaRed = pNewDes->typeInfo.YCbCr.lumaRed;
  1144. pDes->typeInfo.YCbCr.lumaGreen = pNewDes->typeInfo.YCbCr.lumaGreen;
  1145. pDes->typeInfo.YCbCr.lumaBlue = pNewDes->typeInfo.YCbCr.lumaBlue;
  1146. *pFormat = *IL_FORMAT_3BYTE_PLANE;
  1147. dstData.producerObject = (ilObject)NULL;
  1148. dstData.pDes = pDes;
  1149. dstData.pFormat = pFormat;
  1150. dstData.width = pInfo->width;
  1151. dstData.height = pInfo->height;
  1152. dstData.stripHeight = 0;
  1153. dstData.constantStrip = FALSE;
  1154. dstData.pPalette = (unsigned short *)NULL;
  1155. pPriv = (ilRGBToYCbCrPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
  1156. sizeof(ilRGBToYCbCrPrivRec), 0, (ilSrcElementData *)NULL, &dstData,
  1157. IL_NPF, IL_NPF, IL_NPF, ilExecuteRGBToYCbCr, NULL, 0);
  1158. if (!pPriv)
  1159. return FALSE;
  1160. /* See Appendix O pg 3 of TIFF spec. Use fixed point (16.16) for
  1161. floating point values.
  1162. Y = Lr*R + Lg*G + Lb*B
  1163. Cb = (B - Y) / (2-2*Lb)
  1164. = (B - Lr*R - Lg*G - Lb*B) / (2-2*Lb)
  1165. = R * -Lr/(2-2*Lb) + G * -Lg/(2-2*Lb) + B * (1-Lb)/(2-2*Lb)
  1166. Cr = (R - Y) / (2-2*Lr)
  1167. = (R - Lr*R - Lg*G - Lb*B) / (2-2*Lr)
  1168. = R * (1-Lr)/(2-2*Lr) + G * -Lg/(2-2*Lr) + B * -Lb/(2-2*Lr)
  1169. In each case, the scale up to account for the scaling range is done
  1170. by multiplying the scaling range into each RGB factor. The refBlack is
  1171. then added (not shown above). Each of the values multiplied times R/G/B
  1172. is called "Y/Cb/Cr|R/G/B".
  1173. */
  1174. pYCbCr = &pDes->typeInfo.YCbCr;
  1175. Lr = (double)pYCbCr->lumaRed / 10000;
  1176. Lg = (double)pYCbCr->lumaGreen / 10000;
  1177. Lb = (double)pYCbCr->lumaBlue / 10000;
  1178. /* Y R/G/B multiples, plus refBlack. */
  1179. range = (1 << PR2Y) * (double)(pYCbCr->sample[0].refWhite - pYCbCr->sample[0].refBlack) / 255;
  1180. YR = range * Lr + 0.5;
  1181. YG = range * Lg + 0.5;
  1182. YB = range * Lb + 0.5;
  1183. pPriv->YRefBlack = pYCbCr->sample[0].refBlack;
  1184. /* Cb and Cr multiples, refBlack. Note coding range for Cb/Cr == 127. */
  1185. range = (1 << PR2Y) * (double)(pYCbCr->sample[1].refWhite - pYCbCr->sample[1].refBlack) / 127;
  1186. CbR = range * -Lr/(2-2*Lb) + 0.5;
  1187. CbG = range * -Lg/(2-2*Lb) + 0.5;
  1188. CbB = range * (1-Lb)/(2-2*Lb) + 0.5;
  1189. pPriv->CbRefBlack = pYCbCr->sample[1].refBlack;
  1190. range = (1 << PR2Y) * (double)(pYCbCr->sample[2].refWhite - pYCbCr->sample[2].refBlack) / 127;
  1191. CrR = range * (1-Lr)/(2-2*Lr) + 0.5;
  1192. CrG = range * -Lg/(2-2*Lr) + 0.5;
  1193. CrB = range * -Lb/(2-2*Lr) + 0.5;
  1194. pPriv->CrRefBlack = pYCbCr->sample[2].refBlack;
  1195. /* Build lookup table which is the result of multiplying the above by 0..255,
  1196. i.e. the source RGB values. Using this lookup table is equivalent to multiply
  1197. but a whole lot faster.
  1198. */
  1199. for (i = 0; i < 256; i++) {
  1200. pPriv->YR[i] = YR * i;
  1201. pPriv->YG[i] = YG * i;
  1202. pPriv->YB[i] = YB * i;
  1203. pPriv->CbR[i] = CbR * i;
  1204. pPriv->CbG[i] = CbG * i;
  1205. pPriv->CbB[i] = CbB * i;
  1206. pPriv->CrR[i] = CrR * i;
  1207. pPriv->CrG[i] = CrG * i;
  1208. pPriv->CrB[i] = CrB * i;
  1209. }
  1210. return TRUE;
  1211. }