ilconvert.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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 librararies 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: ilconvert.c /main/5 1996/06/19 12:24:11 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. #include "ilint.h"
  40. #include "ilpipeint.h"
  41. #include "ilpipelem.h"
  42. #include "ilconvert.h"
  43. #include "ilerrors.h"
  44. /* ---------------------- ilAddConversionFilter --------------------------- */
  45. /* Add a conversion filter to the given pipe, given a ptr to a structure
  46. which defines the filter and its pipe element. If failure, declare pipe
  47. invalid (which sets error code) and return false; else true.
  48. pInfo must point to the current pipe info; pSrcDes/Format to the pipe
  49. des/format. The information they point to is updated after the pipe
  50. element(s) is/are added; on return they will contain up-to-date data.
  51. */
  52. static ilBool ilAddConversionFilter (
  53. ilPipe pipe,
  54. ilPipeInfo *pInfo,
  55. ilImageDes *pSrcDes,
  56. ilImageFormat *pSrcFormat,
  57. void *pOptionData,
  58. register ilConvertPtr pCvtData
  59. )
  60. {
  61. ilPtr pPriv;
  62. ilDstElementData dstData;
  63. ilError error;
  64. /* Check src format against code for src format demanded by this filter.
  65. If not the same, do ilConvert() to that format (recurse!), exit if error.
  66. */
  67. switch (pCvtData->srcFormatCode) {
  68. case IL_DONT_CHECK_STD_FORMAT: /* filter converts format: dont check */
  69. break;
  70. case IL_STD_FORMAT_BIT:
  71. if ((pSrcFormat->rowBitAlign != 32)
  72. || (pSrcFormat->nBitsPerSample[0] != 1)) {
  73. *pSrcFormat = *IL_FORMAT_BIT;
  74. ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
  75. if (pipe->context->error) return FALSE;
  76. ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
  77. }
  78. break;
  79. case IL_STD_FORMAT_BYTE:
  80. if (pSrcFormat->nBitsPerSample[0] != 8) {
  81. *pSrcFormat = *IL_FORMAT_BYTE;
  82. ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
  83. if (pipe->context->error) return FALSE;
  84. ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
  85. }
  86. break;
  87. case IL_STD_FORMAT_3BYTE_PIXEL:
  88. if ((pSrcFormat->sampleOrder != IL_SAMPLE_PIXELS)
  89. || (pSrcFormat->nBitsPerSample[0] != 8)
  90. || (pSrcFormat->nBitsPerSample[1] != 8)
  91. || (pSrcFormat->nBitsPerSample[2] != 8)) {
  92. *pSrcFormat = *IL_FORMAT_3BYTE_PIXEL;
  93. ilConvert (pipe, (ilImageDes *)NULL, pSrcFormat, 0, NULL);
  94. if (pipe->context->error) return FALSE;
  95. ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
  96. }
  97. break;
  98. }
  99. /* Add a filter, from in *pCvtData. Only the des and format may change;
  100. other info (width, stripHeight, etc.) stays the same.
  101. */
  102. dstData.producerObject = (ilObject)NULL;
  103. dstData.pDes = pCvtData->pDstDes;
  104. dstData.pFormat = pCvtData->pDstFormat;
  105. dstData.width = pInfo->width;
  106. dstData.height = pInfo->height;
  107. dstData.stripHeight = 0;
  108. dstData.constantStrip = FALSE;
  109. dstData.pPalette = (unsigned short *)NULL;
  110. pPriv = ilAddPipeElement (pipe, IL_FILTER, pCvtData->nBytesPrivate, 0,
  111. (ilSrcElementData *)NULL, &dstData, pCvtData->Init, pCvtData->Cleanup,
  112. pCvtData->Destroy, pCvtData->Execute, NULL, 0);
  113. if (!pPriv) return FALSE; /* EXIT */
  114. /* If successful: call converters init function if non-null, return true.
  115. */
  116. if (pCvtData->AddElement) {
  117. error = (*pCvtData->AddElement) (pPriv, pInfo->pPalette, pOptionData);
  118. if (error) {
  119. ilDeclarePipeInvalid (pipe, error);
  120. return FALSE; /* EXIT */
  121. }
  122. }
  123. /* Update the pipe info, return success.
  124. */
  125. ilGetPipeInfo (pipe, FALSE, pInfo, pSrcDes, pSrcFormat);
  126. return TRUE;
  127. }
  128. /* ---------------------- ilAddFormatFilter --------------------------- */
  129. /* Add a filter to the given pipe which converts format only to *pNewFormat.
  130. Similar to ilAddConversionFilter() but simpler.
  131. *pInfo is updated with the new pipe info.
  132. */
  133. static ilBool ilAddFormatFilter (
  134. ilPipe pipe,
  135. ilPipeInfo *pInfo,
  136. const ilImageFormat *pNewFormat,
  137. register ilFormatPtr pData
  138. )
  139. {
  140. ilPtr pPriv;
  141. ilDstElementData dstData;
  142. ilError error;
  143. /* Add a filter, from in *pData. Only the format may change;
  144. other info (des, width, stripHeight, etc.) stays the same.
  145. */
  146. dstData.producerObject = (ilObject)NULL;
  147. dstData.pDes = (ilImageDes *)NULL;
  148. dstData.pFormat = pNewFormat;
  149. dstData.width = pInfo->width;
  150. dstData.height = pInfo->height;
  151. dstData.stripHeight = 0;
  152. dstData.constantStrip = FALSE;
  153. dstData.pPalette = (unsigned short *)NULL;
  154. pPriv = ilAddPipeElement (pipe, IL_FILTER, pData->nBytesPrivate, 0,
  155. (ilSrcElementData *)NULL, &dstData, pData->Init, pData->Cleanup,
  156. pData->Destroy, pData->Execute, NULL, 0);
  157. if (!pPriv) return FALSE; /* EXIT */
  158. /* If successful: call converters init function if non-null, return true.
  159. */
  160. if (pData->AddElement) {
  161. error = (*pData->AddElement) (pPriv, pInfo->pPalette);
  162. if (error) {
  163. ilDeclarePipeInvalid (pipe, error);
  164. return FALSE; /* EXIT */
  165. }
  166. }
  167. /* Update the pipe info, return success. */
  168. ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);
  169. return TRUE;
  170. }
  171. /* ---------------------------- ilConvert -------------------------------- */
  172. /* Public function; see spec.
  173. Convert the current pipe image to the given description (*pDes) and
  174. format (*pFormat). Either or both (a noop) may be null. A null pDes means
  175. "the same as before"; a null pFormat means "whatever is easiest/most
  176. efficient."
  177. If the current pipe image already fits the bill, no pipe element is added.
  178. Note: compression is ignored in "pDes" - call ilCompress() to compress.
  179. */
  180. ilBool ilConvert (
  181. ilPipe pipe,
  182. const ilImageDes *pDes,
  183. const ilImageFormat *pFormat,
  184. int option,
  185. void *pOptionData
  186. )
  187. {
  188. ilPipeInfo info;
  189. ilImageDes pipeDes;
  190. ilImageFormat pipeFormat;
  191. unsigned int sample;
  192. ilBool doConvert, doSubsample;
  193. static unsigned long defaultThreshold = 128; /* dflt threshold for gray->bitonal cvt */
  194. #define ADD_CVT_FILTER(_filter) \
  195. (ilAddConversionFilter (pipe, &info, &pipeDes, &pipeFormat, pOptionData, (_filter)))
  196. /* Macro to determine if the given YCbCr must be upsampled (any bits != 1) */
  197. #define MUST_UPSAMPLE(_des) \
  198. ( ((_des).typeInfo.YCbCr.sample[0].subsampleHoriz | \
  199. (_des).typeInfo.YCbCr.sample[0].subsampleVert | \
  200. (_des).typeInfo.YCbCr.sample[1].subsampleHoriz | \
  201. (_des).typeInfo.YCbCr.sample[1].subsampleVert | \
  202. (_des).typeInfo.YCbCr.sample[2].subsampleHoriz | \
  203. (_des).typeInfo.YCbCr.sample[2].subsampleVert) != 1)
  204. /* Overall approach: if pDes specified, try to convert image descriptor
  205. if different, by adding filters with ilAddConversionFilter(): the des
  206. converting filter may add a reformat filter before it, and may change
  207. the format - the new des and format are returned if changed.
  208. After converting the description if necessary, check format if
  209. pFormat is non-null and reformat as necessary. A format converter
  210. cannot change the des.
  211. Note that we need not validate the format and des together.
  212. ilAddPipeElement() will do that and return an error if they are incompatible
  213. (e.g. des.type = IL_RGB with des.nSamplesPerPixel != 3).
  214. */
  215. /* Get pipe info and decompress! if not ready for a filter, exit.
  216. */
  217. if (ilGetPipeInfo (pipe, TRUE, &info, &pipeDes, &pipeFormat) != IL_PIPE_FORMING) {
  218. if (!pipe->context->error)
  219. ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
  220. return FALSE; /* EXIT */
  221. }
  222. /* If no pDes, point pDes to pipe des for format check below, else check for
  223. descriptor conversions.
  224. */
  225. doSubsample = FALSE; /* assume no subsampling; may be set below */
  226. if (!pDes)
  227. pDes = &pipeDes;
  228. else {
  229. /* ilConvert() does not compress - use ilCompress() to compress. */
  230. if (pDes->compression != IL_UNCOMPRESSED)
  231. return ilDeclarePipeInvalid (pipe, IL_ERROR_CONVERT_COMPRESSION);
  232. if (pipeDes.type == pDes->type) /* cvt within type */
  233. switch (pipeDes.type) {
  234. /* Within YCbCr: check for changes to luma or refBlack/White. If any,
  235. convert to RGB; below cvt back to YCbCr will handle luma and ref.
  236. */
  237. case IL_YCBCR: {
  238. const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
  239. ilBool doCvtYCbCr;
  240. /* If must convert refBlack/White or lumaRed/Green/Blue, convert to
  241. RGB and back to YCbCr; only those conversions handle this.
  242. */
  243. if ((pipeDes.typeInfo.YCbCr.lumaRed != pDes->typeInfo.YCbCr.lumaRed)
  244. || (pipeDes.typeInfo.YCbCr.lumaGreen != pDes->typeInfo.YCbCr.lumaGreen)
  245. || (pipeDes.typeInfo.YCbCr.lumaBlue != pDes->typeInfo.YCbCr.lumaBlue))
  246. doCvtYCbCr = TRUE;
  247. else {
  248. for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
  249. pDstSample = pDes->typeInfo.YCbCr.sample,
  250. doCvtYCbCr = FALSE, sample = 0;
  251. sample < 3; sample++, pSrcSample++, pDstSample++)
  252. if ((pSrcSample->refBlack != pDstSample->refBlack)
  253. || (pSrcSample->refWhite != pDstSample->refWhite))
  254. doCvtYCbCr = TRUE;
  255. }
  256. if (doCvtYCbCr) { /* cvt to RGB */
  257. if (!ilConvert (pipe, IL_DES_RGB, (ilImageFormat *)NULL, 0, NULL))
  258. return FALSE;
  259. ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
  260. }
  261. break;
  262. }
  263. /* Within palette: if option is zero (0), or if option says to dither
  264. and image already dithered to requested levels: fine, done; otherwise
  265. cvt first to RGB, so below conversion to palette will be enabled.
  266. */
  267. case IL_PALETTE:
  268. if (option == 0)
  269. break; /* default = accept as is; fine */
  270. if (option == IL_CONVERT_TO_PALETTE) {
  271. ilConvertToPaletteInfo *pData = (ilConvertToPaletteInfo *)pOptionData;
  272. if ((pipeDes.flags & IL_DITHERED_PALETTE)
  273. && (pipeDes.typeInfo.palette.levels[0] == pData->levels[0])
  274. && (pipeDes.typeInfo.palette.levels[1] == pData->levels[1])
  275. && (pipeDes.typeInfo.palette.levels[2] == pData->levels[2]))
  276. break; /* dithered to requested levels; fine */
  277. }
  278. if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte)) /* cvt up to RGB */
  279. return FALSE;
  280. break;
  281. } /* END cvt within type */
  282. /* Loop converting image type until desired type reached. May take some
  283. iterations, e.g pal->bitonal = pal->rgb; rgb->gray; gray->bitonal.
  284. For conversion to YCbCr, cvt to RGB first.
  285. For conversion to palette, cvt to RGB first.
  286. */
  287. while (pipeDes.type != pDes->type) {
  288. switch (pipeDes.type) {
  289. /* Bitonal: cvt to gray, then to other types as necessary. */
  290. case IL_BITONAL:
  291. switch (pDes->type) {
  292. case IL_GRAY:
  293. case IL_YCBCR:
  294. case IL_PALETTE:
  295. case IL_RGB: {
  296. if (!ilScale (pipe, info.width, info.height, IL_SCALE_BITONAL_TO_GRAY, NULL))
  297. return FALSE;
  298. ilGetPipeInfo (pipe, FALSE, &info, &pipeDes, &pipeFormat);
  299. break;
  300. }
  301. default:
  302. goto CantConvert; /* unsupported conversion(s) */
  303. }
  304. break;
  305. case IL_GRAY:
  306. /* If not 256 levels/sample, cvt to 256 if possible. */
  307. if (pipeDes.nLevelsPerSample[0] != 256)
  308. if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_GRAY, &pipeFormat))
  309. return FALSE;
  310. switch (pDes->type) {
  311. case IL_BITONAL:
  312. if (option == IL_CONVERT_THRESHOLD) {
  313. if (!pOptionData)
  314. pOptionData = &defaultThreshold;
  315. if (!ADD_CVT_FILTER (&_ilThresholdGrayToBitonal))
  316. return FALSE; /* error, EXIT */
  317. }
  318. else if (!ADD_CVT_FILTER (&_ilDiffuseGrayToBitonal))
  319. return FALSE; /* error, EXIT */
  320. break;
  321. case IL_YCBCR:
  322. case IL_PALETTE:
  323. case IL_RGB:
  324. if (!ADD_CVT_FILTER (&_ilGrayToRGB))
  325. return FALSE; /* error, EXIT */
  326. break;
  327. default:
  328. goto CantConvert; /* unsupported conversion(s) */
  329. }
  330. break;
  331. /* Palette to anything (except self - but that case wont get here)
  332. is currently done by converting to RGB, then to des type if necessary.
  333. */
  334. case IL_PALETTE:
  335. if (!ADD_CVT_FILTER (&_ilPaletteToRGBByte))
  336. return FALSE; /* error, EXIT */
  337. break;
  338. /* RGB goes to gray for gray or bitonal; handle conversion to YCbCr.
  339. If not 256 levels/sample, cvt to 256 if possible.
  340. */
  341. case IL_RGB:
  342. if ((pipeDes.nLevelsPerSample[0] != 256)
  343. || (pipeDes.nLevelsPerSample[1] != 256)
  344. || (pipeDes.nLevelsPerSample[2] != 256))
  345. if (!_ilAddLevelConversionFilter (pipe, &info, &pipeDes, IL_DES_RGB, &pipeFormat))
  346. return FALSE;
  347. switch (pDes->type) {
  348. case IL_BITONAL:
  349. case IL_GRAY:
  350. if (!ADD_CVT_FILTER (&_ilRGBToGray))
  351. return FALSE; /* error, EXIT */
  352. break;
  353. case IL_YCBCR:
  354. if (!_ilConvertRGBToYCbCr (pipe, &info, &pipeDes, pDes, &pipeFormat))
  355. return FALSE;
  356. break;
  357. /* Cvt RGB to palette: set pipeDes.type to IL_PALETTE to terminate
  358. loop: private type may actually have been created.
  359. */
  360. case IL_PALETTE:
  361. if (!_ilConvertRGBToPalette (pipe, &info, &pipeDes, &pipeFormat,
  362. option, (ilConvertToPaletteInfo *)pOptionData))
  363. return FALSE;
  364. pipeDes.type = IL_PALETTE; /* see note above */
  365. break;
  366. default:
  367. goto CantConvert; /* unsupported conversion(s) */
  368. }
  369. break;
  370. /* YCbCr (aka LUV): convert based on dst type and set "convertDone"
  371. to true, else convert to RGB, and then loop again until desired type.
  372. */
  373. case IL_YCBCR: {
  374. ilBool convertDone, upSample;
  375. upSample = MUST_UPSAMPLE (pipeDes);
  376. convertDone = FALSE;
  377. switch (pDes->type) {
  378. case IL_BITONAL:
  379. case IL_GRAY: /* extract Y plane if Y range 0..255 */
  380. if ((pipeDes.typeInfo.YCbCr.sample[0].refBlack == 0)
  381. && (pipeDes.typeInfo.YCbCr.sample[0].refWhite == 255)) {
  382. if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, TRUE,
  383. upSample))
  384. return FALSE;
  385. convertDone = TRUE;
  386. }
  387. break;
  388. case IL_PALETTE: /* try direct YCbCr to palette conversion */
  389. if (_ilDitherYCbCr (pipe, &info, &pipeDes, &pipeFormat, option,
  390. (ilConvertToPaletteInfo *)pOptionData)) {
  391. convertDone = TRUE;
  392. pipeDes.type = IL_PALETTE; /* see note above RGB->palette */
  393. }
  394. else if (pipe->context->error)
  395. return FALSE; /* otherwise, no error; filter just cant do it */
  396. break;
  397. }
  398. if (!convertDone) { /* no conversion; convert YCbCr to RGB */
  399. if (upSample && !_ilUpsampleYCbCr (pipe, &info, &pipeDes,
  400. &pipeFormat, FALSE, upSample))
  401. return FALSE;
  402. if (!_ilConvertYCbCrToRGB (pipe, &info, &pipeDes, &pipeFormat))
  403. return FALSE;
  404. }
  405. break;
  406. }
  407. } /* END switch source type */
  408. } /* END while convert type */
  409. /* Image type converted if different; check rest of des. */
  410. if (pipeDes.nSamplesPerPixel != pDes->nSamplesPerPixel)
  411. goto CantConvert;
  412. /* Check levels/sample, but not for palette images, where the levels/sample
  413. must be in range 2 .. (1<<nbits) - 1, but is otherwise ignored.
  414. */
  415. for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
  416. if (pipeDes.nLevelsPerSample[sample] != pDes->nLevelsPerSample[sample]) {
  417. if ((pipeDes.type != IL_PALETTE) &&
  418. !_ilAddLevelConversionFilter (pipe, &info, &pipeDes, pDes, &pipeFormat))
  419. return FALSE;
  420. break;
  421. }
  422. /* Do image type-specific checks and conversions. */
  423. switch (pipeDes.type) {
  424. /* "blackIsZero" applies only to bitonal and gray scale images. If different
  425. then invert bits if not "soft" invert (which means leave bits alone);
  426. if same, invert bits if "hard" invert (which means invert bits).
  427. */
  428. case IL_BITONAL:
  429. case IL_GRAY:
  430. if (pipeDes.blackIsZero != pDes->blackIsZero) {
  431. pipeDes.blackIsZero = pDes->blackIsZero;
  432. if (option == IL_CONVERT_SOFT_INVERT)
  433. _ilSetPipeDesFormat (pipe, &pipeDes, (ilImageFormat *)NULL);
  434. else if (!_ilAddInvertFilter (pipe, &pipeDes, &info))
  435. goto CantConvert;
  436. }
  437. break;
  438. /* YCbCr: check sub/upsampling; up/subsample as necessary */
  439. case IL_YCBCR: {
  440. const ilYCbCrSampleInfo *pSrcSample, *pDstSample;
  441. ilBool doUpsample;
  442. doSubsample = FALSE; /* checked below */
  443. for (pSrcSample = pipeDes.typeInfo.YCbCr.sample,
  444. pDstSample = pDes->typeInfo.YCbCr.sample,
  445. doUpsample = FALSE, sample = 0;
  446. sample < 3; sample++, pSrcSample++, pDstSample++)
  447. {
  448. if (pSrcSample->subsampleHoriz < pDstSample->subsampleHoriz)
  449. doSubsample = TRUE;
  450. else if (pSrcSample->subsampleHoriz > pDstSample->subsampleHoriz)
  451. doUpsample = TRUE;
  452. if (pSrcSample->subsampleVert < pDstSample->subsampleVert)
  453. doSubsample = TRUE;
  454. else if (pSrcSample->subsampleVert > pDstSample->subsampleVert)
  455. doUpsample = TRUE;
  456. }
  457. if (doUpsample)
  458. if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
  459. return FALSE;
  460. if (doSubsample) {
  461. pipeDes = *pDes; /* pass subsample pars; des convert done */
  462. if (!_ilSubsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat))
  463. return FALSE;
  464. }
  465. } /* END YCbCr */
  466. break;
  467. }
  468. } /* END check pDes */
  469. /* If pFormat given, convert to requested format.
  470. WARNING !!!!! - ilCheckPipeFormat() below also does format conversions -
  471. May have to change it when adding new format filters !!!!
  472. */
  473. if (pFormat) {
  474. /* Check if bits/sample needs conversion and if that conversion supported.
  475. Currently supported: 4 to 8 bit, pixel mode only if multi-sample.
  476. */
  477. doConvert = FALSE;
  478. for (sample = 0; sample < pDes->nSamplesPerPixel; sample++)
  479. if (pipeFormat.nBitsPerSample[sample] != pFormat->nBitsPerSample[sample]) {
  480. doConvert = TRUE;
  481. break;
  482. }
  483. /* If any format conversions and YCbCr, upsample if necessary.
  484. However, if subsampling was done before, error: cant convert.
  485. */
  486. if ((pipeDes.type == IL_YCBCR)
  487. && MUST_UPSAMPLE (pipeDes)
  488. && (doConvert || (pipeFormat.sampleOrder != pFormat->sampleOrder)
  489. || (pipeFormat.rowBitAlign != pFormat->rowBitAlign))) {
  490. if (doSubsample)
  491. goto CantConvert; /* cant upsample - subsampled before */
  492. if (!_ilUpsampleYCbCr (pipe, &info, &pipeDes, &pipeFormat, FALSE, TRUE))
  493. return FALSE;
  494. }
  495. /* If doConvert, then pipe image does not have desired # of bits/sample.
  496. Check if all planes have same # src, dst bits; else can't convert.
  497. Currently can convert 4->8 or 8->4.
  498. */
  499. if (doConvert) {
  500. int nSrcBits, nDstBits;
  501. if ((pipeDes.nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
  502. goto CantConvert;
  503. nSrcBits = pipeFormat.nBitsPerSample[0];
  504. nDstBits = pFormat->nBitsPerSample[0];
  505. for (sample = 1; sample < pDes->nSamplesPerPixel; sample++)
  506. if ((nSrcBits != pipeFormat.nBitsPerSample[sample])
  507. || (nDstBits != pFormat->nBitsPerSample[sample]))
  508. goto CantConvert; /* not same # src,dst bits each plane */
  509. if ((nSrcBits == 4) && (nDstBits == 8)) {
  510. if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat4To8Bit))
  511. return FALSE;
  512. }
  513. else if ((nSrcBits == 8) && (nDstBits == 4)) {
  514. if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8To4Bit))
  515. return FALSE;
  516. }
  517. else goto CantConvert;
  518. }
  519. /* Change sample order: only handles 3 samples, each 8 bits. */
  520. if (pipeFormat.sampleOrder != pFormat->sampleOrder) {
  521. if ((pipeDes.nSamplesPerPixel != 3)
  522. || (pipeFormat.nBitsPerSample[0] != 8)
  523. || (pipeFormat.nBitsPerSample[1] != 8)
  524. || (pipeFormat.nBitsPerSample[2] != 8))
  525. goto CantConvert;
  526. if (pipeFormat.sampleOrder == IL_SAMPLE_PIXELS) {
  527. if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PixelToPlane))
  528. return FALSE;
  529. }
  530. else if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormat8Bit3PlaneToPixel))
  531. return FALSE;
  532. }
  533. if (pipeFormat.rowBitAlign != pFormat->rowBitAlign) {
  534. if (!ilAddFormatFilter (pipe, &info, pFormat, &_ilFormatRowBitAlign))
  535. return FALSE;
  536. }
  537. }
  538. /* Succesful conversion.
  539. */
  540. pipe->context->error = IL_OK;
  541. return TRUE; /* EXIT */
  542. /* GOTO point for when conversion not supported.
  543. */
  544. CantConvert:
  545. ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
  546. return FALSE;
  547. }
  548. #ifdef NOTDEF
  549. IN PROGRESS - NOT DONE YET !!!!!!!!!!
  550. /* ------------------------ ilCheckPipeFormat --------------------------------- */
  551. /* Return an IL_CPF_? code for the current pipe image format, or
  552. IL_CPF_ERROR if error or can't match formats in "formatMask".
  553. The pipe info, des and/or format are returned to non-null
  554. pInfo/Des/Format if IL_CPF_ERROR not returned.
  555. */
  556. unsigned int ilCheckPipeFormat (
  557. ilPipe pipe,
  558. register unsigned long formatMask,
  559. ilPipeInfo *pInfo, /* RETURNED */
  560. register ilImageDes *pDes, /* RETURNED */
  561. register ilImageFormat *pFormat /* RETURNED */
  562. )
  563. {
  564. ilPipeInfo localInfo;
  565. ilImageDes localDes;
  566. ilImageFormat localFormat;
  567. /* Point pInfo/Des/Format to local structs if caller passed NULL */
  568. if (!pInfo) pInfo = &localInfo;
  569. if (!pDes) pDes = &localDes;
  570. if (!pFormat) pFormat = &localFormat;
  571. /* Get pipe info and decompress; if pipe not in IL_PIPE_FORMING state: error. */
  572. if (ilGetPipeInfo (pipe, TRUE, pInfo, pDes, pFormat) != IL_PIPE_FORMING) {
  573. if (!pipe->context->error)
  574. ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
  575. return IL_CPF_ERROR;
  576. }
  577. /* Look at des, format and try to match/convert to format(s) caller accepts */
  578. if (pDes->nSamplesPerPixel == 1) {
  579. /* 1 sample/pixel: if bit/pixel and caller accepts, check rowBitAlign */
  580. if ((formatMask & IL_CPF_BIT) && (pFormat->nBitsPerSample[0] == 1)) {
  581. if (pFormat->rowBitAlign != 32) {
  582. pFormat->rowBitAlign = 32;
  583. if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormatRowBitAlign))
  584. return IL_CPF_ERROR;
  585. return IL_CPF_BIT; /* match found: bit/pixel */
  586. }
  587. }
  588. else {
  589. /* 1 sample, bit not accepted; error if byte not accepted, make byte */
  590. if (!(formatMask & IL_CPF_BYTE))
  591. return IL_CPF_ERROR;
  592. if (pFormat->nBitsPerSample[0] != 8) {
  593. if (pFormat->nBitsPerSample[0] == 4) {
  594. pFormat->nBitsPerSample[0] = 8;
  595. if (!ilAddFormatFilter (pipe, pInfo, pFormat, &ilFormat4To8Bit))
  596. return IL_CPF_ERROR;
  597. }
  598. else return IL_CPF_ERROR; /* NOTE!! currently only 4-8 supported!!! */
  599. }
  600. return IL_CPF_BYTE; /* match found: 1 byte/pixel */
  601. }
  602. } /* END 1 sample/pixel */
  603. else { /* multi-sample/pixel */
  604. }
  605. }
  606. #endif