ilmirror.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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: ilmirror.c /main/4 1996/01/08 12:16:48 lehors $ */
  24. /* =============================================================================================================================
  25. /ilc/ilmirror.c : Images Library mirror routines.
  26. Date Mail-ID Description
  27. -------- ----------- -------------------------------------------------------------------
  28. 07/11/91 larsson Initial Coding.
  29. ============================================================================================================================= */
  30. #include "ilint.h"
  31. #include "ilpipelem.h"
  32. #include "ilerrors.h"
  33. #define LONGSZ 4
  34. #define WORDPOS 32
  35. #define BYTESIZE 8
  36. #define LEFT_BIT_ON 0x80000000
  37. /* Table of bytes with equivalent bits flipped, in /ilc/ilrotate.c */
  38. extern const unsigned char ilBitReverseTable [];
  39. typedef struct {
  40. int illinecount; /* running line count as pipe strips are executed */
  41. int ilMirrorheight; /* src height value saved to avoid strip sizes */
  42. } ilMirrorPriv, *ilMirrorPrivptr;
  43. /* =============================================================================================================================
  44. ============================================================================================================================= */
  45. static ilError ilMirrorInit(
  46. ilMirrorPrivptr pPrivate,
  47. ilImageInfo *pSrcImage,
  48. ilImageInfo *pDstImage
  49. )
  50. {
  51. unsigned char *pdstline;
  52. ilImagePlaneInfo *pplane;
  53. /* Initialize counters */
  54. pPrivate->illinecount = 1;
  55. /* Zero out destination memory for bitonal format handling */
  56. pplane = &pDstImage->plane[0];
  57. pdstline = (unsigned char *) (pplane->pPixels);
  58. bzero((char *)pdstline, (pplane->nBytesPerRow * pPrivate->ilMirrorheight) );
  59. return IL_OK;
  60. }
  61. /* =============================================================================================================================
  62. ilMirrorXBitonalExecute - Vertical mirroring for images with bit per pixel format .
  63. ============================================================================================================================= */
  64. static ilError ilMirrorXBitonalExecute (
  65. ilExecuteData *pData,
  66. unsigned long dstLine,
  67. unsigned long *pNLines
  68. )
  69. {
  70. unsigned char *psrc, *pdst, *psrcline, *pdstline;
  71. ilImagePlaneInfo *pplane;
  72. int x, y, lastcount, srcnbytes, dstnbytes;
  73. ilMirrorPrivptr pPriv;
  74. if (*pNLines <= 0) return IL_OK;
  75. pplane = &pData->pSrcImage->plane[0];
  76. srcnbytes = pplane->nBytesPerRow;
  77. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  78. pplane = &pData->pDstImage->plane[0];
  79. dstnbytes = pplane->nBytesPerRow;
  80. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  81. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  82. /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
  83. lastcount = pPriv->illinecount - 1;
  84. for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  85. psrc = psrcline;
  86. pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
  87. for ( x = 0; x < srcnbytes; x++) *pdst++ = *psrc++;
  88. psrcline += srcnbytes;
  89. }
  90. /* No. of lines written is the destination height */
  91. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  92. else *pNLines = pPriv->ilMirrorheight;
  93. return IL_OK;
  94. }
  95. /* =============================================================================================================================
  96. ilMirrorYBitonalExecute - Horizontal mirroring for images with bit per pixel format .
  97. ============================================================================================================================= */
  98. static ilError ilMirrorYBitonalExecute (
  99. ilExecuteData *pData,
  100. unsigned long dstLine,
  101. unsigned long *pNLines
  102. )
  103. {
  104. unsigned char *psrc, *pdst, *psrcline, *psrcbefore, *pdstline;
  105. unsigned char srcbyte;
  106. ilImagePlaneInfo *pplane;
  107. int x, y, lastcount, loffset, roffset;
  108. int srcnbytes, dstnbytes, widthbytes;
  109. ilMirrorPrivptr pPriv;
  110. if (*pNLines <= 0) return IL_OK;
  111. pplane = &pData->pSrcImage->plane[0];
  112. srcnbytes = pplane->nBytesPerRow;
  113. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  114. pplane = &pData->pDstImage->plane[0];
  115. dstnbytes = pplane->nBytesPerRow;
  116. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  117. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  118. loffset = pData->pSrcImage->width % BYTESIZE;
  119. roffset = BYTESIZE - loffset;
  120. widthbytes = pData->pSrcImage->width / BYTESIZE;
  121. if ( loffset > 0 ) widthbytes++;
  122. /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
  123. lastcount = pPriv->illinecount - 1;
  124. for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  125. psrc = psrcline + widthbytes - 1;
  126. psrcbefore = psrc - 1;
  127. pdst = pdstline + (dstnbytes * y);
  128. if ( loffset == 0 )
  129. for ( x = 0; x < widthbytes; x++) *pdst++ = ilBitReverseTable[ *psrc-- ];
  130. else {
  131. for ( x = 0; x < widthbytes; x++) {
  132. if ( psrcbefore < psrcline ) srcbyte = (*psrc >> roffset);
  133. else srcbyte = (*psrcbefore << loffset) | (*psrc >> roffset);
  134. *pdst++ = ilBitReverseTable[srcbyte];
  135. psrc--;
  136. psrcbefore--;
  137. }
  138. }
  139. psrcline += srcnbytes;
  140. }
  141. /* No. of lines written is the destination height */
  142. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  143. else *pNLines = pPriv->ilMirrorheight;
  144. return IL_OK;
  145. }
  146. /* =============================================================================================================================
  147. ilMirrorX3ByteExecute - Vertical mirroring for images with 24 bits per pixel format .
  148. ============================================================================================================================= */
  149. static ilError ilMirrorX3ByteExecute (
  150. ilExecuteData *pData,
  151. unsigned long dstLine,
  152. unsigned long *pNLines
  153. )
  154. {
  155. unsigned char *psrc, *pdst, *psrcline, *pdstline;
  156. unsigned long srcnbytes, dstnbytes;
  157. ilImagePlaneInfo *pplane;
  158. int x, y, lastcount;
  159. ilMirrorPrivptr pPriv;
  160. if (*pNLines <= 0) return IL_OK;
  161. pplane = &pData->pSrcImage->plane[0];
  162. srcnbytes = pplane->nBytesPerRow;
  163. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  164. pplane = &pData->pDstImage->plane[0];
  165. dstnbytes = pplane->nBytesPerRow;
  166. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  167. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  168. /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
  169. lastcount = pPriv->illinecount - 1;
  170. for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  171. psrc = psrcline;
  172. pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
  173. for ( x = 0; x < pData->pSrcImage->width; x++) {
  174. *pdst++ = *psrc++;
  175. *pdst++ = *psrc++;
  176. *pdst++ = *psrc++;
  177. }
  178. psrcline += srcnbytes;
  179. }
  180. /* No. of lines written is the destination height */
  181. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  182. else *pNLines = pPriv->ilMirrorheight;
  183. return IL_OK;
  184. }
  185. /* =============================================================================================================================
  186. ilMirrorY3ByteExecute - Horizontal mirroring for images with 24 bits per pixel format .
  187. ============================================================================================================================= */
  188. static ilError ilMirrorY3ByteExecute (
  189. ilExecuteData *pData,
  190. unsigned long dstLine,
  191. unsigned long *pNLines
  192. )
  193. {
  194. unsigned char *psrc, *pdst, *psrcline, *pdstline;
  195. unsigned long srcnbytes, dstnbytes;
  196. ilImagePlaneInfo *pplane;
  197. int x, y, xoffset, lastcount;
  198. ilMirrorPrivptr pPriv;
  199. if (*pNLines <= 0) return IL_OK;
  200. pplane = &pData->pSrcImage->plane[0];
  201. srcnbytes = pplane->nBytesPerRow;
  202. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  203. pplane = &pData->pDstImage->plane[0];
  204. dstnbytes = pplane->nBytesPerRow;
  205. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  206. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  207. /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
  208. xoffset = pData->pSrcImage->width * 3;
  209. lastcount = pPriv->illinecount - 1;
  210. for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  211. psrc = psrcline + 2;
  212. pdst = pdstline + (dstnbytes * y) + xoffset - 1;
  213. for ( x = 0; x < pData->pSrcImage->width; x++, psrc += 5) {
  214. *pdst-- = *psrc--;
  215. *pdst-- = *psrc--;
  216. *pdst-- = *psrc;
  217. }
  218. psrcline += srcnbytes;
  219. }
  220. /* No. of lines written is the destination height */
  221. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  222. else *pNLines = pPriv->ilMirrorheight;
  223. return IL_OK;
  224. }
  225. /* =============================================================================================================================
  226. ilMirrorXByteExecute - Vertical mirroring for images with byte per pixel format .
  227. ============================================================================================================================= */
  228. static ilError ilMirrorXByteExecute (
  229. ilExecuteData *pData,
  230. unsigned long dstLine,
  231. unsigned long *pNLines
  232. )
  233. {
  234. unsigned char *psrc, *pdst, *psrcline, *pdstline;
  235. unsigned long srcnbytes, dstnbytes;
  236. ilImagePlaneInfo *pplane;
  237. int x, y, lastcount;
  238. ilMirrorPrivptr pPriv;
  239. if (*pNLines <= 0) return IL_OK;
  240. pplane = &pData->pSrcImage->plane[0];
  241. srcnbytes = pplane->nBytesPerRow;
  242. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  243. pplane = &pData->pDstImage->plane[0];
  244. dstnbytes = pplane->nBytesPerRow;
  245. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  246. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  247. /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
  248. lastcount = pPriv->illinecount - 1;
  249. for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  250. psrc = psrcline;
  251. pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
  252. for ( x = 0; x < pData->pSrcImage->width; x++) *pdst++ = *psrc++;
  253. psrcline += srcnbytes;
  254. }
  255. /* No. of lines written is the destination height */
  256. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  257. else *pNLines = pPriv->ilMirrorheight;
  258. return IL_OK;
  259. }
  260. /* =============================================================================================================================
  261. ilMirrorYByteExecute - Horizontal mirroring for images with byte per pixel format .
  262. ============================================================================================================================= */
  263. static ilError ilMirrorYByteExecute (
  264. ilExecuteData *pData,
  265. unsigned long dstLine,
  266. unsigned long *pNLines
  267. )
  268. {
  269. unsigned char *psrc, *pdst, *psrcline, *pdstline;
  270. unsigned long srcnbytes, dstnbytes;
  271. ilImagePlaneInfo *pplane;
  272. int x, y, lastcount;
  273. ilMirrorPrivptr pPriv;
  274. if (*pNLines <= 0) return IL_OK;
  275. pplane = &pData->pSrcImage->plane[0];
  276. srcnbytes = pplane->nBytesPerRow;
  277. psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
  278. pplane = &pData->pDstImage->plane[0];
  279. dstnbytes = pplane->nBytesPerRow;
  280. pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
  281. pPriv = (ilMirrorPrivptr) pData->pPrivate;
  282. /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
  283. lastcount = pPriv->illinecount - 1;
  284. for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
  285. psrc = psrcline;
  286. pdst = pdstline + (dstnbytes * y) + srcnbytes - 1;
  287. for ( x = 0; x < pData->pSrcImage->width; x++) *pdst-- = *psrc++;
  288. psrcline += srcnbytes;
  289. }
  290. /* No. of lines written is the destination height */
  291. if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
  292. else *pNLines = pPriv->ilMirrorheight;
  293. return IL_OK;
  294. }
  295. /* =============================================================================================================================
  296. ilMirror - Add a mirror filter to an existing pipe - checking for format types
  297. and doing an explicit conversion if necessary. Direction parameter
  298. specifies verticle (MIRRORX) or horizontal (MIRRORY).
  299. ============================================================================================================================= */
  300. ilBool ilMirror (
  301. ilPipe pipe,
  302. int direction
  303. )
  304. {
  305. unsigned int state;
  306. ilPipeInfo info;
  307. ilMirrorPrivptr pPriv;
  308. ilDstElementData dstdata;
  309. ilImageDes imdes;
  310. ilImageFormat imformat;
  311. ilBool convert;
  312. ilBool bitonal;
  313. ilBool cw;
  314. unsigned int rtype;
  315. /* Get ptr to pipe info and check state */
  316. state = ilGetPipeInfo(pipe, TRUE, &info, &imdes, &imformat);
  317. if(state != IL_PIPE_FORMING) {
  318. if (!pipe->context->error)
  319. ilDeclarePipeInvalid(pipe, IL_ERROR_PIPE_STATE);
  320. return FALSE;
  321. }
  322. bitonal = FALSE;
  323. /* Check for valid Formats */
  324. convert = FALSE;
  325. switch (imdes.nSamplesPerPixel) {
  326. case 3: /* RGB or YUV */
  327. if(imformat.sampleOrder != IL_SAMPLE_PIXELS) {
  328. imformat.sampleOrder = IL_SAMPLE_PIXELS;
  329. convert = TRUE;
  330. }
  331. if((imformat.nBitsPerSample[0] != 8) ||
  332. (imformat.nBitsPerSample[1] != 8) ||
  333. (imformat.nBitsPerSample[2] != 8)) {
  334. imformat.nBitsPerSample[0] = 8;
  335. imformat.nBitsPerSample[1] = 8;
  336. imformat.nBitsPerSample[2] = 8;
  337. convert = TRUE;
  338. }
  339. break;
  340. case 1:
  341. switch (imformat.nBitsPerSample[0]) {
  342. case 8: /* Byte per pixel */
  343. break;
  344. case 1: /* Bitonal */
  345. bitonal = TRUE;
  346. if (imformat.rowBitAlign != 32) {
  347. imformat.rowBitAlign = 32;
  348. convert = TRUE;
  349. }
  350. break;
  351. default: /* something other than 1 - try 8 */
  352. imformat.nBitsPerSample[0] = 8;
  353. convert = TRUE;
  354. }
  355. break;
  356. default:
  357. return ilDeclarePipeInvalid(pipe, IL_ERROR_NOT_IMPLEMENTED);
  358. }
  359. if(convert) {
  360. if (!ilConvert(pipe, &imdes, &imformat, 0, NULL))
  361. return FALSE;
  362. ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
  363. }
  364. /* if invalid direction flag as an error */
  365. if ((direction != IL_MIRRORX) && (direction != IL_MIRRORY))
  366. return ilDeclarePipeInvalid(pipe, IL_ERROR_INVALID_OPTION);
  367. dstdata.producerObject = (ilObject) NULL;
  368. dstdata.pDes = (ilImageDes *) NULL;
  369. dstdata.pFormat = (ilImageFormat *) NULL;
  370. dstdata.pPalette = info.pPalette;
  371. dstdata.width = info.width;
  372. dstdata.height = info.height;
  373. /* set output strip height */
  374. dstdata.stripHeight = dstdata.height;
  375. dstdata.constantStrip = TRUE;
  376. switch (imdes.nSamplesPerPixel) {
  377. case 3:
  378. switch (direction) {
  379. case IL_MIRRORX:
  380. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  381. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorX3ByteExecute, 0);
  382. break;
  383. case IL_MIRRORY:
  384. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  385. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorY3ByteExecute, 0);
  386. }
  387. break;
  388. case 1:
  389. if(bitonal) {
  390. switch (direction) {
  391. case IL_MIRRORX:
  392. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  393. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXBitonalExecute, 0);
  394. break;
  395. case IL_MIRRORY:
  396. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  397. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYBitonalExecute, 0);
  398. }
  399. }
  400. else {
  401. switch (direction) {
  402. case IL_MIRRORX:
  403. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  404. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXByteExecute, 0);
  405. break;
  406. case IL_MIRRORY:
  407. pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
  408. &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYByteExecute, 0);
  409. }
  410. }
  411. }
  412. if(!pPriv)
  413. return FALSE;
  414. /* Save away true height */
  415. pPriv->ilMirrorheight = info.height;
  416. pipe->context->error = IL_OK;
  417. return TRUE;
  418. }