Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / DtHelp / il / ilmirror.c
1 /* $XConsortium: ilmirror.c /main/4 1996/01/08 12:16:48 lehors $ */
2 /* =============================================================================================================================
3
4      /ilc/ilmirror.c : Images Library mirror routines.   
5
6
7
8         Date        Mail-ID     Description
9         --------    ----------- -------------------------------------------------------------------
10         07/11/91    larsson     Initial Coding.
11
12         
13
14    ============================================================================================================================= */
15
16 #include "ilint.h"
17 #include "ilpipelem.h"
18 #include "ilerrors.h"
19
20 #define LONGSZ        4
21 #define WORDPOS       32
22 #define BYTESIZE      8
23 #define LEFT_BIT_ON   0x80000000
24
25
26     /*  Table of bytes with equivalent bits flipped, in /ilc/ilrotate.c */
27 extern const unsigned char ilBitReverseTable [];
28
29
30  typedef struct {
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;
34
35
36
37 /* =============================================================================================================================
38    ============================================================================================================================= */
39
40
41 static ilError ilMirrorInit(
42     ilMirrorPrivptr  pPrivate,
43     ilImageInfo     *pSrcImage,
44     ilImageInfo     *pDstImage
45     )
46
47 {
48  register unsigned char  *pdstline;
49  ilImagePlaneInfo           *pplane;
50
51
52    /* Initialize counters */
53
54    pPrivate->illinecount =  1;
55             
56    /* Zero out destination memory for bitonal format handling */
57    pplane   = &pDstImage->plane[0];
58    pdstline =  (unsigned char *) (pplane->pPixels);
59
60    bzero((char *)pdstline, (pplane->nBytesPerRow * pPrivate->ilMirrorheight) );
61
62    return IL_OK;
63 }
64
65
66 /* =============================================================================================================================
67
68       ilMirrorXBitonalExecute  -  Vertical mirroring for images with bit per pixel format .
69
70    ============================================================================================================================= */
71 static ilError ilMirrorXBitonalExecute (
72     register ilExecuteData  *pData,
73     unsigned long           dstLine,
74     unsigned long          *pNLines
75     )
76 {
77                         
78
79 register unsigned char     *psrc, *pdst, *psrcline, *pdstline;
80 ilImagePlaneInfo           *pplane;
81 register int               x, y, lastcount, srcnbytes, dstnbytes;
82 register ilMirrorPrivptr   pPriv;
83
84
85
86    if (*pNLines <= 0)  return IL_OK;
87
88    pplane                  =  &pData->pSrcImage->plane[0];
89    srcnbytes               =  pplane->nBytesPerRow;
90    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
91
92    pplane                  =  &pData->pDstImage->plane[0];
93    dstnbytes               =  pplane->nBytesPerRow;
94    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
95    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
96
97
98
99    /* Mirror vertically  map (x,y) to (x, -y) about its center  [ x,  height-y ]  */
100
101    lastcount = pPriv->illinecount - 1;
102    for (y = pPriv->illinecount;   y <= (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
103
104       psrc = psrcline;
105       pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
106       for ( x = 0;   x < srcnbytes;  x++)  *pdst++  = *psrc++;
107       psrcline += srcnbytes;
108
109    }
110
111
112    /* No. of lines written is the destination height */
113    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
114    else   *pNLines = pPriv->ilMirrorheight;
115    
116    return IL_OK;
117 }
118
119
120
121 /* =============================================================================================================================
122
123       ilMirrorYBitonalExecute  -  Horizontal mirroring for images with bit per pixel format .
124
125    ============================================================================================================================= */
126 static ilError ilMirrorYBitonalExecute (
127     register ilExecuteData  *pData,
128     unsigned long           dstLine,
129     unsigned long          *pNLines
130     )
131 {
132                         
133
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;
140
141
142    if (*pNLines <= 0)  return IL_OK;
143
144    pplane                  =  &pData->pSrcImage->plane[0];
145    srcnbytes               =  pplane->nBytesPerRow;
146    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
147
148    pplane                  =  &pData->pDstImage->plane[0];
149    dstnbytes               =  pplane->nBytesPerRow;
150    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
151    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
152
153
154    loffset    = pData->pSrcImage->width % BYTESIZE;
155    roffset    = BYTESIZE - loffset;
156    widthbytes = pData->pSrcImage->width / BYTESIZE;
157    if ( loffset > 0 ) widthbytes++;
158
159
160    /* Mirror horizontally  map (x,y) to (-x, y) about its center  [ width-x,  y ]  */
161
162    lastcount = pPriv->illinecount - 1;
163    for (y = lastcount;   y < (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
164
165       psrc       = psrcline + widthbytes - 1;
166       psrcbefore = psrc - 1;
167
168       pdst = pdstline + (dstnbytes * y);
169
170       if ( loffset == 0 ) 
171            for ( x = 0;  x < widthbytes;  x++)   *pdst++ = ilBitReverseTable[ *psrc-- ];
172       else  { 
173            for ( x = 0;   x < widthbytes;  x++) {
174
175                    if ( psrcbefore < psrcline )    srcbyte = (*psrc >> roffset);
176                    else       srcbyte = (*psrcbefore << loffset) | (*psrc >> roffset);
177
178                    *pdst++  =  ilBitReverseTable[srcbyte];
179                    psrc--;
180                    psrcbefore--;
181            }
182       }
183
184       psrcline += srcnbytes;
185    }
186
187
188    /* No. of lines written is the destination height */
189    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
190    else   *pNLines = pPriv->ilMirrorheight;
191    
192    return IL_OK;
193 }
194
195 /* =============================================================================================================================
196
197       ilMirrorX3ByteExecute  -  Vertical mirroring for images with 24 bits per pixel format .
198
199    ============================================================================================================================= */
200 static ilError ilMirrorX3ByteExecute (
201     register ilExecuteData   *pData,
202     unsigned long           dstLine,
203     unsigned long          *pNLines
204     )
205 {
206
207
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;
213
214
215    if (*pNLines <= 0)  return IL_OK;
216
217    pplane                  =  &pData->pSrcImage->plane[0];
218    srcnbytes               =  pplane->nBytesPerRow;
219    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
220
221    pplane                  =  &pData->pDstImage->plane[0];
222    dstnbytes               =  pplane->nBytesPerRow;
223    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
224    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
225
226
227
228    /* Mirror vertically  map (x,y) to (x, -y) about its center  [ x,  height-y ]  */
229
230    lastcount = pPriv->illinecount - 1;
231    for (y = pPriv->illinecount;   y <= (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
232
233       psrc = psrcline;
234
235       pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
236       for ( x = 0;   x < pData->pSrcImage->width;  x++) {
237            *pdst++  =  *psrc++;
238            *pdst++  =  *psrc++;
239            *pdst++  =  *psrc++;
240       }
241       psrcline += srcnbytes;
242
243    }
244
245
246    /* No. of lines written is the destination height */
247    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
248    else   *pNLines = pPriv->ilMirrorheight;
249    
250    return IL_OK;
251 }
252
253
254 /* =============================================================================================================================
255
256       ilMirrorY3ByteExecute  -  Horizontal mirroring for images with 24 bits per pixel format .
257
258    ============================================================================================================================= */
259 static ilError ilMirrorY3ByteExecute (
260     register ilExecuteData   *pData,
261     unsigned long           dstLine,
262     unsigned long          *pNLines
263     )
264 {
265
266
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;
272
273
274    if (*pNLines <= 0)  return IL_OK;
275
276    pplane                  =  &pData->pSrcImage->plane[0];
277    srcnbytes               =  pplane->nBytesPerRow;
278    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
279
280    pplane                  =  &pData->pDstImage->plane[0];
281    dstnbytes               =  pplane->nBytesPerRow;
282    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
283    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
284
285
286
287    /* Mirror horizontally  map (x,y) to (-x, y) about its center  [ width-x,  y ]  */
288
289    xoffset = pData->pSrcImage->width * 3;
290
291    lastcount = pPriv->illinecount - 1;
292    for (y = lastcount;   y < (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
293
294       psrc = psrcline + 2;
295
296       pdst = pdstline + (dstnbytes * y) + xoffset - 1;
297       for ( x = 0;   x < pData->pSrcImage->width;  x++,  psrc += 5) {
298                 *pdst--  =  *psrc--;
299                 *pdst--  =  *psrc--;
300                 *pdst--  =  *psrc;
301       }
302       psrcline += srcnbytes;
303       
304    }
305
306
307    /* No. of lines written is the destination height */
308    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
309    else   *pNLines = pPriv->ilMirrorheight;
310    
311    return IL_OK;
312 }
313
314
315 /* =============================================================================================================================
316
317       ilMirrorXByteExecute  -  Vertical mirroring for images with byte per pixel format .
318
319    ============================================================================================================================= */
320 static ilError ilMirrorXByteExecute (
321     register ilExecuteData   *pData,
322     unsigned long           dstLine,
323     unsigned long          *pNLines
324     )
325 {
326
327
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;
333
334
335    if (*pNLines <= 0)  return IL_OK;
336
337    pplane                  =  &pData->pSrcImage->plane[0];
338    srcnbytes               =  pplane->nBytesPerRow;
339    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
340
341    pplane                  =  &pData->pDstImage->plane[0];
342    dstnbytes               =  pplane->nBytesPerRow;
343    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
344    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
345
346
347
348
349    /* Mirror vertically  map (x,y) to (x, -y) about its center  [ x,  height-y ]  */
350
351    lastcount = pPriv->illinecount - 1;
352    for (y = pPriv->illinecount;   y <= (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
353
354       psrc = psrcline;
355       pdst = pdstline + (dstnbytes * (pPriv->ilMirrorheight - y));
356       for ( x = 0;   x < pData->pSrcImage->width;  x++) *pdst++  =  *psrc++;
357       psrcline += srcnbytes;
358
359    }
360
361
362    /* No. of lines written is the destination height */
363    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
364    else   *pNLines = pPriv->ilMirrorheight;
365    
366    return IL_OK;
367 }                       
368
369
370 /* =============================================================================================================================
371
372       ilMirrorYByteExecute  -  Horizontal mirroring for images with byte per pixel format .
373
374    ============================================================================================================================= */
375 static ilError ilMirrorYByteExecute (
376     register ilExecuteData   *pData,
377     unsigned long           dstLine,
378     unsigned long          *pNLines
379     )
380 {
381
382
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;
388
389
390    if (*pNLines <= 0)  return IL_OK;
391
392    pplane                  =  &pData->pSrcImage->plane[0];
393    srcnbytes               =  pplane->nBytesPerRow;
394    psrcline                =  (unsigned char *) (pplane->pPixels) +  pData->srcLine * srcnbytes;
395
396    pplane                  =  &pData->pDstImage->plane[0];
397    dstnbytes               =  pplane->nBytesPerRow;
398    pdstline                =  (unsigned char *) (pplane->pPixels)  +  dstLine * dstnbytes;
399    pPriv                   =  (ilMirrorPrivptr) pData->pPrivate;
400
401
402
403
404    /* Mirror horizontally  map (x,y) to (-x, y) about its center  [ width-x,  y ]  */
405
406    lastcount = pPriv->illinecount - 1;
407    for (y = lastcount;   y < (lastcount + *pNLines);  y++, pPriv->illinecount++ )  {
408
409       psrc = psrcline;
410       pdst = pdstline + (dstnbytes * y) + srcnbytes - 1;
411       for ( x = 0;   x < pData->pSrcImage->width;  x++) *pdst--  =  *psrc++;
412       psrcline += srcnbytes;
413
414    }
415
416
417    /* No. of lines written is the destination height */
418    if  ( pPriv->illinecount <= pPriv->ilMirrorheight ) *pNLines = 0;
419    else   *pNLines = pPriv->ilMirrorheight;
420    
421    return IL_OK;
422 }
423
424 /* =============================================================================================================================
425
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).
429                   
430
431    ============================================================================================================================= */
432
433 ilBool ilMirror (
434     ilPipe              pipe,
435     int                 direction
436     )
437
438 {
439 unsigned int              state;
440 ilPipeInfo                info;
441 register ilMirrorPrivptr  pPriv;
442 ilDstElementData          dstdata;
443 ilImageDes                imdes;
444 ilImageFormat             imformat;
445 ilBool                    convert;
446 ilBool                    bitonal;
447 ilBool                    cw;
448 unsigned int              rtype;
449
450
451        /* Get ptr to pipe info and check state */
452
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);
457          return FALSE;
458        }
459
460
461        bitonal = FALSE;
462
463        /* Check for valid Formats */
464        convert = FALSE;
465        switch (imdes.nSamplesPerPixel)  {
466             case  3: /* RGB or YUV */  
467                      if(imformat.sampleOrder != IL_SAMPLE_PIXELS)  { 
468                            imformat.sampleOrder = IL_SAMPLE_PIXELS;
469                            convert = TRUE;
470                      }
471
472                      if((imformat.nBitsPerSample[0] != 8) ||
473                         (imformat.nBitsPerSample[1] != 8) ||
474                         (imformat.nBitsPerSample[2] != 8))  {
475
476                           imformat.nBitsPerSample[0] = 8;
477                           imformat.nBitsPerSample[1] = 8;
478                           imformat.nBitsPerSample[2] = 8;
479                           convert = TRUE;
480                      }
481                      break;
482
483             case  1:
484                      switch (imformat.nBitsPerSample[0]) {
485                              case 8:  /* Byte per pixel */
486                                       break;
487
488                              case 1:  /* Bitonal */
489                                       bitonal = TRUE; 
490                                       if (imformat.rowBitAlign != 32) {
491                                          imformat.rowBitAlign = 32;
492                                          convert = TRUE;
493                                       }
494                                       break;
495
496                              default: /* something other than 1 - try 8 */
497                                       imformat.nBitsPerSample[0] = 8;
498                                       convert = TRUE;
499                      }  
500                      break;
501
502             default:
503                       return ilDeclarePipeInvalid(pipe, IL_ERROR_NOT_IMPLEMENTED);
504        }
505
506
507        if(convert) {
508             if (!ilConvert(pipe, &imdes, &imformat, 0, NULL))
509                 return FALSE;
510             ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
511        }
512          
513
514        /* if invalid direction flag as an error */
515        if ((direction != IL_MIRRORX) && (direction != IL_MIRRORY))
516             return ilDeclarePipeInvalid(pipe, IL_ERROR_INVALID_OPTION);
517
518        dstdata.producerObject = (ilObject) NULL;
519        dstdata.pDes           = (ilImageDes *) NULL;
520        dstdata.pFormat        = (ilImageFormat *) NULL;
521        dstdata.pPalette       = info.pPalette;
522
523        dstdata.width          = info.width;
524        dstdata.height         = info.height;
525
526        /* set output strip height */
527        dstdata.stripHeight    = dstdata.height;
528        dstdata.constantStrip  = TRUE;
529
530
531        switch (imdes.nSamplesPerPixel) {
532             case 3:            
533                       switch (direction) {
534                         case IL_MIRRORX:
535                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
536                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorX3ByteExecute, 0);
537                                break;
538                         case IL_MIRRORY:
539                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
540                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorY3ByteExecute, 0);
541                       }
542                       break;
543
544             case 1:  
545                  if(bitonal) {
546                       switch (direction) {
547                         case IL_MIRRORX:
548                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
549                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXBitonalExecute, 0);
550                                break;
551                         case IL_MIRRORY:
552                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
553                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYBitonalExecute, 0);
554                       }
555                  }
556                  else {
557                       switch (direction) {
558                         case IL_MIRRORX:
559                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
560                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorXByteExecute, 0);
561                                break;
562                         case IL_MIRRORY:
563                                pPriv = (ilMirrorPrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilMirrorPriv), 0, (ilSrcElementData *) NULL,
564                                                                           &dstdata, ilMirrorInit, IL_NPF, IL_NPF, ilMirrorYByteExecute, 0);
565                       }
566                  }
567
568        }
569
570        if(!pPriv)
571             return FALSE;
572
573        /* Save away true height */
574        pPriv->ilMirrorheight = info.height;   
575
576        pipe->context->error = IL_OK;
577        return TRUE;
578 }
579
580