2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: ilmirror.c /main/4 1996/01/08 12:16:48 lehors $ */
24 /* =============================================================================================================================
26 /ilc/ilmirror.c : Images Library mirror routines.
30 Date Mail-ID Description
31 -------- ----------- -------------------------------------------------------------------
32 07/11/91 larsson Initial Coding.
36 ============================================================================================================================= */
39 #include "ilpipelem.h"
45 #define LEFT_BIT_ON 0x80000000
48 /* Table of bytes with equivalent bits flipped, in /ilc/ilrotate.c */
49 extern const unsigned char ilBitReverseTable [];
53 int illinecount; /* running line count as pipe strips are executed */
54 int ilMirrorheight; /* src height value saved to avoid strip sizes */
55 } ilMirrorPriv, *ilMirrorPrivptr;
59 /* =============================================================================================================================
60 ============================================================================================================================= */
63 static ilError ilMirrorInit(
64 ilMirrorPrivptr pPrivate,
65 ilImageInfo *pSrcImage,
66 ilImageInfo *pDstImage
70 register unsigned char *pdstline;
71 ilImagePlaneInfo *pplane;
74 /* Initialize counters */
76 pPrivate->illinecount = 1;
78 /* Zero out destination memory for bitonal format handling */
79 pplane = &pDstImage->plane[0];
80 pdstline = (unsigned char *) (pplane->pPixels);
82 bzero((char *)pdstline, (pplane->nBytesPerRow * pPrivate->ilMirrorheight) );
88 /* =============================================================================================================================
90 ilMirrorXBitonalExecute - Vertical mirroring for images with bit per pixel format .
92 ============================================================================================================================= */
93 static ilError ilMirrorXBitonalExecute (
94 register ilExecuteData *pData,
95 unsigned long dstLine,
96 unsigned long *pNLines
101 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
102 ilImagePlaneInfo *pplane;
103 register int x, y, lastcount, srcnbytes, dstnbytes;
104 register ilMirrorPrivptr pPriv;
108 if (*pNLines <= 0) return IL_OK;
110 pplane = &pData->pSrcImage->plane[0];
111 srcnbytes = pplane->nBytesPerRow;
112 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;
121 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
123 lastcount = pPriv->illinecount - 1;
124 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
127 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
128 for ( x = 0; x < srcnbytes; x++) *pdst++ = *psrc++;
129 psrcline += srcnbytes;
134 /* No. of lines written is the destination height */
135 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
136 else *pNLines = pPriv->ilMirrorheight;
143 /* =============================================================================================================================
145 ilMirrorYBitonalExecute - Horizontal mirroring for images with bit per pixel format .
147 ============================================================================================================================= */
148 static ilError ilMirrorYBitonalExecute (
149 register ilExecuteData *pData,
150 unsigned long dstLine,
151 unsigned long *pNLines
156 register unsigned char *psrc, *pdst, *psrcline, *psrcbefore, *pdstline;
157 register unsigned char srcbyte;
158 ilImagePlaneInfo *pplane;
159 register int x, y, lastcount, loffset, roffset;
160 register int srcnbytes, dstnbytes, widthbytes;
161 register ilMirrorPrivptr pPriv;
164 if (*pNLines <= 0) return IL_OK;
166 pplane = &pData->pSrcImage->plane[0];
167 srcnbytes = pplane->nBytesPerRow;
168 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
170 pplane = &pData->pDstImage->plane[0];
171 dstnbytes = pplane->nBytesPerRow;
172 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
173 pPriv = (ilMirrorPrivptr) pData->pPrivate;
176 loffset = pData->pSrcImage->width % BYTESIZE;
177 roffset = BYTESIZE - loffset;
178 widthbytes = pData->pSrcImage->width / BYTESIZE;
179 if ( loffset > 0 ) widthbytes++;
182 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
184 lastcount = pPriv->illinecount - 1;
185 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
187 psrc = psrcline + widthbytes - 1;
188 psrcbefore = psrc - 1;
190 pdst = pdstline + (dstnbytes * y);
193 for ( x = 0; x < widthbytes; x++) *pdst++ = ilBitReverseTable[ *psrc-- ];
195 for ( x = 0; x < widthbytes; x++) {
197 if ( psrcbefore < psrcline ) srcbyte = (*psrc >> roffset);
198 else srcbyte = (*psrcbefore << loffset) | (*psrc >> roffset);
200 *pdst++ = ilBitReverseTable[srcbyte];
206 psrcline += srcnbytes;
210 /* No. of lines written is the destination height */
211 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
212 else *pNLines = pPriv->ilMirrorheight;
217 /* =============================================================================================================================
219 ilMirrorX3ByteExecute - Vertical mirroring for images with 24 bits per pixel format .
221 ============================================================================================================================= */
222 static ilError ilMirrorX3ByteExecute (
223 register ilExecuteData *pData,
224 unsigned long dstLine,
225 unsigned long *pNLines
230 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
231 register unsigned long srcnbytes, dstnbytes;
232 ilImagePlaneInfo *pplane;
233 register int x, y, lastcount;
234 register ilMirrorPrivptr pPriv;
237 if (*pNLines <= 0) return IL_OK;
239 pplane = &pData->pSrcImage->plane[0];
240 srcnbytes = pplane->nBytesPerRow;
241 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;
250 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
252 lastcount = pPriv->illinecount - 1;
253 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
257 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
258 for ( x = 0; x < pData->pSrcImage->width; x++) {
263 psrcline += srcnbytes;
268 /* No. of lines written is the destination height */
269 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
270 else *pNLines = pPriv->ilMirrorheight;
276 /* =============================================================================================================================
278 ilMirrorY3ByteExecute - Horizontal mirroring for images with 24 bits per pixel format .
280 ============================================================================================================================= */
281 static ilError ilMirrorY3ByteExecute (
282 register ilExecuteData *pData,
283 unsigned long dstLine,
284 unsigned long *pNLines
289 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
290 register unsigned long srcnbytes, dstnbytes;
291 ilImagePlaneInfo *pplane;
292 register int x, y, xoffset, lastcount;
293 register ilMirrorPrivptr pPriv;
296 if (*pNLines <= 0) return IL_OK;
298 pplane = &pData->pSrcImage->plane[0];
299 srcnbytes = pplane->nBytesPerRow;
300 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
302 pplane = &pData->pDstImage->plane[0];
303 dstnbytes = pplane->nBytesPerRow;
304 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
305 pPriv = (ilMirrorPrivptr) pData->pPrivate;
309 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
311 xoffset = pData->pSrcImage->width * 3;
313 lastcount = pPriv->illinecount - 1;
314 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
318 pdst = pdstline + (dstnbytes * y) + xoffset - 1;
319 for ( x = 0; x < pData->pSrcImage->width; x++, psrc += 5) {
324 psrcline += srcnbytes;
329 /* No. of lines written is the destination height */
330 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
331 else *pNLines = pPriv->ilMirrorheight;
337 /* =============================================================================================================================
339 ilMirrorXByteExecute - Vertical mirroring for images with byte per pixel format .
341 ============================================================================================================================= */
342 static ilError ilMirrorXByteExecute (
343 register ilExecuteData *pData,
344 unsigned long dstLine,
345 unsigned long *pNLines
350 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
351 register unsigned long srcnbytes, dstnbytes;
352 ilImagePlaneInfo *pplane;
353 register int x, y, lastcount;
354 register ilMirrorPrivptr pPriv;
357 if (*pNLines <= 0) return IL_OK;
359 pplane = &pData->pSrcImage->plane[0];
360 srcnbytes = pplane->nBytesPerRow;
361 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
363 pplane = &pData->pDstImage->plane[0];
364 dstnbytes = pplane->nBytesPerRow;
365 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
366 pPriv = (ilMirrorPrivptr) pData->pPrivate;
371 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
373 lastcount = pPriv->illinecount - 1;
374 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
377 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
378 for ( x = 0; x < pData->pSrcImage->width; x++) *pdst++ = *psrc++;
379 psrcline += srcnbytes;
384 /* No. of lines written is the destination height */
385 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
386 else *pNLines = pPriv->ilMirrorheight;
392 /* =============================================================================================================================
394 ilMirrorYByteExecute - Horizontal mirroring for images with byte per pixel format .
396 ============================================================================================================================= */
397 static ilError ilMirrorYByteExecute (
398 register ilExecuteData *pData,
399 unsigned long dstLine,
400 unsigned long *pNLines
405 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
406 register unsigned long srcnbytes, dstnbytes;
407 ilImagePlaneInfo *pplane;
408 register int x, y, lastcount;
409 register ilMirrorPrivptr pPriv;
412 if (*pNLines <= 0) return IL_OK;
414 pplane = &pData->pSrcImage->plane[0];
415 srcnbytes = pplane->nBytesPerRow;
416 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
418 pplane = &pData->pDstImage->plane[0];
419 dstnbytes = pplane->nBytesPerRow;
420 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
421 pPriv = (ilMirrorPrivptr) pData->pPrivate;
426 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
428 lastcount = pPriv->illinecount - 1;
429 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
432 pdst = pdstline + (dstnbytes * y) + srcnbytes - 1;
433 for ( x = 0; x < pData->pSrcImage->width; x++) *pdst-- = *psrc++;
434 psrcline += srcnbytes;
439 /* No. of lines written is the destination height */
440 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
441 else *pNLines = pPriv->ilMirrorheight;
446 /* =============================================================================================================================
448 ilMirror - Add a mirror filter to an existing pipe - checking for format types
449 and doing an explicit conversion if necessary. Direction parameter
450 specifies verticle (MIRRORX) or horizontal (MIRRORY).
453 ============================================================================================================================= */
463 register ilMirrorPrivptr pPriv;
464 ilDstElementData dstdata;
466 ilImageFormat imformat;
473 /* Get ptr to pipe info and check state */
475 state = ilGetPipeInfo(pipe, TRUE, &info, &imdes, &imformat);
476 if(state != IL_PIPE_FORMING) {
477 if (!pipe->context->error)
478 ilDeclarePipeInvalid(pipe, IL_ERROR_PIPE_STATE);
485 /* Check for valid Formats */
487 switch (imdes.nSamplesPerPixel) {
488 case 3: /* RGB or YUV */
489 if(imformat.sampleOrder != IL_SAMPLE_PIXELS) {
490 imformat.sampleOrder = IL_SAMPLE_PIXELS;
494 if((imformat.nBitsPerSample[0] != 8) ||
495 (imformat.nBitsPerSample[1] != 8) ||
496 (imformat.nBitsPerSample[2] != 8)) {
498 imformat.nBitsPerSample[0] = 8;
499 imformat.nBitsPerSample[1] = 8;
500 imformat.nBitsPerSample[2] = 8;
506 switch (imformat.nBitsPerSample[0]) {
507 case 8: /* Byte per pixel */
510 case 1: /* Bitonal */
512 if (imformat.rowBitAlign != 32) {
513 imformat.rowBitAlign = 32;
518 default: /* something other than 1 - try 8 */
519 imformat.nBitsPerSample[0] = 8;
525 return ilDeclarePipeInvalid(pipe, IL_ERROR_NOT_IMPLEMENTED);
530 if (!ilConvert(pipe, &imdes, &imformat, 0, NULL))
532 ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
536 /* if invalid direction flag as an error */
537 if ((direction != IL_MIRRORX) && (direction != IL_MIRRORY))
538 return ilDeclarePipeInvalid(pipe, IL_ERROR_INVALID_OPTION);
540 dstdata.producerObject = (ilObject) NULL;
541 dstdata.pDes = (ilImageDes *) NULL;
542 dstdata.pFormat = (ilImageFormat *) NULL;
543 dstdata.pPalette = info.pPalette;
545 dstdata.width = info.width;
546 dstdata.height = info.height;
548 /* set output strip height */
549 dstdata.stripHeight = dstdata.height;
550 dstdata.constantStrip = TRUE;
553 switch (imdes.nSamplesPerPixel) {
557 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
558 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorX3ByteExecute, 0);
561 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
562 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorY3ByteExecute, 0);
570 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
571 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXBitonalExecute, 0);
574 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
575 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYBitonalExecute, 0);
581 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
582 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXByteExecute, 0);
585 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
586 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYByteExecute, 0);
595 /* Save away true height */
596 pPriv->ilMirrorheight = info.height;
598 pipe->context->error = IL_OK;