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: ilformat.c /main/5 1996/06/19 12:21:36 ageorge $ */
24 /**---------------------------------------------------------------------
26 *** (c)Copyright 1991 Hewlett-Packard Co.
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).
38 ***-------------------------------------------------------------------*/
40 /* /ilc/ilformat.c : Reference by ilConvert in /ilc/ilconvert.c .
41 Contains pipe functions and an ilFormatRec, which points to the functions
42 and defines how the formatter should be added by ilConvert().
45 #include "ilpipelem.h"
46 #include "ilconvert.h"
49 /* ------------------------- ilExecuteBitAlign ------------------------- */
50 /* Execute() function: convert the given # of src lines, changing
51 the rowBitAlign. Easy; just bcopy each line, bump by src/dstRowBytes,
52 which presumably are different because of different bit alignment.
54 static ilError ilExecuteBitAlign (
60 ilImagePlaneInfo *pImagePlane;
61 long srcRowBytes, dstRowBytes;
62 long nLinesM1, nBytes;
65 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
66 Exit if no lines or pixels.
68 pImagePlane = &pData->pSrcImage->plane[0];
69 srcRowBytes = pImagePlane->nBytesPerRow;
70 pSrc = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
72 pImagePlane = &pData->pDstImage->plane[0];
73 dstRowBytes = pImagePlane->nBytesPerRow;
74 pDst = pImagePlane->pPixels + dstLine * dstRowBytes;
76 nBytes = (srcRowBytes < dstRowBytes) ? srcRowBytes : dstRowBytes;
85 bcopy ((char *)pSrc, (char *)pDst, nBytes);
88 } while (--nLinesM1 >= 0);
93 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
95 IL_PRIVATE ilFormatRec _ilFormatRowBitAlign = {
96 IL_NPF, /* AddElement() */
97 0, /* nBytesPrivate */
99 IL_NPF, /* Cleanup() */
100 IL_NPF, /* Destroy() */
101 ilExecuteBitAlign /* Execute() */
105 /* ------------------------- ilExecute8Bit3PlaneToPixel ------------------------- */
106 /* Execute() function: convert the given # of src lines, changing
107 format from planar to pixel. Handles 3 planes of 8 bits/pixel only.
109 static ilError ilExecute8Bit3PlaneToPixel (
110 ilExecuteData *pData,
115 ilImagePlaneInfo *pImagePlane;
116 long src0RowBytes, src1RowBytes, src2RowBytes, dstRowBytes;
118 long nLinesM1, nPixelsM1;
119 ilPtr pSrc0Line, pSrc1Line, pSrc2Line, pDstLine;
120 ilPtr pSrc0, pSrc1, pSrc2, pDst;
122 /* Get ptr to start of 3 src planes and to dst */
123 pImagePlane = pData->pSrcImage->plane;
124 src0RowBytes = pImagePlane->nBytesPerRow;
125 pSrc0Line = pImagePlane->pPixels + pData->srcLine * src0RowBytes;
127 src1RowBytes = pImagePlane->nBytesPerRow;
128 pSrc1Line = pImagePlane->pPixels + pData->srcLine * src1RowBytes;
130 src2RowBytes = pImagePlane->nBytesPerRow;
131 pSrc2Line = pImagePlane->pPixels + pData->srcLine * src2RowBytes;
133 pImagePlane = pData->pDstImage->plane;
134 dstRowBytes = pImagePlane->nBytesPerRow;
135 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
137 /* Exit if no lines or pixels. */
138 nPixelsM1Init = pData->pSrcImage->width;
139 if (nPixelsM1Init <= 0)
149 pSrc0Line += src0RowBytes;
151 pSrc1Line += src1RowBytes;
153 pSrc2Line += src2RowBytes;
155 pDstLine += dstRowBytes;
156 nPixelsM1 = nPixelsM1Init;
161 } while (--nPixelsM1 >= 0);
162 } while (--nLinesM1 >= 0);
167 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
169 IL_PRIVATE ilFormatRec _ilFormat8Bit3PlaneToPixel = {
170 IL_NPF, /* AddElement() */
171 0, /* nBytesPrivate */
173 IL_NPF, /* Cleanup() */
174 IL_NPF, /* Destroy() */
175 ilExecute8Bit3PlaneToPixel /* Execute() */
178 /* ------------------------- ilExecute8Bit3PixelToPlane ------------------------- */
179 /* Execute() function: convert the given # of src lines, changing
180 format from pixel to planar. Handles 3 planes of 8 bits/pixel only.
182 static ilError ilExecute8Bit3PixelToPlane (
183 ilExecuteData *pData,
188 ilImagePlaneInfo *pImagePlane;
189 long dst0RowBytes, dst1RowBytes, dst2RowBytes, srcRowBytes;
191 long nLinesM1, nPixelsM1;
192 ilPtr pDst0Line, pDst1Line, pDst2Line, pSrcLine;
193 ilPtr pDst0, pDst1, pDst2, pSrc;
195 /* Get ptr to start src plane and to 3 dst planes */
196 pImagePlane = pData->pSrcImage->plane;
197 srcRowBytes = pImagePlane->nBytesPerRow;
198 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
200 pImagePlane = pData->pDstImage->plane;
201 dst0RowBytes = pImagePlane->nBytesPerRow;
202 pDst0Line = pImagePlane->pPixels + dstLine * dst0RowBytes;
204 dst1RowBytes = pImagePlane->nBytesPerRow;
205 pDst1Line = pImagePlane->pPixels + dstLine * dst1RowBytes;
207 dst2RowBytes = pImagePlane->nBytesPerRow;
208 pDst2Line = pImagePlane->pPixels + dstLine * dst2RowBytes;
210 /* Exit if no lines or pixels. */
211 nPixelsM1Init = pData->pSrcImage->width;
212 if (nPixelsM1Init <= 0)
222 pSrcLine += srcRowBytes;
224 pDst0Line += dst0RowBytes;
226 pDst1Line += dst1RowBytes;
228 pDst2Line += dst2RowBytes;
229 nPixelsM1 = nPixelsM1Init;
234 } while (--nPixelsM1 >= 0);
235 } while (--nLinesM1 >= 0);
240 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
242 IL_PRIVATE ilFormatRec _ilFormat8Bit3PixelToPlane = {
243 IL_NPF, /* AddElement() */
244 0, /* nBytesPrivate */
246 IL_NPF, /* Cleanup() */
247 IL_NPF, /* Destroy() */
248 ilExecute8Bit3PixelToPlane /* Execute() */
252 /* ------------------------- ilExecute4To8Bit ------------------------- */
253 /* Execute() function: convert the given # of src lines, changing nibbles
254 to bytes, by copying the nibbles to the low order of the bytes.
255 Handles any number of samples, but pixel order only if multi-sample.
257 static ilError ilExecute4To8Bit (
258 ilExecuteData *pData,
263 ilImageInfo *pSrcImage;
264 ilImagePlaneInfo *pImagePlane;
265 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
266 ilBool oddNumberOfNibbles;
267 ilPtr pSrcLine, pDstLine;
272 /* Exit if no lines or pixels. */
273 pSrcImage = pData->pSrcImage;
274 pImagePlane = &pSrcImage->plane[0];
275 srcRowBytes = pImagePlane->nBytesPerRow;
276 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
278 pImagePlane = &pData->pDstImage->plane[0];
279 dstRowBytes = pImagePlane->nBytesPerRow;
280 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
287 /* Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
288 where the # of nibbles is width * nSamplesPerPixel.
289 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
290 Copy each src byte (2 nibbles) to two dst bytes; do optional last nibble.
292 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
293 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
294 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
297 pSrcLine += srcRowBytes;
299 pDstLine += dstRowBytes;
300 nBytesM1 = nBytesM1Init;
305 *pDst++ = byte & 0xf;
306 } while (--nBytesM1 >= 0);
308 if (oddNumberOfNibbles) {
312 } while (--nLinesM1 >= 0);
317 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
319 IL_PRIVATE ilFormatRec _ilFormat4To8Bit = {
320 IL_NPF, /* AddElement() */
321 0, /* nBytesPrivate */
323 IL_NPF, /* Cleanup() */
324 IL_NPF, /* Destroy() */
325 ilExecute4To8Bit /* Execute() */
329 /* ------------------------- ilExecute8To4Bit ------------------------- */
330 /* Pack pipe image which is byte/pixel into nibble/pixel.
331 Handles any number of samples, but pixel order only if multi-sample.
333 static ilError ilExecute8To4Bit (
334 ilExecuteData *pData,
339 ilImageInfo *pSrcImage;
340 ilImagePlaneInfo *pImagePlane;
341 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
342 ilBool oddNumberOfNibbles;
343 ilPtr pSrcLine, pDstLine;
348 /* Exit if no lines or pixels. */
349 pSrcImage = pData->pSrcImage;
350 pImagePlane = &pSrcImage->plane[0];
351 srcRowBytes = pImagePlane->nBytesPerRow;
352 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
354 pImagePlane = &pData->pDstImage->plane[0];
355 dstRowBytes = pImagePlane->nBytesPerRow;
356 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
363 /* Set "nBytesM1Init" to whole # of dst bytes to do (2 nibbles each),
364 where the # of nibbles is width * nSamplesPerPixel.
365 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
366 Pack each pair of src bytes into one dst nibble; do optional last nibble.
368 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
369 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
370 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
373 pSrcLine += srcRowBytes;
375 pDstLine += dstRowBytes;
376 nBytesM1 = nBytesM1Init;
381 *pDst++ = (byte0 << 4) | (byte1 & 0xf);
382 } while (--nBytesM1 >= 0);
384 if (oddNumberOfNibbles) {
386 *pDst++ = byte0 << 4;
388 } while (--nLinesM1 >= 0);
393 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
395 IL_PRIVATE ilFormatRec _ilFormat8To4Bit = {
396 IL_NPF, /* AddElement() */
397 0, /* nBytesPrivate */
399 IL_NPF, /* Cleanup() */
400 IL_NPF, /* Destroy() */
401 ilExecute8To4Bit /* Execute() */
405 /* ------------------------- ilExecute4To8BitScaled ------------------------- */
406 /* Execute() function: convert the given # of src lines, changing nibbles
407 to bytes, by copying the nibbles to the low order and high order nibbles
408 of the bytes, thus scaling from 0..15 to 0..255.
409 Handles any number of samples, but pixel order only if multi-sample.
411 static ilError ilExecute4To8BitScaled (
412 ilExecuteData *pData,
417 ilImageInfo *pSrcImage;
418 ilImagePlaneInfo *pImagePlane;
419 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
420 ilBool oddNumberOfNibbles;
421 ilPtr pSrcLine, pDstLine;
426 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
427 Exit if no lines or pixels.
429 pSrcImage = pData->pSrcImage;
430 pImagePlane = &pSrcImage->plane[0];
431 srcRowBytes = pImagePlane->nBytesPerRow;
432 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
434 pImagePlane = &pData->pDstImage->plane[0];
435 dstRowBytes = pImagePlane->nBytesPerRow;
436 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
443 /* Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
444 where the # of nibbles is width * nSamplesPerPixel.
445 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
446 Make from each src byte (2 nibbles) two dst bytes; do optional last nibble.
447 Replicate each src nibble to upper/lower nibble of dst byte, thus scaling
448 to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
450 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
451 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
452 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
455 pSrcLine += srcRowBytes;
457 pDstLine += dstRowBytes;
458 nBytesM1 = nBytesM1Init;
462 *pDst++ = (byte & 0xf0) | (byte >> 4);
464 *pDst++ = (byte << 4) | byte;
465 } while (--nBytesM1 >= 0);
467 if (oddNumberOfNibbles) {
469 *pDst++ = (byte & 0xf0) | (byte >> 4);
471 } while (--nLinesM1 >= 0);
477 /* ------------------------- ilExecuteByte16To256Level ---------------------- */
478 /* Execute() function: convert the given # of src lines, changing bytes from
479 16 levels to 256 levels, by replicating the low-order nibble to the high
480 order nibble, thus scaling from 0..15 to 0..255.
481 Handles any number of samples, but pixel order only if multi-sample.
483 static ilError ilExecuteByte16To256Level (
484 ilExecuteData *pData,
489 ilImageInfo *pSrcImage;
490 ilImagePlaneInfo *pImagePlane;
491 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
492 ilPtr pSrcLine, pDstLine;
497 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
498 Exit if no lines or pixels.
500 pSrcImage = pData->pSrcImage;
501 pImagePlane = &pSrcImage->plane[0];
502 srcRowBytes = pImagePlane->nBytesPerRow;
503 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
505 pImagePlane = &pData->pDstImage->plane[0];
506 dstRowBytes = pImagePlane->nBytesPerRow;
507 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
514 /* Set "nBytesM1Init" to whole # of src bytes to do, = width * # samples/pixel
515 (note that each sample must be a byte!)
516 Replicate low-order nibble to upper nibble of dst byte, thus scaling
517 to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
519 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel - 1;
520 if (nBytesM1Init < 0)
525 pSrcLine += srcRowBytes;
527 pDstLine += dstRowBytes;
528 nBytesM1 = nBytesM1Init;
532 *pDst++ = (byte << 4) | byte;
533 } while (--nBytesM1 >= 0);
534 } while (--nLinesM1 >= 0);
540 /* ---------------------- ilAddLevelConversionFilter ------------------------ */
541 /* Add a conversion filter to the given pipe which converts from the levels
542 in "*pPipeDes" (i.e. the levels of the current pipe image) to those in
543 "*pDes" (note - only nLevelsPerSample is reference from pDes).
544 If failure, declares pipe invalid (which sets error code) and returns false;
545 else returns true and "*pInfo", "*pPipeDes" and "*pFormat" are updated
546 with the new pipe state info.
548 IL_PRIVATE ilBool _ilAddLevelConversionFilter (
551 ilImageDes *pPipeDes,
552 const ilImageDes *pDes,
553 ilImageFormat *pFormat
558 ilDstElementData dstData;
559 ilError (*executeFunction)();
560 ilBool all4Bit, all8Bit;
562 /* Determine if we support requested conversion.
563 Currently only support: 4 or 8 bit, 16 level => 8 bit, 256 level, any # of
564 samples/pixel, but pixel mode only if # samples > 1.
566 if ((pDes->nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
567 return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
569 all4Bit = all8Bit = TRUE;
570 for (sample = 0; sample < pPipeDes->nSamplesPerPixel; sample++) {
571 if ((pPipeDes->nLevelsPerSample[sample] != 16)
572 || (pDes->nLevelsPerSample[sample] != 256))
573 return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
574 pPipeDes->nLevelsPerSample[sample] = 256;
576 if (pFormat->nBitsPerSample[sample] == 4) {
578 pFormat->nBitsPerSample[sample] = 8;
580 else if (pFormat->nBitsPerSample[sample] == 8)
582 else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
585 /* All src # levels == 16, dst == 256. If all src formats are 4 bit or 8 bit,
586 can handle, else error. pFormat->nBitsPerSample now == 8 for all samples.
589 executeFunction = ilExecute4To8BitScaled;
591 executeFunction = ilExecuteByte16To256Level;
592 else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
594 /* Update *pPipeDes, *pFormat and add filter or error.
595 Update pInfo after successful add; pPipeDes and pFormat already updated.
597 dstData.producerObject = (ilObject)NULL;
598 dstData.pDes = pPipeDes;
599 dstData.pFormat = pFormat;
600 dstData.width = pInfo->width;
601 dstData.height = pInfo->height;
602 dstData.stripHeight = 0;
603 dstData.constantStrip = FALSE;
604 dstData.pPalette = pInfo->pPalette;
605 dstData.pCompData = pInfo->pCompData;
606 pPriv = ilAddPipeElement (pipe, IL_FILTER, 0, 0,
607 (ilSrcElementData *)NULL, &dstData,
608 IL_NPF, IL_NPF, IL_NPF, executeFunction, NULL, 0);
609 if (!pPriv) return FALSE; /* EXIT */
611 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);