1 /* $XConsortium: ilmirror.c /main/4 1996/01/08 12:16:48 lehors $ */
2 /* =============================================================================================================================
4 /ilc/ilmirror.c : Images Library mirror routines.
8 Date Mail-ID Description
9 -------- ----------- -------------------------------------------------------------------
10 07/11/91 larsson Initial Coding.
14 ============================================================================================================================= */
17 #include "ilpipelem.h"
23 #define LEFT_BIT_ON 0x80000000
26 /* Table of bytes with equivalent bits flipped, in /ilc/ilrotate.c */
27 extern const unsigned char ilBitReverseTable [];
31 int illinecount; /* running line count as pipe strips are executed */
32 int ilMirrorheight; /* src height value saved to avoid strip sizes */
33 } ilMirrorPriv, *ilMirrorPrivptr;
37 /* =============================================================================================================================
38 ============================================================================================================================= */
41 static ilError ilMirrorInit(
42 ilMirrorPrivptr pPrivate,
43 ilImageInfo *pSrcImage,
44 ilImageInfo *pDstImage
48 register unsigned char *pdstline;
49 ilImagePlaneInfo *pplane;
52 /* Initialize counters */
54 pPrivate->illinecount = 1;
56 /* Zero out destination memory for bitonal format handling */
57 pplane = &pDstImage->plane[0];
58 pdstline = (unsigned char *) (pplane->pPixels);
60 bzero((char *)pdstline, (pplane->nBytesPerRow * pPrivate->ilMirrorheight) );
66 /* =============================================================================================================================
68 ilMirrorXBitonalExecute - Vertical mirroring for images with bit per pixel format .
70 ============================================================================================================================= */
71 static ilError ilMirrorXBitonalExecute (
72 register ilExecuteData *pData,
73 unsigned long dstLine,
74 unsigned long *pNLines
79 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
80 ilImagePlaneInfo *pplane;
81 register int x, y, lastcount, srcnbytes, dstnbytes;
82 register ilMirrorPrivptr pPriv;
86 if (*pNLines <= 0) return IL_OK;
88 pplane = &pData->pSrcImage->plane[0];
89 srcnbytes = pplane->nBytesPerRow;
90 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
92 pplane = &pData->pDstImage->plane[0];
93 dstnbytes = pplane->nBytesPerRow;
94 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
95 pPriv = (ilMirrorPrivptr) pData->pPrivate;
99 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
101 lastcount = pPriv->illinecount - 1;
102 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
105 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
106 for ( x = 0; x < srcnbytes; x++) *pdst++ = *psrc++;
107 psrcline += srcnbytes;
112 /* No. of lines written is the destination height */
113 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
114 else *pNLines = pPriv->ilMirrorheight;
121 /* =============================================================================================================================
123 ilMirrorYBitonalExecute - Horizontal mirroring for images with bit per pixel format .
125 ============================================================================================================================= */
126 static ilError ilMirrorYBitonalExecute (
127 register ilExecuteData *pData,
128 unsigned long dstLine,
129 unsigned long *pNLines
134 register unsigned char *psrc, *pdst, *psrcline, *psrcbefore, *pdstline;
135 register unsigned char srcbyte;
136 ilImagePlaneInfo *pplane;
137 register int x, y, lastcount, loffset, roffset;
138 register int srcnbytes, dstnbytes, widthbytes;
139 register ilMirrorPrivptr pPriv;
142 if (*pNLines <= 0) return IL_OK;
144 pplane = &pData->pSrcImage->plane[0];
145 srcnbytes = pplane->nBytesPerRow;
146 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
148 pplane = &pData->pDstImage->plane[0];
149 dstnbytes = pplane->nBytesPerRow;
150 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
151 pPriv = (ilMirrorPrivptr) pData->pPrivate;
154 loffset = pData->pSrcImage->width % BYTESIZE;
155 roffset = BYTESIZE - loffset;
156 widthbytes = pData->pSrcImage->width / BYTESIZE;
157 if ( loffset > 0 ) widthbytes++;
160 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
162 lastcount = pPriv->illinecount - 1;
163 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
165 psrc = psrcline + widthbytes - 1;
166 psrcbefore = psrc - 1;
168 pdst = pdstline + (dstnbytes * y);
171 for ( x = 0; x < widthbytes; x++) *pdst++ = ilBitReverseTable[ *psrc-- ];
173 for ( x = 0; x < widthbytes; x++) {
175 if ( psrcbefore < psrcline ) srcbyte = (*psrc >> roffset);
176 else srcbyte = (*psrcbefore << loffset) | (*psrc >> roffset);
178 *pdst++ = ilBitReverseTable[srcbyte];
184 psrcline += srcnbytes;
188 /* No. of lines written is the destination height */
189 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
190 else *pNLines = pPriv->ilMirrorheight;
195 /* =============================================================================================================================
197 ilMirrorX3ByteExecute - Vertical mirroring for images with 24 bits per pixel format .
199 ============================================================================================================================= */
200 static ilError ilMirrorX3ByteExecute (
201 register ilExecuteData *pData,
202 unsigned long dstLine,
203 unsigned long *pNLines
208 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
209 register unsigned long srcnbytes, dstnbytes;
210 ilImagePlaneInfo *pplane;
211 register int x, y, lastcount;
212 register ilMirrorPrivptr pPriv;
215 if (*pNLines <= 0) return IL_OK;
217 pplane = &pData->pSrcImage->plane[0];
218 srcnbytes = pplane->nBytesPerRow;
219 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
221 pplane = &pData->pDstImage->plane[0];
222 dstnbytes = pplane->nBytesPerRow;
223 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
224 pPriv = (ilMirrorPrivptr) pData->pPrivate;
228 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
230 lastcount = pPriv->illinecount - 1;
231 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
235 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
236 for ( x = 0; x < pData->pSrcImage->width; x++) {
241 psrcline += srcnbytes;
246 /* No. of lines written is the destination height */
247 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
248 else *pNLines = pPriv->ilMirrorheight;
254 /* =============================================================================================================================
256 ilMirrorY3ByteExecute - Horizontal mirroring for images with 24 bits per pixel format .
258 ============================================================================================================================= */
259 static ilError ilMirrorY3ByteExecute (
260 register ilExecuteData *pData,
261 unsigned long dstLine,
262 unsigned long *pNLines
267 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
268 register unsigned long srcnbytes, dstnbytes;
269 ilImagePlaneInfo *pplane;
270 register int x, y, xoffset, lastcount;
271 register ilMirrorPrivptr pPriv;
274 if (*pNLines <= 0) return IL_OK;
276 pplane = &pData->pSrcImage->plane[0];
277 srcnbytes = pplane->nBytesPerRow;
278 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
280 pplane = &pData->pDstImage->plane[0];
281 dstnbytes = pplane->nBytesPerRow;
282 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
283 pPriv = (ilMirrorPrivptr) pData->pPrivate;
287 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
289 xoffset = pData->pSrcImage->width * 3;
291 lastcount = pPriv->illinecount - 1;
292 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
296 pdst = pdstline + (dstnbytes * y) + xoffset - 1;
297 for ( x = 0; x < pData->pSrcImage->width; x++, psrc += 5) {
302 psrcline += srcnbytes;
307 /* No. of lines written is the destination height */
308 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
309 else *pNLines = pPriv->ilMirrorheight;
315 /* =============================================================================================================================
317 ilMirrorXByteExecute - Vertical mirroring for images with byte per pixel format .
319 ============================================================================================================================= */
320 static ilError ilMirrorXByteExecute (
321 register ilExecuteData *pData,
322 unsigned long dstLine,
323 unsigned long *pNLines
328 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
329 register unsigned long srcnbytes, dstnbytes;
330 ilImagePlaneInfo *pplane;
331 register int x, y, lastcount;
332 register ilMirrorPrivptr pPriv;
335 if (*pNLines <= 0) return IL_OK;
337 pplane = &pData->pSrcImage->plane[0];
338 srcnbytes = pplane->nBytesPerRow;
339 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
341 pplane = &pData->pDstImage->plane[0];
342 dstnbytes = pplane->nBytesPerRow;
343 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
344 pPriv = (ilMirrorPrivptr) pData->pPrivate;
349 /* Mirror vertically map (x,y) to (x, -y) about its center [ x, height-y ] */
351 lastcount = pPriv->illinecount - 1;
352 for (y = pPriv->illinecount; y <= (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
355 pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
356 for ( x = 0; x < pData->pSrcImage->width; x++) *pdst++ = *psrc++;
357 psrcline += srcnbytes;
362 /* No. of lines written is the destination height */
363 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
364 else *pNLines = pPriv->ilMirrorheight;
370 /* =============================================================================================================================
372 ilMirrorYByteExecute - Horizontal mirroring for images with byte per pixel format .
374 ============================================================================================================================= */
375 static ilError ilMirrorYByteExecute (
376 register ilExecuteData *pData,
377 unsigned long dstLine,
378 unsigned long *pNLines
383 register unsigned char *psrc, *pdst, *psrcline, *pdstline;
384 register unsigned long srcnbytes, dstnbytes;
385 ilImagePlaneInfo *pplane;
386 register int x, y, lastcount;
387 register ilMirrorPrivptr pPriv;
390 if (*pNLines <= 0) return IL_OK;
392 pplane = &pData->pSrcImage->plane[0];
393 srcnbytes = pplane->nBytesPerRow;
394 psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
396 pplane = &pData->pDstImage->plane[0];
397 dstnbytes = pplane->nBytesPerRow;
398 pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
399 pPriv = (ilMirrorPrivptr) pData->pPrivate;
404 /* Mirror horizontally map (x,y) to (-x, y) about its center [ width-x, y ] */
406 lastcount = pPriv->illinecount - 1;
407 for (y = lastcount; y < (lastcount + *pNLines); y++, pPriv->illinecount++ ) {
410 pdst = pdstline + (dstnbytes * y) + srcnbytes - 1;
411 for ( x = 0; x < pData->pSrcImage->width; x++) *pdst-- = *psrc++;
412 psrcline += srcnbytes;
417 /* No. of lines written is the destination height */
418 if ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
419 else *pNLines = pPriv->ilMirrorheight;
424 /* =============================================================================================================================
426 ilMirror - Add a mirror filter to an existing pipe - checking for format types
427 and doing an explicit conversion if necessary. Direction parameter
428 specifies verticle (MIRRORX) or horizontal (MIRRORY).
431 ============================================================================================================================= */
441 register ilMirrorPrivptr pPriv;
442 ilDstElementData dstdata;
444 ilImageFormat imformat;
451 /* Get ptr to pipe info and check state */
453 state = ilGetPipeInfo(pipe, TRUE, &info, &imdes, &imformat);
454 if(state != IL_PIPE_FORMING) {
455 if (!pipe->context->error)
456 ilDeclarePipeInvalid(pipe, IL_ERROR_PIPE_STATE);
463 /* Check for valid Formats */
465 switch (imdes.nSamplesPerPixel) {
466 case 3: /* RGB or YUV */
467 if(imformat.sampleOrder != IL_SAMPLE_PIXELS) {
468 imformat.sampleOrder = IL_SAMPLE_PIXELS;
472 if((imformat.nBitsPerSample[0] != 8) ||
473 (imformat.nBitsPerSample[1] != 8) ||
474 (imformat.nBitsPerSample[2] != 8)) {
476 imformat.nBitsPerSample[0] = 8;
477 imformat.nBitsPerSample[1] = 8;
478 imformat.nBitsPerSample[2] = 8;
484 switch (imformat.nBitsPerSample[0]) {
485 case 8: /* Byte per pixel */
488 case 1: /* Bitonal */
490 if (imformat.rowBitAlign != 32) {
491 imformat.rowBitAlign = 32;
496 default: /* something other than 1 - try 8 */
497 imformat.nBitsPerSample[0] = 8;
503 return ilDeclarePipeInvalid(pipe, IL_ERROR_NOT_IMPLEMENTED);
508 if (!ilConvert(pipe, &imdes, &imformat, 0, NULL))
510 ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
514 /* if invalid direction flag as an error */
515 if ((direction != IL_MIRRORX) && (direction != IL_MIRRORY))
516 return ilDeclarePipeInvalid(pipe, IL_ERROR_INVALID_OPTION);
518 dstdata.producerObject = (ilObject) NULL;
519 dstdata.pDes = (ilImageDes *) NULL;
520 dstdata.pFormat = (ilImageFormat *) NULL;
521 dstdata.pPalette = info.pPalette;
523 dstdata.width = info.width;
524 dstdata.height = info.height;
526 /* set output strip height */
527 dstdata.stripHeight = dstdata.height;
528 dstdata.constantStrip = TRUE;
531 switch (imdes.nSamplesPerPixel) {
535 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
536 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorX3ByteExecute, 0);
539 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
540 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorY3ByteExecute, 0);
548 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
549 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXBitonalExecute, 0);
552 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
553 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYBitonalExecute, 0);
559 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
560 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXByteExecute, 0);
563 pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
564 &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYByteExecute, 0);
573 /* Save away true height */
574 pPriv->ilMirrorheight = info.height;
576 pipe->context->error = IL_OK;