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: ilupsample.c /main/6 1996/06/19 12:20:32 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/ilupsample.c : Code for doing upsampling, or scaling
41 by 1, 2, 4x of planar images; each plane independent.
44 #include "ilpipelem.h"
45 #include "ilconvert.h"
48 /* ========================== Fast Code ================================= */
49 /* This code handles the upsampling cases where the vertical and horizontal subsample
50 factors are equal (generally the case). It is faster than the general case code.
53 /* Private for fast upsampling filters. "subsampleShift" is the shift value (0,1,2)
54 for how that sample was subsampled; "shift" is the shift for upsampling that
55 sample. They are the same unless "double"; shift[i]=subsampleShift[i]+1 then.
58 unsigned int nSamples;
59 unsigned int subsampleShift[IL_MAX_SAMPLES];
60 unsigned int shift[IL_MAX_SAMPLES];
62 } ilUpFastPrivRec, *ilUpFastPrivPtr;
65 /* -------------------------- ilExecuteFastUpsample ------------------------------ */
66 /* Called by ilExecuteFastUpsample() to quadruple (scale up by 4) one plane.
68 static void ilUpsampleQuadruple (
77 int temp0, temp1, delta;
79 long nSrcBytesM1, dstOffset;
80 ilPtr pSrc, pSrcBelow, pDst;
81 int left, leftBelow, right, rightBelow;
83 #define FUPINTER(_start, _delta, _temp, _result) { \
84 _result = (_start) << 8; \
86 _result += _temp >> 2; \
89 _result += _temp >> 2; \
92 _result += _temp >> 2; \
95 /* Quadrupling: similar to doubling except * 4. Basically interpolate
96 and write 4 values from src pixels "left" and "right", by setting
97 "temp" = left * 4, then adding "right-left" each time to it and
98 writing that result div 4. Do down for four lines.
100 dstOffset = 4 - 3 * dstRowBytes; /* from 3 lines down to next long */
101 while (nSrcLines-- > 0) { /* double and interpolate next line */
103 if (nSrcLines > 0) /* else use last for below line */
104 pSrcLine += srcRowBytes;
105 pSrcBelow = pSrcLine;
107 pDstLine += dstRowBytes << 2; /* skip down 4 dst lines */
109 nSrcBytesM1 = nSrcBytes - 1;
110 if (nSrcBytesM1 > 0) {
112 leftBelow = *pSrcBelow++;
114 else { /* one pixel; use left as right */
116 leftBelow = *pSrcBelow;
121 delta = right - left;
122 FUPINTER (left, delta, temp0, aLong)
123 *((unsigned long *)pDst) = aLong;
126 rightBelow = *pSrcBelow++;
127 temp0 = (left << 1) + left;
129 temp1 = (right << 1) + right;
131 delta = (temp1 >> 2) - (temp0 >> 2);
132 FUPINTER (temp0>>2, delta, temp0, aLong)
133 *((unsigned long *)pDst) = aLong;
136 temp0 = (left + leftBelow) >> 1;
137 temp1 = (right + rightBelow) >> 1;
138 delta = temp1 - temp0;
140 FUPINTER (temp0>>2, delta, temp0, aLong)
141 *((unsigned long *)pDst) = aLong;
144 temp0 = (leftBelow << 1) + leftBelow;
146 temp1 = (rightBelow << 1) + rightBelow;
148 delta = (temp1 >> 2) - (temp0 >> 2);
149 FUPINTER (temp0>>2, delta, temp0, aLong)
150 *((unsigned long *)pDst) = aLong;
151 pDst += dstOffset; /* bump to next long of first line */
154 leftBelow = rightBelow;
155 if (--nSrcBytesM1 < 0)
156 break; /* last pixel; done */
157 if (nSrcBytesM1 == 0) { /* next-to-last pixel; back up src */
161 } /* END while bytes across */
162 } /* END while lines */
166 /* -------------------------- ilExecuteFastUpsample ------------------------------ */
167 /* Execute(): upsample as necessary "pPriv->nSamples" planes of the source image,
168 where the hori/vertical upsampling factors are equal for each plane.
170 static ilError ilExecuteFastUpsample (
171 ilExecuteData *pData,
176 ilUpFastPrivPtr pPriv;
177 ilImagePlaneInfo *pSrcPlane, *pDstPlane;
178 int sample, subsampleShift;
179 ilPtr pSrcLine, pDstLine;
180 long width, nLines, nSrcLines, nSrcBytes, srcRowBytes, nSrcBytesM2;
182 ilPtr pSrc, pSrcBelow, pDst;
183 int left, leftBelow, right, rightBelow;
185 /* Get width and height of _upsampled_ image; exit if zero. */
186 pPriv = (ilUpFastPrivPtr)pData->pPrivate;
187 nLines = *pNLines; /* # of lines before subsampling */
188 *pNLines = nLines << pPriv->scaleFactor; /* # of dst lines after any scaling */
191 width = pData->pSrcImage->width;
195 /* Loop on samples (components), upsample/translate each plane separately.
196 Note that "srcLine" is shifted - indexing into plane based on vert subsample.
198 pSrcPlane = pData->pSrcImage->plane;
199 pDstPlane = pData->pDstImage->plane;
200 for (sample = 0; sample < pPriv->nSamples; sample++, pSrcPlane++, pDstPlane++) {
201 subsampleShift = pPriv->subsampleShift[sample];
203 srcRowBytes = pSrcPlane->nBytesPerRow;
204 pSrcLine = pSrcPlane->pPixels + (pData->srcLine >> subsampleShift) * srcRowBytes;
205 dstRowBytes = pDstPlane->nBytesPerRow;
206 pDstLine = pDstPlane->pPixels + dstLine * dstRowBytes;
208 /* Handle tiny image: if subsampling left nothing, fill with zeros. */
209 nSrcLines = nLines >> subsampleShift;
210 nSrcBytes = width >> subsampleShift;
211 if ((nSrcLines <= 0) || (nSrcBytes <= 0)) {
214 bzero ((char *)pDstLine, width);
215 pDstLine += dstRowBytes;
219 switch (pPriv->shift[sample]) {
221 /* No upsampling/doubling: just copy this plane */
225 if (srcRowBytes == dstRowBytes)
226 bcopy ((char *)pSrc, (char *)pDst, nSrcBytes * nSrcLines);
227 else while (nSrcLines-- > 0) {
228 bcopy ((char *)pSrc, (char *)pDst, nSrcBytes);
234 /* Doubling: loop while there are a pair of src lines, replicating
235 and interpolating into dst. For each pixel across: do left with
236 interpolated pixel between. For each pixel pair, interpolate
237 between hori and vertically. Replicate last pixel. For last line,
238 point "pSrcBelow" to last src line: replication of last line occurs.
243 while (nSrcLines-- > 0) { /* double and interpolate next line */
245 if (nSrcLines > 0) /* else use last for below line */
246 pSrcLine += srcRowBytes;
247 pSrcBelow = pSrcLine;
249 pDstLine += dstRowBytes << 1; /* skip down 2 dst lines */
251 leftBelow = *pSrcBelow++; /* do first (left) byte */
253 pDst[dstRowBytes] = (left + leftBelow) >> 1;
255 nSrcBytesM2 = nSrcBytes - 2;
256 if (nSrcBytesM2 >= 0) { /* middle bytes with interpolation */
258 rightBelow = *pSrcBelow++;
260 left = (left + right) >> 1;
261 pDst[dstRowBytes] = (left + ((leftBelow + rightBelow) >> 1)) >> 1;
263 pDst[dstRowBytes] = (right + rightBelow) >> 1;
266 leftBelow = rightBelow;
267 } while (--nSrcBytesM2 >= 0);
269 *pDst = left; /* replicate last byte */
270 pDst[dstRowBytes] = (left + leftBelow) >> 1;
271 } /* END while lines */
272 break; /* END doubling */
275 ilUpsampleQuadruple (nSrcLines, nSrcBytes, srcRowBytes, pSrcLine,
276 dstRowBytes, pDstLine);
279 } /* END switch sample's shift */
280 } /* END not tiny image */
281 } /* END for each sample/plane */
286 /* ---------------------------- _ilFastUpsample ----------------------------- */
287 /* Attempt to upsample and scale based on "scaleFactor" (0 = no scaling; 1 = double;
288 2 = 4x), or return false if it cannot be done with the given pipe image (in which
289 case pipe->context->error == 0) or if error occurs (error != 0). Pipe image
290 must be decompressed before calling this function.
291 Note: when scaling up by 2x or 4x, always yields even/ *4 width/height.
292 Thus, *cannot* be used to upsample odd width/height YCbCr images.
294 IL_PRIVATE ilBool _ilFastUpsample (
298 ilImageFormat *pFormat,
302 ilUpFastPrivPtr pUpPriv;
303 ilUpFastPrivRec upPriv;
305 ilYCbCrSampleInfo *pSample;
306 ilDstElementData dstData;
307 ilSrcElementData srcData;
308 const ilImageDes *pNewDes;
310 /* Check image type; return if not handled, else init upPrivRec */
311 pipe->context->error = IL_OK; /* assume no error */
312 pNewDes = (ilImageDes *)NULL; /* assume no descriptor change */
313 upPriv.scaleFactor = scaleFactor;
315 switch (pDes->type) {
317 if (!scaleFactor) return TRUE; /* no scaling is noop; return */
318 if (!ilConvert (pipe, IL_DES_GRAY, IL_FORMAT_BYTE, 0, NULL))
320 upPriv.nSamples = 1; /* double one plane */
321 upPriv.subsampleShift[0] = 0;
322 upPriv.shift[0] = scaleFactor;
323 ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
327 if (!scaleFactor) return TRUE; /* no scaling is noop; return */
328 if (!ilConvert (pipe, IL_DES_RGB, IL_FORMAT_3BYTE_PLANE, 0, NULL))
330 upPriv.nSamples = 3; /* double three planes */
331 upPriv.subsampleShift[0] = upPriv.subsampleShift[1] = upPriv.subsampleShift[2] = 0;
332 upPriv.shift[0] = upPriv.shift[1] = upPriv.shift[2] = scaleFactor;
333 ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
336 /* YCbCr: hori/vert subsample each plane must be equal and must be planar */
338 if (pFormat->sampleOrder != IL_SAMPLE_PLANES)
341 for (i = 0, pSample = pDes->typeInfo.YCbCr.sample; i < 3; i++, pSample++) {
342 if (pSample->subsampleHoriz != pSample->subsampleVert)
344 j = _ilSubsampleShift [pSample->subsampleHoriz];
345 upPriv.subsampleShift[i] = j; /* shift due to subsampling */
346 j += scaleFactor; /* plus that due to scaling */
347 if (j > 2) /* more than 4x scale; can't do */
349 upPriv.shift[i] = j; /* shift due to subsampling and doubling */
351 pNewDes = IL_DES_YCBCR; /* now YCbCr with no subsampling */
355 return FALSE; /* can't handle image type */
358 /* Add the pipe element: width / height scaled if double */
359 dstData.producerObject = (ilObject)NULL;
360 dstData.pDes = pNewDes;
361 dstData.pFormat = pFormat;
362 dstData.width = pInfo->width << scaleFactor;
363 dstData.height = pInfo->height << scaleFactor;
364 dstData.stripHeight = pInfo->stripHeight << scaleFactor;
365 dstData.constantStrip = pInfo->constantStrip;
366 dstData.pPalette = (unsigned short *)NULL;
368 /* Set format: 32 bit alignment required if any scales up by 4x.
369 Don't mark as such if width multiple of 4, as other filters may check it.
371 if (dstData.width & 3) { /* not long-aligned */
372 for (i = 0; i < upPriv.nSamples; i++)
373 if (upPriv.shift[i] == 2) {
374 pFormat->rowBitAlign = 32;
379 /* Use current strip height rather than allowing image to be split into
380 smaller strips; there is a copied rather than smoothed line at the end
381 of each strip, so should do min number of strips. Could force no strips
382 for better quality, but performance penalty probably not worth it.
384 srcData.consumerImage = (ilObject)NULL;
385 srcData.stripHeight = pInfo->stripHeight;
386 srcData.constantStrip = FALSE;
387 srcData.minBufferHeight = 0;
388 pUpPriv = (ilUpFastPrivPtr)ilAddPipeElement (pipe, IL_FILTER,
389 sizeof (ilUpFastPrivRec), 0, &srcData,
390 &dstData, IL_NPF, IL_NPF, IL_NPF, ilExecuteFastUpsample, NULL, 0);
395 ilGetPipeInfo (pipe, FALSE, pInfo, pDes, pFormat);
400 /* ========================== Slow General Code ================================= */
401 /* This code handles the upsampling cases where the vertical and horizontal subsample
402 factors are not the same.
405 /* Upsample factors as shifts (1=0, 2=1, 4=2) - others not supported. */
407 unsigned int horiz, vert;
408 } ilUpsampleShiftRec, *ilUpsampleShiftPtr;
410 /* Private for upsampling filters. */
412 int nSamples; /* # of samples (components) to process */
413 ilUpsampleShiftRec shift[IL_MAX_SAMPLES]; /* upsample mul as shift value */
414 } ilUpsamplePrivRec, *ilUpsamplePrivPtr;
418 /* -------------------------- ilUpsampleHorizontal ------------------------------ */
419 /* Do horizontal upsampling as necessary first, spreading the dst lines
420 based on vertical upsampling.
421 # of lines to do is "height" divided by vertical upsample factor.
423 static void ilUpsampleHorizontal (
424 unsigned int shift, /* 0 = no upsample; 1 = * 2 (doubling); 2 = * 4 */
425 long width, /* width of _whole_ (un-upsampled) image */
426 long nLines, /* # of src lines to upsample */
427 long srcRowBytes, /* bytes / row of src (downsampled) image */
428 ilPtr pSrcLine, /* ptr to first line of src image */
429 long dstRowInc, /* byte offset between dst lines written */
430 ilPtr pDstLine /* ptr to first line of dst image */
433 long nMidPixels, nEndPixels;
436 ilByte pixel, prevPixel;
441 /* Upsample based on "shift", i.e. scale up by 2 ++ "shift". */
444 /* 0: no horizontal upsampling - just copy */
448 while (nLines-- > 0) {
449 bcopy ((char *)pSrc, (char *)pDst, width);
455 /* 1: doubling; The image for this plane is 1/2 "width". Copy the first pixel,
456 interpolate pixels between previous pixels and the last pixel, then replicate
457 last pixel to fill out width. Example: width == 9, source width = 4 (0..3):
459 <0> | <0+1/2> <1> <1+2/2> <2> <2+3/2> <3> | <3> <3>
460 A: write first src pixel (pixel <0>); set into "prevPixel"
461 B: write (interpolated pixel, src pixel) pair "nMidPixels" times, leaving
462 srcPixel in prevPixel
463 C: replicate last pixel (prevPixel) "nEndPixels" times
466 nMidPixels = (width >> 1) - 1;
467 nEndPixels = width - (nMidPixels << 1) - 1;
468 while (nLines-- > 0) {
470 pSrcLine += srcRowBytes;
472 pDstLine += dstRowInc;
474 *pDst++ = prevPixel; /* prevPixel = first src pixel; copy to dst */
475 if (nMidPixels > 0) { /* <interpolated>, <src> pairs */
476 nPixelsM1 = nMidPixels - 1;
479 *pDst++ = (pixel + prevPixel) >> 1;
482 } while (--nPixelsM1 >= 0);
484 if (nEndPixels > 0) {
485 nPixelsM1 = nEndPixels - 1;
488 } while (--nPixelsM1 >= 0);
490 } /* END while lines */
493 /* 1: quadrupling; The image for this plane is 1/4 "width". Copy the first pixel,
494 interpolate pixels between previous pixels and the last pixel, then replicate
495 last pixel to fill out width. To interpolate: add "delta" = pixel-prevPixel
496 to "temp" (which starts at prevPixel*4) then divide temp by 4 before storing.
497 For example, if prevPixel = 3 and pixel = 6, delta = 3, pixels are:
498 3 (prevPixel) | (12+3)/4=3 (15+3)/4=4 (18+3)/4=5 6 (src pixel) |
503 nMidPixels = (width >> 2) - 1;
504 nEndPixels = width - (nMidPixels << 2) - 1;
505 while (nLines-- > 0) {
507 pSrcLine += srcRowBytes;
509 pDstLine += dstRowInc;
511 *pDst++ = prevPixel; /* prevPixel = first src pixel; copy to dst */
512 if (nMidPixels > 0) { /* <3 interpolated>, <src> 4tuples */
513 nPixelsM1 = nMidPixels - 1;
516 delta = pixel - prevPixel;
517 temp = (prevPixel << 2);
526 } while (--nPixelsM1 >= 0);
528 if (nEndPixels > 0) {
529 nPixelsM1 = nEndPixels - 1;
532 } while (--nPixelsM1 >= 0);
534 } /* END while lines */
537 } /* END switch shift */
538 } /* END ilUpsampleHorizontal */
541 /* -------------------------- ilUpsampleVertical ------------------------------ */
542 /* Do vertical upsampling as necessary, after the horizontal upsampling is done.
543 Vertical upsampling is done in the dst buffer: pLine points to first line
544 (which contains an already upsampled line); rowBytes is bytes/row of buffer.
546 static void ilUpsampleVertical (
547 unsigned int shift, /* 0 = no upsample; 1 = * 2 (doubling); 2 = * 4 */
548 long width, /* width of _whole_ (un-upsampled) image */
549 long nLines, /* # of dst lines (after upsampling) */
550 long rowBytes, /* bytes / row in src/dst image */
551 ilPtr pLine /* ptr to first line of src/dst image */
557 /* Return if no pixels or lines to do. */
560 nPixelsM1Init = width - 1;
561 if (nPixelsM1Init < 0)
564 /* Upsample based on "shift", i.e. scale up by 2 ++ "shift". */
567 /* 0: no vertical upsampling; buffer is already complete */
571 /* 1: doubling. Interpolate between pairs of lines, starting with the first
572 and third lines, filling in the second with the average of the two.
575 ilPtr pDst, pSrc1, pSrc2;
577 nLines--; /* don't count first line already in buffer */
578 while (nLines >= 2) { /* two src lines, line between to interpolate */
585 nPixelsM1 = nPixelsM1Init;
587 *pDst++ = (*pSrc1++ + *pSrc2++) >> 1;
588 } while (--nPixelsM1 >= 0);
591 /* Replicate last line to fill out to last line(s) */
593 while (nLines-- > 0) {
595 bcopy ((char *)pLine, (char *)(pDst), width);
600 /* 1: quadrupling. Interpolate between quadruples of lines, starting with lines
601 0 and 4, interpolating 1..3 - see horizontal upsampling.
606 long rowBytesTimes4 = rowBytes << 2;
608 nLines--; /* don't count first line already in buffer */
609 while (nLines >= 4) { /* four src lines, line between to interpolate */
612 pLine += rowBytesTimes4; /* point 4 lines down */
613 nPixelsM1 = nPixelsM1Init;
616 pixel = *pSrc++; /* pixel from top src line; next pixel */
617 delta = *(pDst + rowBytesTimes4) - pixel; /* delta = bottom - top */
618 pixel <<= 2; /* work in pixels * 4, /4 before storing */
621 *pDst = pixel >> 2; /* store one interpolated */
624 *pDst = pixel >> 2; /* store one interpolated */
627 *pDst = pixel >> 2; /* store one interpolated */
628 } while (--nPixelsM1 >= 0);
631 /* Replicate last line to fill out to last line(s) */
633 while (nLines-- > 0) {
635 bcopy ((char *)pLine, (char *)(pDst), width);
638 } /* END quadrupling */
639 } /* END switch shift */
640 } /* END ilUpsampleVertical */
643 /* -------------------------- ilExecuteUpsample ------------------------------- */
644 /* Execute(): upsample as necessary "pPriv->nSamples" planes of the source image.
646 static ilError ilExecuteUpsample (
647 ilExecuteData *pData,
649 long *pNLines /* ignored on input */
652 ilUpsamplePrivPtr pPriv;
653 ilImagePlaneInfo *pSrcPlane, *pDstPlane;
655 ilPtr pSrcLine, pDstLine;
656 long height, width, nLines;
657 long srcRowBytes, dstRowBytes;
658 ilUpsampleShiftPtr pShift;
660 /* Get width and height of _upsampled_ image; exit if zero. */
661 pPriv = (ilUpsamplePrivPtr)pData->pPrivate;
665 width = pData->pSrcImage->width;
669 /* Loop on samples (components), upsample/translate each plane separately.
670 Note that "srcLine" is shifted - indexing into plane based on vert subsample.
672 for (pSrcPlane = pData->pSrcImage->plane, pDstPlane = pData->pDstImage->plane,
673 pShift = pPriv->shift, nSamples = pPriv->nSamples;
675 pSrcPlane++, pDstPlane++, pShift++) {
677 srcRowBytes = pSrcPlane->nBytesPerRow;
678 pSrcLine = pSrcPlane->pPixels + (pData->srcLine >> pShift->vert) * srcRowBytes;
679 dstRowBytes = pDstPlane->nBytesPerRow;
680 pDstLine = pDstPlane->pPixels + dstLine * dstRowBytes;
682 /* Upsample horizontal "height >> pShift->vert" src lines (e.g. half
683 the lines for shift = 1). Write the results starting at pDstLine,
684 each line "dstRowBytes << pShift->vert" bytes after the other, e.g.
685 if pShift->vert is 1 (double), leave one line gap between each dst line.
686 But first, handle very small image: if subsampling left nothing,
687 fill with zeros. Note that small strips will not cause this to happen,
688 because stripHeight checked when element added.
690 nLines = height >> pShift->vert;
691 if ((nLines <= 0) || ((width >> pShift->horiz) <= 0)) {
694 bzero ((char *)pDstLine, width);
695 pDstLine += dstRowBytes;
699 ilUpsampleHorizontal (pShift->horiz, width, nLines,
700 srcRowBytes, pSrcLine, dstRowBytes << pShift->vert, pDstLine);
702 /* Upsample vertically, interpolating between the lines just written. */
703 ilUpsampleVertical (pShift->vert, width, height, dstRowBytes, pDstLine);
710 /* ---------------------------- ilUpsampleYCbCr ----------------------------- */
711 /* Upsample and / or convert to gray the pipe image which must be a YCbCr image.
712 If "toGray" is true, the Y plane only will be upsampled (or copied) resulting
713 in a gray image; else a planar YCbCr image will result.
714 If "upSample" is true must upsample; "upSample" and/or "toGray" must be true.
715 pFormat points to the source format; on return, *pFormat is updated
716 to the dst format, *pDes to the dst descriptor.
718 IL_PRIVATE ilBool _ilUpsampleYCbCr (
722 ilImageFormat *pFormat,
727 ilUpsamplePrivPtr pUpPriv;
729 ilUpsampleShiftRec *pShift;
730 ilYCbCrSampleInfo *pSample;
732 ilDstElementData dstData;
733 ilSrcElementData srcData;
736 /* Only 8 bit planar YCbCr can currently be upsampled; if not that and upsampling
737 needed, error; if no upsampling (only convert to gray) convert to planar.
738 NOTE: can't ilConvert() to planar if upsampling needed as ilConvert() will
739 call this function back to upsample, thereby recursing "forever".
741 if ((pFormat->sampleOrder != IL_SAMPLE_PLANES)
742 || (pFormat->nBitsPerSample[0] != 8)
743 || (pFormat->nBitsPerSample[1] != 8)
744 || (pFormat->nBitsPerSample[2] != 8)) {
746 return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
747 if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_3BYTE_PLANE, 0, NULL))
749 *pFormat = *IL_FORMAT_3BYTE_PLANE;
754 This code currently not included. It tries the "fast" upsampling code, which
755 is in fact faster than the "slow" upsampling code, but for some reason the resulting
756 YCbCr data causes the conversion to RGB to be much slower, probably because more
757 out-of-range (0..255) values are generated which cause the clip code to be hit.
758 For now, the fast upsample code is used only by ilScale(..., IL_SCALE_SAMPLE) for
761 /* Try to use fast upsampling case, but not if "toGray" true, or if width/height
762 of resulting image is not multiple of subsample factor.
765 ilBool tryFast = TRUE;
767 for (sample = 0; sample < 3; sample++) {
768 factor = pDes->typeInfo.YCbCr.sample[sample].subsampleHoriz;
769 if (((factor == 2) && ((pInfo->width | pInfo->height) & 1))
770 || ((factor == 4) && ((pInfo->width | pInfo->height) & 3)))
774 if (_ilFastUpsample (pipe, pInfo, pDes, pFormat, FALSE))
775 return TRUE; /* handled; done */
776 if (pipe->context->error) /* not handled but error; exit */
782 /* Must do "slow" upsample: init dstData for filter(s) to be added. */
784 dstData.producerObject = (ilObject)NULL;
786 dstData.pFormat = pFormat;
787 dstData.width = pInfo->width;
788 dstData.height = pInfo->height;
789 dstData.stripHeight = 0;
790 dstData.constantStrip = FALSE;
791 dstData.pPalette = (unsigned short *)NULL;
793 /* Demand constant strips, a multiple of maximum subsample (4). To avoid the
794 problem of having the last strip have 3 lines or less (and therefore for * 4
795 upsampling require that the previous line be copied - but no previous line
796 available), bump stripHeight by 4 until stripHeight mod 4 > 3, or until
797 requiring whole image as one strip.
801 j = dstData.height % i;
802 if ((j == 0) || (j > 3))
804 if ((i += 4) >= dstData.height) {
809 srcData.consumerImage = (ilObject)NULL;
810 srcData.stripHeight = i;
811 srcData.constantStrip = TRUE;
812 srcData.minBufferHeight = 0;
814 /* Add a filter to upsample; if "toGray" upsample/copy one plane and done. */
816 *pDes = *IL_DES_GRAY;
817 *pFormat = *IL_FORMAT_BYTE;
820 pDes->typeInfo.YCbCr.sample[0].subsampleHoriz = 1;
821 pDes->typeInfo.YCbCr.sample[0].subsampleVert = 1;
822 pDes->typeInfo.YCbCr.sample[1].subsampleHoriz = 1;
823 pDes->typeInfo.YCbCr.sample[1].subsampleVert = 1;
824 pDes->typeInfo.YCbCr.sample[2].subsampleHoriz = 1;
825 pDes->typeInfo.YCbCr.sample[2].subsampleVert = 1; /* des now upsampled */
827 pUpPriv = (ilUpsamplePrivPtr)ilAddPipeElement (pipe, IL_FILTER,
828 sizeof (ilUpsamplePrivRec), 0, &srcData,
829 &dstData, IL_NPF, IL_NPF, IL_NPF, ilExecuteUpsample, NULL, 0);
834 pUpPriv->nSamples = (toGray) ? 1 : 3;
835 pSample = pipeDes.typeInfo.YCbCr.sample;
836 pShift = pUpPriv->shift;
838 for (sample = 0; sample < pUpPriv->nSamples; sample++, pShift++, pSample++) {
839 pShift->horiz = _ilSubsampleShift [pSample->subsampleHoriz];
840 pShift->vert = _ilSubsampleShift [pSample->subsampleVert];