965 lines
32 KiB
C
965 lines
32 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: ilscale.c /main/6 1996/09/24 17:13:24 drk $ */
|
|
/**---------------------------------------------------------------------
|
|
***
|
|
*** (c)Copyright 1991 Hewlett-Packard Co.
|
|
***
|
|
*** RESTRICTED RIGHTS LEGEND
|
|
*** Use, duplication, or disclosure by the U.S. Government is subject to
|
|
*** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
|
|
*** Technical Data and Computer Software clause in DFARS 252.227-7013.
|
|
*** Hewlett-Packard Company
|
|
*** 3000 Hanover Street
|
|
*** Palo Alto, CA 94304 U.S.A.
|
|
*** Rights for non-DOD U.S. Government Departments and Agencies are as set
|
|
*** forth in FAR 52.227-19(c)(1,2).
|
|
***
|
|
***-------------------------------------------------------------------*/
|
|
|
|
#include "ilint.h"
|
|
#include "ilpipelem.h"
|
|
#include "ilscaleint.h"
|
|
#include "ilerrors.h"
|
|
#include "ilconvert.h"
|
|
|
|
#define LONGSZ 4
|
|
#ifdef LSB_BIT_ORDER
|
|
# define SPECIAL_MASK_BIT 0x00000001 /* for LSB bit order */
|
|
# define SHIFT_MASK(m) ((m) <<= 1)
|
|
#else
|
|
# define SPECIAL_MASK_BIT 0x80000000 /* for MSB bit order */
|
|
# define SHIFT_MASK(m) ((m) >>= 1)
|
|
#endif
|
|
|
|
|
|
typedef struct {
|
|
long ilScaleAccDown; /* accumulator value used in scale down algorithm */
|
|
long ilScaleAccUp; /* accumulator value used in scale up algorithm */
|
|
long ilScaleDstheight; /* destination height value saved to avoid strip sizes */
|
|
long ilScaleSrcheight; /* src height value saved to avoid strip sizes */
|
|
} ilScalePriv, *ilScalePrivptr;
|
|
|
|
#ifdef LSB_BIT_ORDER
|
|
extern void flip_bits(ilPtr start, unsigned n);
|
|
#else
|
|
# define flip_bits(start,n) /*EMPTY*/
|
|
#endif
|
|
|
|
|
|
/* =============================================================================================================================
|
|
ilScaleInit - Initialization function for a scale filter performed with the
|
|
method of replication/decimation. This gets called when the pipe
|
|
is executed for the first time.
|
|
============================================================================================================================= */
|
|
|
|
|
|
static ilError ilScaleInit(
|
|
ilScalePrivptr pPrivate,
|
|
ilImageInfo *pSrcImage,
|
|
ilImageInfo *pDstImage
|
|
)
|
|
|
|
{
|
|
pPrivate->ilScaleAccDown = pPrivate->ilScaleSrcheight - pPrivate->ilScaleDstheight;
|
|
pPrivate->ilScaleAccUp = pPrivate->ilScaleDstheight - pPrivate->ilScaleSrcheight;
|
|
|
|
return IL_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
ilswbitdown - Routine to scale down the width of an image by decimation.
|
|
Operates on bitonal images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilswbitdown(
|
|
CARD32 *psrcline,
|
|
CARD32 *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, nbits;
|
|
CARD32 srcMask;
|
|
CARD32 srcLong;
|
|
CARD32 dstLong;
|
|
ilBool copy;
|
|
ilBool Lastbit;
|
|
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
|
|
srcLong = *psrcline++;
|
|
dstLong = 1;
|
|
Lastbit = FALSE;
|
|
|
|
acc = srcwidth - dstwidth;
|
|
copy = (acc == 0) ? TRUE : FALSE;
|
|
|
|
nbits = dstwidth;
|
|
|
|
if(copy == TRUE) { /* degenerate case optimized */
|
|
|
|
while (nbits-- ) {
|
|
|
|
/* copy bit logic */
|
|
dstLong <<= 1;
|
|
if (srcMask & srcLong) dstLong++;
|
|
|
|
if(Lastbit) {
|
|
|
|
flip_bits((ilPtr)&dstLong, sizeof(dstLong));
|
|
|
|
*pdstline++ = dstLong;
|
|
dstLong = 1;
|
|
Lastbit = FALSE;
|
|
}
|
|
|
|
|
|
/* See if the last bit in the word is coming */
|
|
if( (INT32) dstLong < 0) Lastbit = TRUE;
|
|
|
|
SHIFT_MASK(srcMask);
|
|
if (!srcMask) { /* after 32 bits reset mask and get new srcline */
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
srcLong = *psrcline++;
|
|
}
|
|
|
|
} /* End While */
|
|
|
|
}
|
|
else { /* scale down algorithm */
|
|
|
|
|
|
while (nbits-- ) {
|
|
|
|
for(; acc > 0; acc -= dstwidth) { /* skip bits according to scale ratio */
|
|
|
|
SHIFT_MASK(srcMask);
|
|
|
|
if (!srcMask) { /* after 32 bits reset mask and get new srcline */
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
srcLong = *psrcline++;
|
|
}
|
|
}
|
|
acc += (srcwidth - dstwidth);
|
|
|
|
|
|
/* copy bit logic */
|
|
dstLong <<= 1;
|
|
if (srcMask & srcLong) dstLong++;
|
|
|
|
if(Lastbit) {
|
|
|
|
flip_bits((ilPtr)&dstLong, sizeof(dstLong));
|
|
|
|
*pdstline++ = dstLong;
|
|
dstLong = 1;
|
|
Lastbit = FALSE;
|
|
}
|
|
|
|
|
|
/* See if the last bit in the word is coming */
|
|
if( (INT32) dstLong < 0) Lastbit = TRUE;
|
|
|
|
SHIFT_MASK(srcMask);
|
|
if (!srcMask) { /* after 32 bits reset mask and get new srcline */
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
srcLong = *psrcline++;
|
|
}
|
|
|
|
|
|
} /* End While */
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Shift up and write out any last bits */
|
|
|
|
if (dstLong != 1) { /* has data not copied to pdstline */
|
|
while ( (INT32) dstLong > 0) dstLong <<= 1; /* shift up */
|
|
dstLong <<= 1;
|
|
flip_bits((ilPtr)&dstLong, sizeof(dstLong));
|
|
*pdstline++ = dstLong;
|
|
}
|
|
|
|
}
|
|
|
|
/* =============================================================================================================================
|
|
ilswbitup - Routine to scale up the width of an image by replication.
|
|
Operates on bitonal images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilswbitup(
|
|
CARD32 *psrcline,
|
|
CARD32 *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, nbits;
|
|
CARD32 srcMask;
|
|
CARD32 srcLong;
|
|
CARD32 dstLong;
|
|
ilBool Lastbit;
|
|
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
|
|
srcLong = *psrcline++;
|
|
dstLong = 1;
|
|
Lastbit = FALSE;
|
|
|
|
acc = dstwidth - srcwidth;
|
|
nbits = srcwidth;
|
|
|
|
while (nbits-- ) {
|
|
|
|
for(; acc >= 0; acc -= srcwidth) { /* keep copying */
|
|
|
|
/* copy bit logic */
|
|
dstLong <<= 1;
|
|
if (srcMask & srcLong) dstLong++;
|
|
|
|
if(Lastbit) {
|
|
|
|
flip_bits((ilPtr)&dstLong, sizeof(dstLong));
|
|
|
|
*pdstline++ = dstLong;
|
|
dstLong = 1;
|
|
Lastbit = FALSE;
|
|
}
|
|
|
|
/* See if the last bit in the word is coming */
|
|
if( (INT32) dstLong < 0) Lastbit = TRUE;
|
|
}
|
|
|
|
|
|
acc += dstwidth;
|
|
|
|
/* increment the mask to the next src bit */
|
|
SHIFT_MASK(srcMask);
|
|
|
|
if (!srcMask) { /* after 32 bits reset mask and get new srcline */
|
|
srcMask = SPECIAL_MASK_BIT;
|
|
srcLong = *psrcline++;
|
|
}
|
|
|
|
} /* End While */
|
|
|
|
|
|
/* Shift up and write out any last bits */
|
|
|
|
if (dstLong != 1) { /* has data not copied to pdstline */
|
|
while ( (INT32) dstLong > 0) dstLong <<= 1; /* shift up */
|
|
dstLong <<= 1;
|
|
flip_bits((ilPtr)&dstLong, sizeof(dstLong));
|
|
*pdstline++ = dstLong;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
ilsw3bytedown - Routine to scale down the width of an image by decimation.
|
|
Operates on 24 bit images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilsw3bytedown(
|
|
unsigned char *psrcline,
|
|
unsigned char *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, n3bytes;
|
|
ilBool copy;
|
|
|
|
|
|
acc = srcwidth - dstwidth;
|
|
copy = (acc == 0) ? TRUE : FALSE;
|
|
|
|
n3bytes = dstwidth;
|
|
|
|
if(copy == TRUE) { /* degenerate case optimized */
|
|
while (n3bytes--) {
|
|
*pdstline++ = *psrcline++; /* 3 Bytes to copy */
|
|
*pdstline++ = *psrcline++;
|
|
*pdstline++ = *psrcline++;
|
|
}
|
|
}
|
|
else { /* scale down algorithm */
|
|
|
|
while (n3bytes--) {
|
|
|
|
for(; acc > 0; acc -= dstwidth) psrcline += 3;
|
|
acc += (srcwidth - dstwidth);
|
|
|
|
*pdstline++ = *psrcline++; /* 3 Bytes to copy */
|
|
*pdstline++ = *psrcline++;
|
|
*pdstline++ = *psrcline++;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* =============================================================================================================================
|
|
ilsw3byteup - Routine to scale up the width of an image by replication.
|
|
Operates on 24 bit images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilsw3byteup(
|
|
unsigned char *psrcline,
|
|
unsigned char *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, n3bytes;
|
|
|
|
acc = dstwidth - srcwidth;
|
|
n3bytes = srcwidth;
|
|
|
|
while (n3bytes--) {
|
|
|
|
for(; acc >= 0; acc -= srcwidth) {
|
|
*pdstline++ = *psrcline;
|
|
*pdstline++ = *(psrcline + 1);
|
|
*pdstline++ = *(psrcline + 2);
|
|
}
|
|
|
|
acc += dstwidth;
|
|
psrcline += 3;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
ilswbytedown - Routine to scale down the width of an image by decimation.
|
|
Operates on 8 bit images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilswbytedown(
|
|
unsigned char *psrcline,
|
|
unsigned char *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, nbytes;
|
|
ilBool copy;
|
|
|
|
|
|
acc = srcwidth - dstwidth;
|
|
copy = (acc == 0) ? TRUE : FALSE;
|
|
|
|
nbytes = dstwidth;
|
|
|
|
if(copy == TRUE) { /* degenerate case optimized */
|
|
while (nbytes-- ) *pdstline++ = *psrcline++;
|
|
}
|
|
else { /* scale down algorithm */
|
|
|
|
while (nbytes-- ) {
|
|
|
|
for(; acc > 0; acc -= dstwidth) psrcline++;
|
|
acc += (srcwidth - dstwidth);
|
|
|
|
*pdstline++ = *psrcline++;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* =============================================================================================================================
|
|
ilswbyteup - Routine to scale up the width of an image by replication.
|
|
Operates on 8 bit images.
|
|
============================================================================================================================= */
|
|
|
|
static void ilswbyteup(
|
|
unsigned char *psrcline,
|
|
unsigned char *pdstline,
|
|
unsigned long srcwidth,
|
|
unsigned long dstwidth
|
|
)
|
|
|
|
{
|
|
int acc, nbytes;
|
|
|
|
acc = dstwidth - srcwidth;
|
|
nbytes = srcwidth;
|
|
|
|
while (nbytes--) {
|
|
|
|
for(; acc >= 0; acc -= srcwidth) *pdstline++ = *psrcline;
|
|
|
|
acc += dstwidth;
|
|
psrcline++;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilScaleBitonalExecute - Scale processing for images with bit per pixel format .
|
|
This function that will get called at least once when the
|
|
pipe is executed. This routine loops through the number of
|
|
lines, scaling the height and calls the appropriate function
|
|
to scale the width.
|
|
============================================================================================================================= */
|
|
static ilError ilScaleBitonalExecute (
|
|
ilExecuteData *pData,
|
|
unsigned long dstLine,
|
|
unsigned long *pNLines
|
|
)
|
|
{
|
|
CARD32 *psrcline, *pdstline;
|
|
unsigned long srcnwords, dstnwords;
|
|
long nlines;
|
|
unsigned long srcwidth, dstwidth;
|
|
ilImagePlaneInfo *pplane;
|
|
unsigned long local_noDstLine;
|
|
ilScalePrivptr pPriv;
|
|
|
|
|
|
|
|
nlines = *pNLines;
|
|
if (nlines <= 0) return IL_OK;
|
|
|
|
pplane = &pData->pSrcImage->plane[0];
|
|
srcnwords = (pplane->nBytesPerRow + LONGSZ - 1)/LONGSZ;
|
|
psrcline = (CARD32 *) (pplane->pPixels) + pData->srcLine * srcnwords;
|
|
|
|
pplane = &pData->pDstImage->plane[0];
|
|
dstnwords = (pplane->nBytesPerRow + LONGSZ - 1)/LONGSZ;
|
|
pdstline = (CARD32 *) (pplane->pPixels) + dstLine * dstnwords;
|
|
pPriv = (ilScalePrivptr) pData->pPrivate;
|
|
|
|
srcwidth = pData->pSrcImage->width;
|
|
dstwidth = pData->pDstImage->width;
|
|
|
|
local_noDstLine = 0;
|
|
|
|
|
|
|
|
if (pPriv->ilScaleSrcheight == pPriv->ilScaleDstheight) { /* copy case optimized */
|
|
|
|
while (nlines-- > 0) {
|
|
if(srcwidth >= dstwidth)
|
|
ilswbitdown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbitup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnwords;
|
|
pdstline += dstnwords;
|
|
}
|
|
}
|
|
else if (pPriv->ilScaleSrcheight > pPriv->ilScaleDstheight) { /* scale height down */
|
|
|
|
while (TRUE) {
|
|
while (pPriv->ilScaleAccDown > 0) {
|
|
if (nlines-- <= 0)
|
|
break;
|
|
pPriv->ilScaleAccDown -= pPriv->ilScaleDstheight;
|
|
psrcline += srcnwords;
|
|
}
|
|
if (nlines-- <= 0)
|
|
break;
|
|
|
|
pPriv->ilScaleAccDown += (pPriv->ilScaleSrcheight - pPriv->ilScaleDstheight);
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilswbitdown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbitup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnwords;
|
|
pdstline += dstnwords;
|
|
}
|
|
|
|
}
|
|
else if (pPriv->ilScaleSrcheight < pPriv->ilScaleDstheight) { /* scale height up */
|
|
|
|
while (nlines-- > 0) {
|
|
|
|
for(; pPriv->ilScaleAccUp >= 0; pPriv->ilScaleAccUp -= pPriv->ilScaleSrcheight) {
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilswbitdown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbitup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
pdstline += dstnwords;
|
|
}
|
|
|
|
pPriv->ilScaleAccUp += pPriv->ilScaleDstheight;
|
|
psrcline += srcnwords;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
*pNLines = local_noDstLine;
|
|
return IL_OK;
|
|
|
|
}
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilScale3ByteExecute - Scale processing for images with 24 bits per pixel format .
|
|
This function that will get called at least once when the
|
|
pipe is executed. This routine loops through the number of
|
|
lines, scaling the height and calls the appropriate function
|
|
to scale the width.
|
|
============================================================================================================================= */
|
|
static ilError ilScale3ByteExecute (
|
|
ilExecuteData *pData,
|
|
unsigned long dstLine,
|
|
unsigned long *pNLines
|
|
)
|
|
{
|
|
unsigned char *psrcline, *pdstline;
|
|
unsigned long srcnbytes, dstnbytes;
|
|
long nlines;
|
|
unsigned long srcwidth, dstwidth;
|
|
ilImagePlaneInfo *pplane;
|
|
unsigned long local_noDstLine;
|
|
ilScalePrivptr pPriv;
|
|
|
|
|
|
|
|
nlines = *pNLines;
|
|
if (nlines <= 0) return IL_OK;
|
|
|
|
pplane = &pData->pSrcImage->plane[0];
|
|
srcnbytes = pplane->nBytesPerRow;
|
|
psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
|
|
|
|
pplane = &pData->pDstImage->plane[0];
|
|
dstnbytes = pplane->nBytesPerRow;
|
|
pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
|
|
pPriv = (ilScalePrivptr) pData->pPrivate;
|
|
|
|
|
|
srcwidth = pData->pSrcImage->width;
|
|
dstwidth = pData->pDstImage->width;
|
|
|
|
local_noDstLine = 0;
|
|
|
|
|
|
|
|
if (pPriv->ilScaleSrcheight == pPriv->ilScaleDstheight) { /* copy case optimized */
|
|
|
|
while (nlines-- > 0) {
|
|
if(srcwidth >= dstwidth)
|
|
ilsw3bytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilsw3byteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnbytes;
|
|
pdstline += dstnbytes;
|
|
}
|
|
}
|
|
else if (pPriv->ilScaleSrcheight > pPriv->ilScaleDstheight) { /* scale height down */
|
|
|
|
while (TRUE) {
|
|
while (pPriv->ilScaleAccDown > 0) {
|
|
if (nlines-- <= 0)
|
|
break;
|
|
pPriv->ilScaleAccDown -= pPriv->ilScaleDstheight;
|
|
psrcline += srcnbytes;
|
|
}
|
|
if (nlines-- <= 0)
|
|
break;
|
|
|
|
pPriv->ilScaleAccDown += (pPriv->ilScaleSrcheight - pPriv->ilScaleDstheight);
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilsw3bytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilsw3byteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnbytes;
|
|
pdstline += dstnbytes;
|
|
}
|
|
|
|
}
|
|
else if (pPriv->ilScaleSrcheight < pPriv->ilScaleDstheight) { /* scale height up */
|
|
|
|
while (nlines-- > 0) {
|
|
|
|
for(; pPriv->ilScaleAccUp >= 0; pPriv->ilScaleAccUp -= pPriv->ilScaleSrcheight) {
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilsw3bytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilsw3byteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
pdstline += dstnbytes;
|
|
}
|
|
|
|
pPriv->ilScaleAccUp += pPriv->ilScaleDstheight;
|
|
psrcline += srcnbytes;
|
|
}
|
|
|
|
}
|
|
|
|
*pNLines = local_noDstLine;
|
|
return IL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilScaleByteExecute - Scale processing for images with byte per pixel format .
|
|
This function that will get called at least once when the
|
|
pipe is executed. This routine loops through the number of
|
|
lines, scaling the height and calls the appropriate function
|
|
to scale the width.
|
|
============================================================================================================================= */
|
|
static ilError ilScaleByteExecute (
|
|
ilExecuteData *pData,
|
|
unsigned long dstLine,
|
|
unsigned long *pNLines
|
|
)
|
|
{
|
|
unsigned char *psrcline, *pdstline;
|
|
unsigned long srcnbytes, dstnbytes;
|
|
long nlines;
|
|
unsigned long srcwidth, dstwidth;
|
|
ilImagePlaneInfo *pplane;
|
|
unsigned long local_noDstLine;
|
|
ilScalePrivptr pPriv;
|
|
|
|
|
|
|
|
nlines = *pNLines;
|
|
if (nlines <= 0) return IL_OK;
|
|
|
|
pplane = &pData->pSrcImage->plane[0];
|
|
srcnbytes = pplane->nBytesPerRow;
|
|
psrcline = (unsigned char *) (pplane->pPixels) + pData->srcLine * srcnbytes;
|
|
|
|
pplane = &pData->pDstImage->plane[0];
|
|
dstnbytes = pplane->nBytesPerRow;
|
|
pdstline = (unsigned char *) (pplane->pPixels) + dstLine * dstnbytes;
|
|
pPriv = (ilScalePrivptr) pData->pPrivate;
|
|
|
|
|
|
srcwidth = pData->pSrcImage->width;
|
|
dstwidth = pData->pDstImage->width;
|
|
|
|
local_noDstLine = 0;
|
|
|
|
|
|
if (pPriv->ilScaleSrcheight == pPriv->ilScaleDstheight) { /* copy case optimized */
|
|
|
|
while (nlines-- > 0) {
|
|
if(srcwidth >= dstwidth)
|
|
ilswbytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbyteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnbytes;
|
|
pdstline += dstnbytes;
|
|
}
|
|
}
|
|
else if (pPriv->ilScaleSrcheight > pPriv->ilScaleDstheight ) { /* scale height down */
|
|
|
|
while (TRUE) {
|
|
while (pPriv->ilScaleAccDown > 0) {
|
|
if (nlines-- <= 0)
|
|
break;
|
|
pPriv->ilScaleAccDown -= pPriv->ilScaleDstheight;
|
|
psrcline += srcnbytes;
|
|
}
|
|
if (nlines-- <= 0)
|
|
break;
|
|
|
|
pPriv->ilScaleAccDown += (pPriv->ilScaleSrcheight - pPriv->ilScaleDstheight);
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilswbytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbyteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
psrcline += srcnbytes;
|
|
pdstline += dstnbytes;
|
|
}
|
|
|
|
}
|
|
else if (pPriv->ilScaleSrcheight < pPriv->ilScaleDstheight ) { /* scale height up */
|
|
|
|
while (nlines-- > 0) {
|
|
|
|
for(; pPriv->ilScaleAccUp >= 0; pPriv->ilScaleAccUp -= pPriv->ilScaleSrcheight) {
|
|
|
|
if(srcwidth >= dstwidth)
|
|
ilswbytedown (psrcline, pdstline, srcwidth, dstwidth);
|
|
else if (srcwidth < dstwidth)
|
|
ilswbyteup (psrcline, pdstline, srcwidth, dstwidth);
|
|
|
|
local_noDstLine++;
|
|
pdstline += dstnbytes;
|
|
}
|
|
|
|
pPriv->ilScaleAccUp += pPriv->ilScaleDstheight ;
|
|
psrcline += srcnbytes;
|
|
}
|
|
|
|
}
|
|
|
|
*pNLines = local_noDstLine;
|
|
return IL_OK;
|
|
|
|
}
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilScale - This is the pipe constructor function that is called by the
|
|
application to Add a scale filter to an existing pipe.
|
|
This routine will check for format types and do an explicit
|
|
conversion if necessary.
|
|
============================================================================================================================= */
|
|
ilBool ilScale (
|
|
ilPipe pipe,
|
|
long dstWidth,
|
|
long dstHeight,
|
|
int option,
|
|
void *pOptionData
|
|
)
|
|
|
|
{
|
|
unsigned int state;
|
|
ilPipeInfo info;
|
|
ilScalePrivptr pPriv = NULL;
|
|
ilDstElementData dstdata;
|
|
ilImageDes imdes;
|
|
ilImageFormat imformat;
|
|
ilBool convert;
|
|
ilBool bitonal;
|
|
static unsigned long defaultNGrays = 256;
|
|
static unsigned long defaultBitonalThreshold = 192;
|
|
|
|
/* Get ptr to pipe info and check state */
|
|
|
|
state = ilGetPipeInfo(pipe, TRUE, &info, &imdes, &imformat);
|
|
if(state != IL_PIPE_FORMING) {
|
|
if (!pipe->context->error)
|
|
ilDeclarePipeInvalid(pipe, IL_ERROR_PIPE_STATE);
|
|
return FALSE;
|
|
}
|
|
|
|
/* if scale is by exactly 2x or 4x, try to use fast scale code */
|
|
if (option == IL_SCALE_SAMPLE) {
|
|
int scaleFactor;
|
|
if (((info.width << 1) == dstWidth) && ((info.height << 1) == dstHeight))
|
|
scaleFactor = 1;
|
|
else if (((info.width << 2) == dstWidth) && ((info.height << 2) == dstHeight))
|
|
scaleFactor = 2;
|
|
else scaleFactor = 0;
|
|
if (scaleFactor) {
|
|
if (_ilFastUpsample (pipe, &info, &imdes, &imformat, scaleFactor))
|
|
return TRUE; /* scale filter added; exit */
|
|
else if (pipe->context->error)
|
|
return FALSE; /* error occurred; exit */
|
|
}
|
|
}
|
|
|
|
bitonal = FALSE;
|
|
|
|
/* Check for valid Formats */
|
|
convert = FALSE;
|
|
|
|
switch (imdes.nSamplesPerPixel) {
|
|
case 3: /* RGB or YUV */
|
|
if(imformat.sampleOrder != IL_SAMPLE_PIXELS) {
|
|
imformat.sampleOrder = IL_SAMPLE_PIXELS;
|
|
convert = TRUE;
|
|
}
|
|
|
|
if((imformat.nBitsPerSample[0] != 8) ||
|
|
(imformat.nBitsPerSample[1] != 8) ||
|
|
(imformat.nBitsPerSample[2] != 8)) {
|
|
|
|
imformat.nBitsPerSample[0] = 8;
|
|
imformat.nBitsPerSample[1] = 8;
|
|
imformat.nBitsPerSample[2] = 8;
|
|
convert = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
switch (imformat.nBitsPerSample[0]) {
|
|
case 8: /* Byte per pixel */
|
|
break;
|
|
|
|
case 1: /* Bitonal */
|
|
bitonal = TRUE;
|
|
if (imformat.rowBitAlign != 32) {
|
|
imformat.rowBitAlign = 32;
|
|
convert = TRUE;
|
|
}
|
|
break;
|
|
|
|
default: /* something other than 1 - try 8 */
|
|
imformat.nBitsPerSample[0] = 8;
|
|
convert = TRUE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return ilDeclarePipeInvalid(pipe, IL_ERROR_NOT_IMPLEMENTED);
|
|
}
|
|
|
|
|
|
if(convert) {
|
|
if (!ilConvert(pipe, &imdes, &imformat, 0, NULL))
|
|
return FALSE;
|
|
ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
|
|
}
|
|
if((dstWidth <= 0) || (dstHeight <= 0))
|
|
return ilDeclarePipeInvalid(pipe, IL_ERROR_ZERO_SIZE_IMAGE);
|
|
|
|
switch (option) {
|
|
case IL_SCALE_SIMPLE:
|
|
|
|
if ((dstWidth == info.width) && (dstHeight == info.height)) return TRUE;
|
|
break;
|
|
|
|
case IL_SCALE_SAMPLE:
|
|
|
|
/* demotion to simple if not scaling down */
|
|
if ((info.width < dstWidth) || (info.height < dstHeight)) break;
|
|
|
|
if ( ((dstWidth == info.width) && (dstHeight == info.height)) &&
|
|
((!bitonal) || (!pOptionData)) ) return TRUE;
|
|
|
|
|
|
/* if a palette image first convert to RGB */
|
|
if (imdes.type == IL_PALETTE) {
|
|
if (!ilConvert (pipe, IL_DES_RGB, IL_FORMAT_3BYTE_PIXEL, 0, (ilPtr)NULL))
|
|
return FALSE;
|
|
ilGetPipeInfo (pipe, FALSE, &info, &imdes, &imformat);
|
|
}
|
|
|
|
if (bitonal) {
|
|
/* Use default threshold if not supplied */
|
|
if (!pOptionData) pOptionData = &defaultBitonalThreshold;
|
|
_ilAreaScaleBitonal (pipe, dstWidth, dstHeight, (int *)pOptionData, &info);
|
|
}
|
|
else
|
|
_ilScaleSample (pipe, imdes.nSamplesPerPixel, dstWidth, dstHeight,
|
|
256, imdes.blackIsZero, &info);
|
|
return (pipe->context->error) ? FALSE : TRUE;
|
|
|
|
case IL_SCALE_BITONAL_TO_GRAY:
|
|
|
|
/* Error condition if not scaling down (no demotion) or if the image
|
|
is not bitonal. If pOptionData is null, default to 256 levels of gray.
|
|
*/
|
|
if (!pOptionData) pOptionData = &defaultNGrays;
|
|
if ((info.width < dstWidth) || (info.height < dstHeight) || !bitonal)
|
|
return ilDeclarePipeInvalid(pipe, IL_ERROR_SCALE_BITONAL_TO_GRAY);
|
|
|
|
_ilScaleBitonalToGray (pipe, dstWidth, dstHeight,
|
|
*((unsigned long *)pOptionData), imdes.blackIsZero, &info);
|
|
return (pipe->context->error) ? FALSE : TRUE;
|
|
|
|
default:
|
|
return ilDeclarePipeInvalid(pipe, IL_ERROR_INVALID_OPTION);
|
|
}
|
|
|
|
|
|
|
|
|
|
dstdata.producerObject = (ilObject) NULL;
|
|
dstdata.pDes = (ilImageDes *) NULL;
|
|
dstdata.pFormat = (ilImageFormat *) NULL;
|
|
dstdata.width = dstWidth;
|
|
dstdata.height = dstHeight;
|
|
dstdata.pPalette = info.pPalette;;
|
|
|
|
/* set output strip height */
|
|
dstdata.stripHeight = (dstHeight * info.recommendedStripHeight)/info.height + 1;
|
|
dstdata.constantStrip = FALSE;
|
|
|
|
switch (imdes.nSamplesPerPixel) {
|
|
case 3:
|
|
pPriv = (ilScalePrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilScalePriv), 0, (ilSrcElementData *) NULL,
|
|
&dstdata, ilScaleInit, IL_NPF, IL_NPF, ilScale3ByteExecute, NULL, 0);
|
|
break;
|
|
|
|
case 1:
|
|
if(bitonal)
|
|
pPriv = (ilScalePrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilScalePriv), 0, (ilSrcElementData *) NULL,
|
|
&dstdata, ilScaleInit, IL_NPF, IL_NPF, ilScaleBitonalExecute, NULL, 0);
|
|
else
|
|
pPriv = (ilScalePrivptr) ilAddPipeElement(pipe, IL_FILTER, sizeof(ilScalePriv), 0, (ilSrcElementData *) NULL,
|
|
&dstdata, ilScaleInit, IL_NPF, IL_NPF, ilScaleByteExecute, NULL, 0);
|
|
}
|
|
|
|
if(!pPriv)
|
|
return FALSE;
|
|
|
|
/* Save away true heights */
|
|
pPriv->ilScaleDstheight = dstHeight;
|
|
pPriv->ilScaleSrcheight = info.height;
|
|
|
|
pipe->context->error = IL_OK;
|
|
return TRUE;
|
|
}
|
|
|