jedi-outcast/utils/roq2/libim/imvfbadjust.c

1810 lines
25 KiB
C
Raw Permalink Normal View History

2013-04-22 05:25:59 +00:00
/**
** $Header: /roq/libim/imvfbadjust.c 1 11/02/99 4:38p Zaphod $
** Copyright (c) 1989-1995 San Diego Supercomputer Center (SDSC)
** a division of General Atomics, San Diego, California, USA
**
** Users and possessors of this source code are hereby granted a
** nonexclusive, royalty-free copyright and design patent license to
** use this code in individual software. License is not granted for
** commercial resale, in whole or in part, without prior written
** permission from SDSC. This source is provided "AS IS" without express
** or implied warranty of any kind.
**
** For further information contact:
** E-Mail: info@sds.sdsc.edu
**
** Surface Mail: Information Center
** San Diego Supercomputer Center
** P.O. Box 85608
** San Diego, CA 92138-5608
** (619) 534-5000
**/
#define HEADER " $Header: /roq/libim/imvfbadjust.c 1 11/02/99 4:38p Zaphod $"
/**
** FILE
** imvfbadjust.c - adjust a VFB
**
** PROJECT
** libim - SDSC image manipulation library
**
** DESCRIPTION
** imvfbadjust.c contains routines for adjusting components of pixels in a VFB
**
** PUBLIC CONTENTS
** d =defined constant
** f =function
** m =defined macro
** t =typedef/struct/union
** v =variable
** ? =other
**
** ImVfbAdjust f adjust the field values of a virtual frame buffer
**
** PRIVATE CONTENTS
** imAdjustPixel m adjust a pixel component
** imCheckField m check that a field value is within legal range
** IM_ERROR m return an error
**
** HISTORY
** $Log: /roq/libim/imvfbadjust.c $
*
* 1 11/02/99 4:38p Zaphod
** Revision 1.7 1995/06/29 00:28:04 bduggan
** updated copyright year
**
** Revision 1.6 1994/10/03 11:29:45 nadeau
** Updated to ANSI C and C++ compatibility.
** Removed all use of register keyword.
** Minimized use of custom SDSC types (e.g., uchar vs. unsigned char)
** Changed all float arguments to double.
** Added forward declarations.
** Added misc. casts to passify SGI and DEC compilers.
** Changed all macros and defined constants to have names
** starting with IM.
** Updated comments.
** Updated indenting on some code.
** Updated copyright message.
**
** Revision 1.5 92/12/03 01:53:59 nadeau
** Changed names of ImRgbHsi and ImHsiRgb to new names.
**
** Revision 1.4 92/09/01 20:11:06 vle
** Updated copyright notice.
**
** Revision 1.3 92/09/01 12:24:45 nadeau
** Rearranged and rewrote much of the code to add in additional
** error checks, support keying off of non-RGB images when given
** RGB or HSI key fields, support monochrome, write protect,
** Z-buffer, integer data, and float data fields.
**
** Revision 1.2 92/08/26 12:45:45 groening
** minor error corrections
**
** Revision 1.1 92/08/10 08:52:09 groening
** Initial revision
**
**
**/
/**
** CODE CREDITS
** Custom development, Chris Groening, San Diego Supercomputer Center, 1992.
** Custom development, Dave Nadeau, San Diego Supercomputer Center, 1992.
**/
#include "iminternal.h"
/*
* MACRO
* imAdjustPixel - adjust a pixel component
*
* DESCRIPTION
* Used by each of the adjustment operators of ImVfbAdjust(),
* this macro queries a pixel's component value, adjusts it as
* requested, checks that it is a legal value, then saves it
* back to the VFB.
*
* The macro is provide to encapsulate an algorithm that is
* nearly identical for each adjustment operator. Note that
* the 'op' argument is a C operator, like "+=" or "*=" that
* is substituted into the code. It is not a variable and is
* not a character string. This macro should be invoked with
* a statement like:
*
* imAdjustPixel( += )
*
* in order to implement an ADD operation. Pretty tricky, huh?
*/
#define imAdjustPixel(op) \
{ \
float hsi[3]; \
int rgb[3]; \
switch ( adjustField ) \
{ \
case IMRED: \
pixel = ImVfbQRed( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSRed( dstVfb, pDst, (int)pixel ); \
break; \
case IMGREEN: \
pixel = ImVfbQGreen( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSGreen( dstVfb, pDst, (int)pixel ); \
break; \
case IMBLUE: \
pixel = ImVfbQBlue( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSBlue( dstVfb, pDst, (int)pixel ); \
break; \
case IMINDEX8: \
pixel = ImVfbQIndex8( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSIndex8( dstVfb, pDst, (int)pixel ); \
break; \
case IMINDEX16: \
pixel = ImVfbQIndex16( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 65535 ) pixel = 65535; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSIndex16( dstVfb, pDst, (int)pixel ); \
break; \
case IMMONO: \
pixel = ImVfbQMono( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 1 ) pixel = 1; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSMono( dstVfb, pDst, (int)pixel ); \
break; \
case IMHUE: \
case IMSATURATION: \
case IMINTENSITY: \
rgb[0] = ImVfbQRed( dstVfb, pDst ); \
rgb[1] = ImVfbQGreen( dstVfb, pDst ); \
rgb[2] = ImVfbQBlue( dstVfb, pDst ); \
ImRgbToHsi( rgb, hsi ); \
if ( adjustField == IMHUE ) hsi[0] op value;\
else if ( adjustField == IMSATURATION) hsi[1] op value;\
else hsi[2] op value;\
ImHsiToRgb( hsi, rgb ); \
ImVfbSRed( dstVfb, pDst, rgb[0] ); \
ImVfbSGreen( dstVfb, pDst, rgb[1] ); \
ImVfbSBlue( dstVfb, pDst, rgb[2] ); \
break; \
case IMALPHA: \
pixel = ImVfbQAlpha( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSAlpha( dstVfb, pDst, (int)pixel ); \
break; \
case IMWPROT: \
pixel = ImVfbQWProt( dstVfb, pDst ); \
pixel op value; \
if ( pixel > 255 ) pixel = 255; \
if ( pixel < 0 ) pixel = 0; \
ImVfbSWProt( dstVfb, pDst, (int)pixel ); \
break; \
case IMZ: \
pixel = ImVfbQZ( dstVfb, pDst ); \
pixel op value; \
ImVfbSZ( dstVfb, pDst, (int)pixel ); \
break; \
case IMFDATA: \
pixel = ImVfbQFData( dstVfb, pDst ); \
pixel op value; \
ImVfbSFData( dstVfb, pDst, pixel ); \
break; \
case IMIDATA: \
pixel = ImVfbQIData( dstVfb, pDst ); \
pixel op value; \
ImVfbSIData( dstVfb, pDst, (int)pixel ); \
break; \
} \
}
/*
* MACRO
* IM_ERROR - return an error code
*
* DESCRIPTION
* This macro encapsulates setting ImErrNo and returning and is
* used just to make the code shorter and easier to read.
*/
#define IM_ERROR(errnum) \
{ \
ImErrNo = (errnum); \
return( IMVFBNULL ); \
}
/*
* MACRO
* imCheckField - check that a value is within a legal range
*
* DESCRIPTION
* This macro is used to check each of the key and adjust values
* to make sure they are within acceptable ranges.
*/
#define imCheckField(extent,error) \
{ \
switch ( operation ) \
{ \
case IMADD: \
case IMSUBTRACT: \
if ( adjustLow < -(extent) || adjustHigh > (extent) ) \
IM_ERROR( error ); \
break; \
case IMMULTIPLY: \
if ( adjustLow < 0 ) \
IM_ERROR( error ); \
break; \
case IMDIVIDE: \
if ( adjustLow <= 0 ) \
IM_ERROR( error ); \
break; \
case IMSET: \
if ( adjustLow < 0 || adjustHigh > (extent) ) \
IM_ERROR( error ); \
break; \
} \
}
/*
* FUNCTION
* ImVfbAdjust - adjust the fields in a virtual frame buffer.
*
* DESCRIPTION
* The source image's pixels are adjusted and written to the destination
* image. Adjustements are performed on pixels selected by the 'key'
* arguments and modify those pixel's 'adjust' fields using the given
* operation.
*
* The majority of the code here is just to check that all the incomming
* arguments make sense. Whew!
*/
#ifdef __STDC__
ImVfb * /* Returns filled destination vfb */
ImVfbAdjust( ImVfb *srcVfb, int keyField, double keyStart, double keyEnd, int operation,
int adjustField, double adjustStart, double adjustEnd, ImVfb *dstVfb )
#else
ImVfb * /* Returns filled destination vfb */
ImVfbAdjust( srcVfb, keyField, keyStart, keyEnd, operation,
adjustField, adjustStart, adjustEnd, dstVfb)
ImVfb *srcVfb; /* incoming vfb */
int keyField; /* what field to change */
double keyStart; /* Start range of field to change */
double keyEnd; /* End range of field to change */
int operation; /* What operation to perform on field */
int adjustField; /* what field to adjust */
double adjustStart; /* Start range of field to adjust */
double adjustEnd; /* End range of field to adjust */
ImVfb *dstVfb; /* Destination vfb */
#endif
{
int x,y; /* Width and height of image */
int i,j; /* Counters */
float factor; /* Replacement value factor */
int fields; /* Fields of source VFB */
int pixelRgb[3]; /* RGB pixel value */
float pixelHsi[3]; /* HSI pixel value */
float pixel; /* Pixel value */
float value; /* Value with which to modify pixel */
ImClt *clt; /* Image's color lookup table */
ImVfbPtr pDst; /* Pointer to destination VFB */
float keyLow; /* Low key value */
float keyHigh; /* High key value */
float adjustLow; /* Low adjust value */
float adjustHigh; /* High adjust value */
/*
* Check for legal key and adjust values. This is made a bit
* tricky because of the following:
*
* 1. Different field types have different legal key value
* ranges.
*
* 2. Replace value ranges depend on the operation being
* performed, as well as upon the adjust field's type.
*
* Key fields are restricted as follows:
* mono: 0 to 1
* red, green, blue, alpha, index8, wprot: 0 to 255
* index16: 0 to 65535
* z: 0 to maxint
* idata: any int
* fdata: any float
* hue: 0 to 360.0
* saturation, intensity: 0 to 1.0
*
* Adjust fields are restricted as follows:
*
* Add and subtract:
* It doesn't make much sense to add more, or subtract more
* than the max or min field value. Doing so puts the result
* beyond the max or min, and will just get clamped back to
* the max or min anyway.
* mono: -1 to 1
* red, green, blue, alpha, index8, wprot: -255 to 255
* index16: -65535 to 65535
* z, idata, fdata: anything
* hue: -360.0 to 360.0
* saturation, intensity: -1.0 to 1.0
*
* Multiply:
* Multiplication factors can be anything except negative.
* Negative factors would produce negative results, which
* would just get clamped back to 0 anyway.
* mono: 0 to 1
* red, green, blue, alpha, index8, wprot: 0 to anything
* index16: 0 to anything
* z: 0 to anything
* idata, fdata: anything
* hue: 0 to anything
* saturation, intensity: 0 to anything
*
* Divide:
* Division factors can be anything except zero or negative.
* Zero causes horrible things. Negative values would produce
* negative results, which would just get clamped back to
* 0 anyway.
* mono: >0 to 1
* red, green, blue, alpha, index8, wprot: >0 to anything
* index16: >0 to anything
* z: >0 to anything
* idata, fdata: !=0, anything
* hue: >0 to anything
* saturation, intensity: >0 to anything
*
* Set:
* Set can be anything legal for the field.
* mono: 0 to 1
* red, green, blue, alpha, index8, wprot: 0 to 255
* index16: 0 to 65535
* z: 0 to anything
* idata, fdata: anything
* hue: 0 to 360.0
* saturation, intensity: 0 to 1.0
*/
/*
* Get the low and high key and adjust values to make testing
* extent faster.
*/
if ( keyStart < keyEnd )
{
keyLow = keyStart;
keyHigh = keyEnd;
}
else
{
keyHigh = keyStart;
keyLow = keyEnd;
}
if ( adjustStart < adjustEnd )
{
adjustLow = adjustStart;
adjustHigh = adjustEnd;
}
else
{
adjustHigh = adjustStart;
adjustLow = adjustEnd;
}
/*
* Make sure the key field and key range are good.
*/
switch ( keyField )
{
case IMMONO:
if ( keyLow < 0.0 || keyHigh > 1.0 )
IM_ERROR( IMEKEY );
break;
case IMRED:
case IMGREEN:
case IMBLUE:
case IMALPHA:
case IMINDEX8:
case IMWPROT:
if ( keyLow < 0.0 || keyHigh > 255.0 )
IM_ERROR( IMEKEY );
break;
case IMINDEX16:
if ( keyLow < 0.0 || keyHigh > 65535.0 )
IM_ERROR( IMEKEY );
break;
case IMHUE:
if ( keyLow < 0.0 || keyHigh > 360.0 )
IM_ERROR( IMEKEY );
break;
case IMSATURATION:
case IMINTENSITY:
if ( keyLow < 0.0 || keyHigh > 1.0 )
IM_ERROR( IMEKEY );
break;
case IMZ:
if ( keyLow < 0.0 )
IM_ERROR( IMEKEY );
break;
case IMIDATA:
case IMFDATA:
/* All values allowed. */
break;
default:
IM_ERROR( IMEKEYFIELD );
}
/*
* Make sure the operation is good.
*/
switch ( operation )
{
case IMADD:
case IMSUBTRACT:
case IMMULTIPLY:
case IMDIVIDE:
case IMSET:
break;
default:
IM_ERROR( IMEOPERATION );
}
/*
* Make sure the adjust field and adjust range are good.
*/
switch ( adjustField )
{
case IMMONO:
imCheckField( 1.0, IMEADJUST );
break;
case IMRED:
case IMGREEN:
case IMBLUE:
case IMALPHA:
case IMINDEX8:
case IMWPROT:
imCheckField( 255.0, IMEADJUST );
break;
case IMINDEX16:
imCheckField( 65535.0, IMEADJUST );
break;
case IMZ:
switch ( operation )
{
case IMADD:
case IMSUBTRACT:
break;
case IMMULTIPLY:
case IMSET:
if ( adjustLow < 0.0 )
IM_ERROR( IMEADJUST );
break;
case IMDIVIDE:
if ( adjustLow == 0.0 || adjustHigh == 0.0 )
IM_ERROR( IMEADJUST );
break;
}
break;
case IMIDATA:
case IMFDATA:
if ( operation == IMDIVIDE &&
( adjustLow == 0.0 || adjustHigh == 0.0 ) )
IM_ERROR( IMEADJUST );
break;
case IMHUE:
imCheckField( 360.0, IMEADJUST );
break;
case IMSATURATION:
case IMINTENSITY:
imCheckField( 1.0, IMEADJUST );
break;
}
/*
* Check that the source VFB has the fields we need to do the
* adjustment.
*
* Key fields:
* red, green, blue: source may have any color field type
* hue, saturation, inten: source may have any color field type
* mono: source must have MONO
* index8: source must have INDEX8
* index16: source must have INDEX16
* alpha: source must have ALPHA
* wprot: source must have WPROT
* z: source must have Z
* idata: source must have IDATA
* fdata: source must have FDATA
*
* Replace fields:
* red, green, blue: destination must have RGB.
* hue, saturation, inten: destination must have RGB.
* index8: destination must have INDEX8.
* index16: destination must have INDEX16.
* alpha: destination must have ALPHA.
* wprot: destination must have WPROT
* z: destination must have Z
* idata: destination must have IDATA
* fdata: destination must have FDATA
*/
fields = ImVfbQFields( srcVfb );
switch ( keyField )
{
case IMMONO:
if ( !(fields & IMVFBMONO) )
IM_ERROR( IMEKEYFIELD );
break;
case IMRED:
case IMGREEN:
case IMBLUE:
case IMHUE:
case IMSATURATION:
case IMINTENSITY:
if ( !(fields&(IMVFBRGB|IMVFBINDEX8|IMVFBINDEX16|IMVFBMONO)))
IM_ERROR( IMEKEYFIELD );
break;
case IMINDEX8:
if ( !(fields & IMVFBINDEX8) )
IM_ERROR( IMEKEYFIELD );
break;
case IMINDEX16:
if ( !(fields & IMVFBINDEX16) )
IM_ERROR( IMEKEYFIELD );
break;
case IMALPHA:
if ( !(fields & IMVFBALPHA) )
IM_ERROR( IMEKEYFIELD );
break;
case IMWPROT:
if ( !(fields & IMVFBWPROT) )
IM_ERROR( IMEKEYFIELD );
break;
case IMZ:
if ( !(fields & IMVFBZ) )
IM_ERROR( IMEKEYFIELD );
break;
case IMIDATA:
if ( !(fields & IMVFBIDATA) )
IM_ERROR( IMEKEYFIELD );
break;
case IMFDATA:
if ( !(fields & IMVFBFDATA) )
IM_ERROR( IMEKEYFIELD );
break;
}
switch ( adjustField )
{
case IMMONO:
if ( !(fields & IMVFBMONO) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMRED:
case IMGREEN:
case IMBLUE:
case IMHUE:
case IMSATURATION:
case IMINTENSITY:
if ( !(fields & IMVFBRGB) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMINDEX8:
if ( !(fields & IMVFBINDEX8) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMINDEX16:
if ( !(fields & IMVFBINDEX16) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMALPHA:
if ( !(fields & IMVFBALPHA) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMWPROT:
if ( !(fields & IMVFBWPROT) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMZ:
if ( !(fields & IMVFBZ) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMIDATA:
if ( !(fields & IMVFBIDATA) )
IM_ERROR( IMEADJUSTFIELD );
break;
case IMFDATA:
if ( !(fields & IMVFBFDATA) )
IM_ERROR( IMEADJUSTFIELD );
break;
}
/*
* Copy the source into the destination, creating a new destination
* if needed. ImVfbCopy() will catch problems where the given
* destination VFB (if not IMVFBNEW) doesn't have the same fields as
* the source, or isn't at least as large as the source.
*/
x = ImVfbQWidth( srcVfb );
y = ImVfbQHeight( srcVfb );
if ( srcVfb == IMVFBNULL )
IM_ERROR( IMENOVFB );
if ( srcVfb != dstVfb )
{
dstVfb = ImVfbCopy( srcVfb, 0, 0, x, y, fields, dstVfb, 0,0);
if ( dstVfb == IMVFBNULL )
return ( IMVFBNULL ); /* ImErrNo already set */
}
/*
* Prepare to adjust the image.
*/
if ( keyEnd != keyStart )
factor = (adjustEnd - adjustStart) / (keyEnd - keyStart);
else
factor = 0;
clt = ImVfbQClt( dstVfb ); /* Might be IMCLTNULL */
pDst = ImVfbQFirst( dstVfb );
fields = ImVfbQFields( dstVfb );
/*
* Simplify the field mask to the single key field we care about.
*/
switch ( keyField )
{
case IMRED:
case IMGREEN:
case IMBLUE:
case IMHUE:
case IMSATURATION:
case IMINTENSITY:
fields &= IMVFBIMAGEMASK;
break;
default:
fields = keyField;
}
/*
* Adjust the image.
*
* Note that there are a lot of checks in the innermost pixel scan
* loop that are loop-invariant. It would certainly speed things
* up if they were moved out of the loop. Unfortunately, this
* considerably increases the amount of the code since it requires
* duplicating the loop for each combination of:
*
* keyField
* red 4 combinations of dst VFB fields
* green 4 combinations of dst VFB fields
* blue 4 combinations of dst VFB fields
* hue 4 combinations of dst VFB fields
* saturation 4 combinations of dst VFB fields
* intensity 4 combinations of dst VFB fields
* index8 2 combinations of dst CLT existance
* index16 2 combinations of dst CLT existance
* mono 1 combination
* alpha 1 combination
* wprot 1 combination
* z 1 combination
* idata 1 combination
* fdata 1 combination
* --
* subtotal 34
*
* operator 5 possible values
* adjustField 10 possible values
* ---
* TOTAL 34 * 5 * 10 = 1700 variants
*
* Things clearly get out of hand quick. Additionally, the basic
* algorithm gets spread out all over everywhere, even with liberal
* use of macros.
*
* So, we'll pay the speed penalty in order to get less code and
* easier maintenance.
*/
for ( i = 0; i < y; i++ )
{
for ( j = 0; j < x; j++ )
{
/* Get the pixel value depending upon keyfield. */
switch ( keyField )
{
case IMRED:
/* Get pixel value from VFB depending upon fields. */
switch ( fields )
{
case IMVFBRGB:
pixel = ImVfbQRed( dstVfb, pDst );
break;
case IMVFBINDEX8:
pixel = ImVfbQIndex8( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQRed( ImCltQPtr( clt, (int)pixel));
break;
case IMVFBINDEX16:
pixel = ImVfbQIndex16( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQRed( ImCltQPtr( clt, (int)pixel));
else
pixel /= 255;
break;
case IMVFBMONO:
pixel = ImVfbQMono( dstVfb, pDst ) * 255;
break;
}
break;
case IMGREEN:
/* Get pixel value from VFB depending upon fields. */
switch ( fields )
{
case IMVFBRGB:
pixel = ImVfbQGreen( dstVfb, pDst );
break;
case IMVFBINDEX8:
pixel = ImVfbQIndex8( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQGreen( ImCltQPtr( clt, (int)pixel));
break;
case IMVFBINDEX16:
pixel = ImVfbQIndex16( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQGreen( ImCltQPtr( clt, (int)pixel));
else
pixel /= 255;
break;
case IMVFBMONO:
pixel = ImVfbQMono( dstVfb, pDst ) * 255;
break;
}
break;
case IMBLUE:
/* Get pixel value from VFB depending upon fields. */
switch ( fields )
{
case IMVFBRGB:
pixel = ImVfbQBlue( dstVfb, pDst );
break;
case IMVFBINDEX8:
pixel = ImVfbQIndex8( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQBlue( ImCltQPtr( clt, (int)pixel));
break;
case IMVFBINDEX16:
pixel = ImVfbQIndex16( dstVfb, pDst );
if ( clt != IMCLTNULL )
pixel = ImCltQBlue( ImCltQPtr( clt, (int)pixel));
else
pixel /= 255;
break;
case IMVFBMONO:
pixel = ImVfbQMono( dstVfb, pDst ) * 255;
break;
}
break;
case IMINDEX8:
pixel = ImVfbQIndex8( dstVfb, pDst );
break;
case IMINDEX16:
pixel = ImVfbQIndex16( dstVfb, pDst );
break;
case IMMONO:
pixel = ImVfbQMono( dstVfb, pDst );
break;
case IMALPHA:
pixel = ImVfbQAlpha( dstVfb, pDst );
break;
case IMWPROT:
pixel = ImVfbQWProt( dstVfb, pDst );
break;
case IMZ:
pixel = ImVfbQZ( dstVfb, pDst );
break;
case IMIDATA:
pixel = ImVfbQIData( dstVfb, pDst );
break;
case IMFDATA:
pixel = ImVfbQFData( dstVfb, pDst );
break;
case IMHUE:
case IMSATURATION:
case IMINTENSITY:
/* Get pixel value from VFB depending upon fields. */
switch ( fields )
{
case IMVFBRGB:
pixelRgb[0] = ImVfbQRed( dstVfb, pDst );
pixelRgb[1] = ImVfbQGreen( dstVfb, pDst );
pixelRgb[2] = ImVfbQBlue( dstVfb, pDst );
break;
case IMVFBINDEX8:
pixel = ImVfbQIndex8( dstVfb, pDst );
if ( clt != IMCLTNULL )
{
pixelRgb[0] = ImCltQRed( ImCltQPtr( clt, (int)pixel));
pixelRgb[1] = ImCltQGreen( ImCltQPtr( clt, (int)pixel));
pixelRgb[2] = ImCltQBlue( ImCltQPtr( clt, (int)pixel));
}
else
{
pixelRgb[0] = (int)pixel;
pixelRgb[1] = (int)pixel;
pixelRgb[2] = (int)pixel;
}
break;
case IMVFBINDEX16:
pixel = ImVfbQIndex16( dstVfb, pDst );
if ( clt != IMCLTNULL )
{
pixelRgb[0] = ImCltQRed( ImCltQPtr( clt, (int)pixel));
pixelRgb[1] = ImCltQGreen( ImCltQPtr( clt, (int)pixel));
pixelRgb[2] = ImCltQBlue( ImCltQPtr( clt, (int)pixel));
}
else
{
pixelRgb[0] = (int)pixel / 255;
pixelRgb[1] = (int)pixel / 255;
pixelRgb[2] = (int)pixel / 255;
}
break;
case IMVFBMONO:
pixel = ImVfbQMono( dstVfb, pDst ) * 255;
pixelRgb[0] = (int)pixel;
pixelRgb[1] = (int)pixel;
pixelRgb[2] = (int)pixel;
break;
}
ImRgbToHsi( pixelRgb, pixelHsi );
switch ( keyField )
{
case IMHUE: pixel = pixelHsi[0]; break;
case IMSATURATION: pixel = pixelHsi[1]; break;
case IMINTENSITY: pixel = pixelHsi[2]; break;
}
break;
}
/* Check if the pixel is within the key range. */
if ( !(pixel >= keyStart && pixel <= keyEnd) )
{
/* Nope! */
ImVfbSInc( dstVfb, pDst );
continue;
}
/* Compute the value to add, subtract, etc. */
value = adjustStart + factor * (pixel - keyStart);
/* Update the pixel depending upon the operation. */
switch ( operation )
{
case IMADD:
imAdjustPixel( += );
break;
case IMSUBTRACT:
imAdjustPixel( -= );
break;
case IMMULTIPLY:
imAdjustPixel( *= );
break;
case IMDIVIDE:
imAdjustPixel( /= );
break;
case IMSET:
imAdjustPixel( = );
break;
}
ImVfbSInc( dstVfb, pDst );
}
}
return( dstVfb);
}