333 lines
12 KiB
C
333 lines
12 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: ilhplrotate.c /main/3 1995/10/23 15:48:20 rswiston $ */
|
|
/**---------------------------------------------------------------------
|
|
***
|
|
*** (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).
|
|
***
|
|
***-------------------------------------------------------------------*/
|
|
|
|
/* =============================================================================================================================
|
|
|
|
/ilc/ilhplrotate.c : Images Library arbitrary rotation routines. using HP-LABs
|
|
image rotation code
|
|
============================================================================================================================= */
|
|
|
|
#include "ilint.h"
|
|
#include "ilpipelem.h"
|
|
#include "ilerrors.h"
|
|
#include "ilhplrotation.h"
|
|
|
|
|
|
typedef struct {
|
|
DATA_IN_PTR data_in; /* pointer to where to put input data */
|
|
DATA_OUT_PTR buf;
|
|
ilBool restart; /* TRUE on pipe re-execution */
|
|
short in_w; /* Arguments to IR_Rotate_Image_Begin */
|
|
short in_h;
|
|
short in_nSPP;
|
|
short mode;
|
|
float degrees;
|
|
unsigned char bg_r, bg_g, bg_b;
|
|
} ilRotatePriv, *ilRotatePrivptr;
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilRotateInit - Init for Rotation for images
|
|
|
|
============================================================================================================================= */
|
|
|
|
|
|
static ilError ilRotateInit2(
|
|
ilRotatePrivptr p,
|
|
ilImageInfo *pSrcImage,
|
|
ilImageInfo *pDstImage
|
|
)
|
|
|
|
{
|
|
DATA_IN_PTR data_in;
|
|
DATA_OUT_PTR buf;
|
|
short out_w, out_h;
|
|
/* Re-Initialize rotation code if necessary */
|
|
if (p->restart) {
|
|
data_in = _il_Rotate_Image_Begin (p->in_w , p->in_h, p->in_nSPP, p->mode,
|
|
p->degrees, p->bg_r, p->bg_g, p->bg_b, &out_w, &out_h);
|
|
|
|
buf = (DATA_OUT_PTR) malloc(out_w * p->in_nSPP);
|
|
if (!buf) {
|
|
return FALSE;
|
|
}
|
|
|
|
p->buf = buf;
|
|
p->data_in = data_in;
|
|
}
|
|
else
|
|
p->restart = TRUE;
|
|
|
|
return IL_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilRotateCleanup - Cleanup for Rotation for images
|
|
|
|
============================================================================================================================= */
|
|
static ilError ilRotateCleanup (
|
|
ilRotatePrivptr pPriv,
|
|
ilBool aborting
|
|
)
|
|
{
|
|
free (pPriv->buf);
|
|
_il_Rotate_Image_End();
|
|
return IL_OK;
|
|
}
|
|
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilRotateExecute - Rotation for images
|
|
|
|
============================================================================================================================= */
|
|
static ilError ilRotateExecute (
|
|
ilExecuteData *pData,
|
|
unsigned long dstLine,
|
|
unsigned long *pNLines
|
|
)
|
|
{
|
|
|
|
|
|
|
|
unsigned char *psrc, *pdst, *psrcline, *pdstline;
|
|
unsigned long srcnbytes, dstnbytes;
|
|
ilImagePlaneInfo *pplane;
|
|
ilRotatePrivptr pPriv;
|
|
int nrows, nlines, nlinesout;
|
|
|
|
if (*pNLines <= 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 = (ilRotatePrivptr) pData->pPrivate;
|
|
|
|
|
|
|
|
nlines = *pNLines;
|
|
nlinesout = 0;
|
|
for (nlines = *pNLines; nlines > 0; nlines--){
|
|
bcopy ((char *) psrcline, (char *) pPriv->data_in, (int) srcnbytes);
|
|
for (nrows = _il_Rotate_Send_Row(&pPriv->data_in);
|
|
nrows > 0; --nrows) {
|
|
_il_Rotate_Get_Row(pPriv->buf);
|
|
bcopy ((char *) pPriv->buf, (char *) pdstline, (int) dstnbytes);
|
|
pdstline += dstnbytes;
|
|
nlinesout++;
|
|
}
|
|
psrcline += srcnbytes;
|
|
}
|
|
*pNLines = nlinesout;
|
|
return IL_OK;
|
|
}
|
|
|
|
|
|
/* =============================================================================================================================
|
|
|
|
ilRotate - Add a rotate filter to an existing pipe for 0 - 90 degree rotations - checking
|
|
for format types and doing an explicit conversion if necessary. Positive factors
|
|
cause clockwise rotations - negative counter clockwise.
|
|
|
|
============================================================================================================================= */
|
|
|
|
ilBool ilRotate(
|
|
ilPipe pipe,
|
|
int degrees,
|
|
int interpMode,
|
|
unsigned long bg_color[]
|
|
)
|
|
|
|
{
|
|
unsigned int state;
|
|
ilPipeInfo info;
|
|
ilRotatePrivptr pPriv;
|
|
ilDstElementData dstdata;
|
|
ilImageDes imdes;
|
|
ilImageFormat imformat;
|
|
ilBool convert;
|
|
unsigned int rtype;
|
|
short out_w, out_h, nrows;
|
|
DATA_IN_PTR data_in;
|
|
DATA_OUT_PTR buf;
|
|
|
|
#define PIPE_FLAGS
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/* 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 */
|
|
if (imdes.type == IL_PALETTE &&
|
|
interpMode != IL_ROTATE_SIMPLE) {
|
|
imdes.type = IL_RGB;
|
|
convert = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 1: /* Bitonal */
|
|
return ilDeclarePipeInvalid
|
|
(pipe, IL_ERROR_NOT_IMPLEMENTED);
|
|
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);
|
|
}
|
|
|
|
|
|
/* Determine rotation type */
|
|
|
|
degrees %= 360;
|
|
if (degrees < 0) degrees += 360;
|
|
/*
|
|
* temporarily, special code can only handle 0 - 90 rotation
|
|
* also, code rotates ccw, but we want to rotate clockwise.
|
|
*/
|
|
if (!ilRotate90(pipe, (degrees+89)/90)) return FALSE;
|
|
ilGetPipeInfo (pipe, FALSE, &info, (ilImageDes *)NULL, (ilImageFormat *)NULL);
|
|
degrees = 90 - (degrees % 90);
|
|
|
|
/* check if 90 deg rotations is sufficient */
|
|
|
|
if (degrees == 90) {pipe->context->error = IL_OK; return TRUE;}
|
|
|
|
data_in = _il_Rotate_Image_Begin ( (short) info.width, (short) info.height,
|
|
(short) imdes.nSamplesPerPixel, (short) interpMode,
|
|
(float) degrees,
|
|
(unsigned char) bg_color[0], (unsigned char) bg_color[1], (unsigned char) bg_color[2],
|
|
&out_w, &out_h);
|
|
|
|
dstdata.producerObject = (ilObject) NULL;
|
|
dstdata.pDes = (ilImageDes *) NULL;
|
|
dstdata.pFormat = (ilImageFormat *) NULL;
|
|
dstdata.pPalette = info.pPalette;
|
|
|
|
dstdata.width = out_w;
|
|
dstdata.height = out_h;
|
|
|
|
/* set output strip height */
|
|
dstdata.stripHeight = dstdata.height;
|
|
dstdata.constantStrip = FALSE;
|
|
|
|
|
|
pPriv = (ilRotatePrivptr) ilAddPipeElement (pipe, IL_FILTER,
|
|
sizeof(ilRotatePriv), IL_ADD_PIPE_HOLD_DST,
|
|
(ilSrcElementData *) NULL, &dstdata, ilRotateInit2,
|
|
ilRotateCleanup, IL_NPF, ilRotateExecute, 0);
|
|
|
|
if(!pPriv)
|
|
return FALSE;
|
|
|
|
buf = (DATA_OUT_PTR) malloc(out_w * (short) imdes.nSamplesPerPixel);
|
|
if (!buf) {
|
|
pipe->context->error = IL_ERROR_MALLOC;
|
|
free(pPriv);
|
|
return FALSE;
|
|
}
|
|
|
|
pPriv->buf = buf;
|
|
pPriv->data_in = data_in;
|
|
pPriv->restart = FALSE;
|
|
|
|
/* Arguments to IR_Rotate_Image_Begin */
|
|
pPriv->in_w = (short) info.width ;
|
|
pPriv->in_h = (short) info.height;
|
|
pPriv->in_nSPP = (short) imdes.nSamplesPerPixel;
|
|
pPriv->mode = (short) interpMode;
|
|
pPriv->degrees = (float) degrees;
|
|
pPriv->bg_r = (unsigned char) bg_color[0];
|
|
pPriv->bg_g = (unsigned char) bg_color[1];
|
|
pPriv->bg_b = (unsigned char) bg_color[2];
|
|
|
|
pipe->context->error = IL_OK;
|
|
return TRUE;
|
|
}
|
|
|
|
|