cdesktopenv/cde/lib/DtHelp/il/ilhplrotate.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;
}