1 /* $XConsortium: ilformat.c /main/5 1996/06/19 12:21:36 ageorge $ */
2 /**---------------------------------------------------------------------
4 *** (c)Copyright 1991 Hewlett-Packard Co.
6 *** RESTRICTED RIGHTS LEGEND
7 *** Use, duplication, or disclosure by the U.S. Government is subject to
8 *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
9 *** Technical Data and Computer Software clause in DFARS 252.227-7013.
10 *** Hewlett-Packard Company
11 *** 3000 Hanover Street
12 *** Palo Alto, CA 94304 U.S.A.
13 *** Rights for non-DOD U.S. Government Departments and Agencies are as set
14 *** forth in FAR 52.227-19(c)(1,2).
16 ***-------------------------------------------------------------------*/
18 /* /ilc/ilformat.c : Reference by ilConvert in /ilc/ilconvert.c .
19 Contains pipe functions and an ilFormatRec, which points to the functions
20 and defines how the formatter should be added by ilConvert().
23 #include "ilpipelem.h"
24 #include "ilconvert.h"
27 /* ------------------------- ilExecuteBitAlign ------------------------- */
28 /* Execute() function: convert the given # of src lines, changing
29 the rowBitAlign. Easy; just bcopy each line, bump by src/dstRowBytes,
30 which presumably are different because of different bit alignment.
32 static ilError ilExecuteBitAlign (
38 ilImagePlaneInfo *pImagePlane;
39 long srcRowBytes, dstRowBytes;
40 register long nLinesM1, nBytes;
41 register ilPtr pSrc, pDst;
43 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
44 Exit if no lines or pixels.
46 pImagePlane = &pData->pSrcImage->plane[0];
47 srcRowBytes = pImagePlane->nBytesPerRow;
48 pSrc = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
50 pImagePlane = &pData->pDstImage->plane[0];
51 dstRowBytes = pImagePlane->nBytesPerRow;
52 pDst = pImagePlane->pPixels + dstLine * dstRowBytes;
54 nBytes = (srcRowBytes < dstRowBytes) ? srcRowBytes : dstRowBytes;
63 bcopy ((char *)pSrc, (char *)pDst, nBytes);
66 } while (--nLinesM1 >= 0);
71 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
73 IL_PRIVATE ilFormatRec _ilFormatRowBitAlign = {
74 IL_NPF, /* AddElement() */
75 0, /* nBytesPrivate */
77 IL_NPF, /* Cleanup() */
78 IL_NPF, /* Destroy() */
79 ilExecuteBitAlign /* Execute() */
83 /* ------------------------- ilExecute8Bit3PlaneToPixel ------------------------- */
84 /* Execute() function: convert the given # of src lines, changing
85 format from planar to pixel. Handles 3 planes of 8 bits/pixel only.
87 static ilError ilExecute8Bit3PlaneToPixel (
93 ilImagePlaneInfo *pImagePlane;
94 long src0RowBytes, src1RowBytes, src2RowBytes, dstRowBytes;
96 register long nLinesM1, nPixelsM1;
97 ilPtr pSrc0Line, pSrc1Line, pSrc2Line, pDstLine;
98 register ilPtr pSrc0, pSrc1, pSrc2, pDst;
100 /* Get ptr to start of 3 src planes and to dst */
101 pImagePlane = pData->pSrcImage->plane;
102 src0RowBytes = pImagePlane->nBytesPerRow;
103 pSrc0Line = pImagePlane->pPixels + pData->srcLine * src0RowBytes;
105 src1RowBytes = pImagePlane->nBytesPerRow;
106 pSrc1Line = pImagePlane->pPixels + pData->srcLine * src1RowBytes;
108 src2RowBytes = pImagePlane->nBytesPerRow;
109 pSrc2Line = pImagePlane->pPixels + pData->srcLine * src2RowBytes;
111 pImagePlane = pData->pDstImage->plane;
112 dstRowBytes = pImagePlane->nBytesPerRow;
113 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
115 /* Exit if no lines or pixels. */
116 nPixelsM1Init = pData->pSrcImage->width;
117 if (nPixelsM1Init <= 0)
127 pSrc0Line += src0RowBytes;
129 pSrc1Line += src1RowBytes;
131 pSrc2Line += src2RowBytes;
133 pDstLine += dstRowBytes;
134 nPixelsM1 = nPixelsM1Init;
139 } while (--nPixelsM1 >= 0);
140 } while (--nLinesM1 >= 0);
145 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
147 IL_PRIVATE ilFormatRec _ilFormat8Bit3PlaneToPixel = {
148 IL_NPF, /* AddElement() */
149 0, /* nBytesPrivate */
151 IL_NPF, /* Cleanup() */
152 IL_NPF, /* Destroy() */
153 ilExecute8Bit3PlaneToPixel /* Execute() */
156 /* ------------------------- ilExecute8Bit3PixelToPlane ------------------------- */
157 /* Execute() function: convert the given # of src lines, changing
158 format from pixel to planar. Handles 3 planes of 8 bits/pixel only.
160 static ilError ilExecute8Bit3PixelToPlane (
161 ilExecuteData *pData,
166 ilImagePlaneInfo *pImagePlane;
167 long dst0RowBytes, dst1RowBytes, dst2RowBytes, srcRowBytes;
169 register long nLinesM1, nPixelsM1;
170 ilPtr pDst0Line, pDst1Line, pDst2Line, pSrcLine;
171 register ilPtr pDst0, pDst1, pDst2, pSrc;
173 /* Get ptr to start src plane and to 3 dst planes */
174 pImagePlane = pData->pSrcImage->plane;
175 srcRowBytes = pImagePlane->nBytesPerRow;
176 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
178 pImagePlane = pData->pDstImage->plane;
179 dst0RowBytes = pImagePlane->nBytesPerRow;
180 pDst0Line = pImagePlane->pPixels + dstLine * dst0RowBytes;
182 dst1RowBytes = pImagePlane->nBytesPerRow;
183 pDst1Line = pImagePlane->pPixels + dstLine * dst1RowBytes;
185 dst2RowBytes = pImagePlane->nBytesPerRow;
186 pDst2Line = pImagePlane->pPixels + dstLine * dst2RowBytes;
188 /* Exit if no lines or pixels. */
189 nPixelsM1Init = pData->pSrcImage->width;
190 if (nPixelsM1Init <= 0)
200 pSrcLine += srcRowBytes;
202 pDst0Line += dst0RowBytes;
204 pDst1Line += dst1RowBytes;
206 pDst2Line += dst2RowBytes;
207 nPixelsM1 = nPixelsM1Init;
212 } while (--nPixelsM1 >= 0);
213 } while (--nLinesM1 >= 0);
218 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
220 IL_PRIVATE ilFormatRec _ilFormat8Bit3PixelToPlane = {
221 IL_NPF, /* AddElement() */
222 0, /* nBytesPrivate */
224 IL_NPF, /* Cleanup() */
225 IL_NPF, /* Destroy() */
226 ilExecute8Bit3PixelToPlane /* Execute() */
230 /* ------------------------- ilExecute4To8Bit ------------------------- */
231 /* Execute() function: convert the given # of src lines, changing nibbles
232 to bytes, by copying the nibbles to the low order of the bytes.
233 Handles any number of samples, but pixel order only if multi-sample.
235 static ilError ilExecute4To8Bit (
236 ilExecuteData *pData,
241 ilImageInfo *pSrcImage;
242 ilImagePlaneInfo *pImagePlane;
243 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
244 ilBool oddNumberOfNibbles;
245 ilPtr pSrcLine, pDstLine;
246 register long nBytesM1;
247 register ilPtr pSrc, pDst;
248 register ilByte byte;
250 /* Exit if no lines or pixels. */
251 pSrcImage = pData->pSrcImage;
252 pImagePlane = &pSrcImage->plane[0];
253 srcRowBytes = pImagePlane->nBytesPerRow;
254 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
256 pImagePlane = &pData->pDstImage->plane[0];
257 dstRowBytes = pImagePlane->nBytesPerRow;
258 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
265 /* Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
266 where the # of nibbles is width * nSamplesPerPixel.
267 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
268 Copy each src byte (2 nibbles) to two dst bytes; do optional last nibble.
270 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
271 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
272 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
275 pSrcLine += srcRowBytes;
277 pDstLine += dstRowBytes;
278 nBytesM1 = nBytesM1Init;
283 *pDst++ = byte & 0xf;
284 } while (--nBytesM1 >= 0);
286 if (oddNumberOfNibbles) {
290 } while (--nLinesM1 >= 0);
295 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
297 IL_PRIVATE ilFormatRec _ilFormat4To8Bit = {
298 IL_NPF, /* AddElement() */
299 0, /* nBytesPrivate */
301 IL_NPF, /* Cleanup() */
302 IL_NPF, /* Destroy() */
303 ilExecute4To8Bit /* Execute() */
307 /* ------------------------- ilExecute8To4Bit ------------------------- */
308 /* Pack pipe image which is byte/pixel into nibble/pixel.
309 Handles any number of samples, but pixel order only if multi-sample.
311 static ilError ilExecute8To4Bit (
312 ilExecuteData *pData,
317 ilImageInfo *pSrcImage;
318 ilImagePlaneInfo *pImagePlane;
319 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
320 ilBool oddNumberOfNibbles;
321 ilPtr pSrcLine, pDstLine;
322 register long nBytesM1;
323 register ilPtr pSrc, pDst;
324 register ilByte byte0, byte1;
326 /* Exit if no lines or pixels. */
327 pSrcImage = pData->pSrcImage;
328 pImagePlane = &pSrcImage->plane[0];
329 srcRowBytes = pImagePlane->nBytesPerRow;
330 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
332 pImagePlane = &pData->pDstImage->plane[0];
333 dstRowBytes = pImagePlane->nBytesPerRow;
334 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
341 /* Set "nBytesM1Init" to whole # of dst bytes to do (2 nibbles each),
342 where the # of nibbles is width * nSamplesPerPixel.
343 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
344 Pack each pair of src bytes into one dst nibble; do optional last nibble.
346 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
347 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
348 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
351 pSrcLine += srcRowBytes;
353 pDstLine += dstRowBytes;
354 nBytesM1 = nBytesM1Init;
359 *pDst++ = (byte0 << 4) | (byte1 & 0xf);
360 } while (--nBytesM1 >= 0);
362 if (oddNumberOfNibbles) {
364 *pDst++ = byte0 << 4;
366 } while (--nLinesM1 >= 0);
371 /* Table exported to ilConvert(), declared in /ilc/ilconvert.h .
373 IL_PRIVATE ilFormatRec _ilFormat8To4Bit = {
374 IL_NPF, /* AddElement() */
375 0, /* nBytesPrivate */
377 IL_NPF, /* Cleanup() */
378 IL_NPF, /* Destroy() */
379 ilExecute8To4Bit /* Execute() */
383 /* ------------------------- ilExecute4To8BitScaled ------------------------- */
384 /* Execute() function: convert the given # of src lines, changing nibbles
385 to bytes, by copying the nibbles to the low order and high order nibbles
386 of the bytes, thus scaling from 0..15 to 0..255.
387 Handles any number of samples, but pixel order only if multi-sample.
389 static ilError ilExecute4To8BitScaled (
390 ilExecuteData *pData,
395 ilImageInfo *pSrcImage;
396 ilImagePlaneInfo *pImagePlane;
397 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
398 ilBool oddNumberOfNibbles;
399 ilPtr pSrcLine, pDstLine;
400 register long nBytesM1;
401 register ilPtr pSrc, pDst;
402 register ilByte byte;
404 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
405 Exit if no lines or pixels.
407 pSrcImage = pData->pSrcImage;
408 pImagePlane = &pSrcImage->plane[0];
409 srcRowBytes = pImagePlane->nBytesPerRow;
410 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
412 pImagePlane = &pData->pDstImage->plane[0];
413 dstRowBytes = pImagePlane->nBytesPerRow;
414 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
421 /* Set "nBytesM1Init" to whole # of src bytes to do (2 nibbles each),
422 where the # of nibbles is width * nSamplesPerPixel.
423 Set "oddNumberOfNibbles" true if width is odd (do one last nibble).
424 Make from each src byte (2 nibbles) two dst bytes; do optional last nibble.
425 Replicate each src nibble to upper/lower nibble of dst byte, thus scaling
426 to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
428 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel;
429 oddNumberOfNibbles = ((nBytesM1Init & 1) != 0);
430 nBytesM1Init = (nBytesM1Init >> 1) - 1; /* width/2 - 1 */
433 pSrcLine += srcRowBytes;
435 pDstLine += dstRowBytes;
436 nBytesM1 = nBytesM1Init;
440 *pDst++ = (byte & 0xf0) | (byte >> 4);
442 *pDst++ = (byte << 4) | byte;
443 } while (--nBytesM1 >= 0);
445 if (oddNumberOfNibbles) {
447 *pDst++ = (byte & 0xf0) | (byte >> 4);
449 } while (--nLinesM1 >= 0);
455 /* ------------------------- ilExecuteByte16To256Level ---------------------- */
456 /* Execute() function: convert the given # of src lines, changing bytes from
457 16 levels to 256 levels, by replicating the low-order nibble to the high
458 order nibble, thus scaling from 0..15 to 0..255.
459 Handles any number of samples, but pixel order only if multi-sample.
461 static ilError ilExecuteByte16To256Level (
462 ilExecuteData *pData,
467 ilImageInfo *pSrcImage;
468 ilImagePlaneInfo *pImagePlane;
469 long srcRowBytes, dstRowBytes, nBytesM1Init, nLinesM1;
470 ilPtr pSrcLine, pDstLine;
471 register long nBytesM1;
472 register ilPtr pSrc, pDst;
473 register ilByte byte;
475 /* Use bcopy to copy each line; copy the lesser of the src/dstRowBytes.
476 Exit if no lines or pixels.
478 pSrcImage = pData->pSrcImage;
479 pImagePlane = &pSrcImage->plane[0];
480 srcRowBytes = pImagePlane->nBytesPerRow;
481 pSrcLine = pImagePlane->pPixels + pData->srcLine * srcRowBytes;
483 pImagePlane = &pData->pDstImage->plane[0];
484 dstRowBytes = pImagePlane->nBytesPerRow;
485 pDstLine = pImagePlane->pPixels + dstLine * dstRowBytes;
492 /* Set "nBytesM1Init" to whole # of src bytes to do, = width * # samples/pixel
493 (note that each sample must be a byte!)
494 Replicate low-order nibble to upper nibble of dst byte, thus scaling
495 to new # of levels (from 16 to 256): 0 => 0, 1 => 17, 15 => 255.
497 nBytesM1Init = pSrcImage->width * pSrcImage->pDes->nSamplesPerPixel - 1;
498 if (nBytesM1Init < 0)
503 pSrcLine += srcRowBytes;
505 pDstLine += dstRowBytes;
506 nBytesM1 = nBytesM1Init;
510 *pDst++ = (byte << 4) | byte;
511 } while (--nBytesM1 >= 0);
512 } while (--nLinesM1 >= 0);
518 /* ---------------------- ilAddLevelConversionFilter ------------------------ */
519 /* Add a conversion filter to the given pipe which converts from the levels
520 in "*pPipeDes" (i.e. the levels of the current pipe image) to those in
521 "*pDes" (note - only nLevelsPerSample is reference from pDes).
522 If failure, declares pipe invalid (which sets error code) and returns false;
523 else returns true and "*pInfo", "*pPipeDes" and "*pFormat" are updated
524 with the new pipe state info.
526 IL_PRIVATE ilBool _ilAddLevelConversionFilter (
529 ilImageDes *pPipeDes,
530 const ilImageDes *pDes,
531 ilImageFormat *pFormat
536 ilDstElementData dstData;
537 ilError (*executeFunction)();
538 ilBool all4Bit, all8Bit;
540 /* Determine if we support requested conversion.
541 Currently only support: 4 or 8 bit, 16 level => 8 bit, 256 level, any # of
542 samples/pixel, but pixel mode only if # samples > 1.
544 if ((pDes->nSamplesPerPixel > 1) && (pFormat->sampleOrder != IL_SAMPLE_PIXELS))
545 return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
547 all4Bit = all8Bit = TRUE;
548 for (sample = 0; sample < pPipeDes->nSamplesPerPixel; sample++) {
549 if ((pPipeDes->nLevelsPerSample[sample] != 16)
550 || (pDes->nLevelsPerSample[sample] != 256))
551 return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
552 pPipeDes->nLevelsPerSample[sample] = 256;
554 if (pFormat->nBitsPerSample[sample] == 4) {
556 pFormat->nBitsPerSample[sample] = 8;
558 else if (pFormat->nBitsPerSample[sample] == 8)
560 else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
563 /* All src # levels == 16, dst == 256. If all src formats are 4 bit or 8 bit,
564 can handle, else error. pFormat->nBitsPerSample now == 8 for all samples.
567 executeFunction = ilExecute4To8BitScaled;
569 executeFunction = ilExecuteByte16To256Level;
570 else return ilDeclarePipeInvalid (pipe, IL_ERROR_CANT_CONVERT);
572 /* Update *pPipeDes, *pFormat and add filter or error.
573 Update pInfo after successful add; pPipeDes and pFormat already updated.
575 dstData.producerObject = (ilObject)NULL;
576 dstData.pDes = pPipeDes;
577 dstData.pFormat = pFormat;
578 dstData.width = pInfo->width;
579 dstData.height = pInfo->height;
580 dstData.stripHeight = 0;
581 dstData.constantStrip = FALSE;
582 dstData.pPalette = pInfo->pPalette;
583 dstData.pCompData = pInfo->pCompData;
584 pPriv = ilAddPipeElement (pipe, IL_FILTER, 0, 0,
585 (ilSrcElementData *)NULL, &dstData,
586 IL_NPF, IL_NPF, IL_NPF, executeFunction, NULL, 0);
587 if (!pPriv) return FALSE; /* EXIT */
589 ilGetPipeInfo (pipe, FALSE, pInfo, (ilImageDes *)NULL, (ilImageFormat *)NULL);