示例#1
0
LOCAL LPFRAME ConvertFrame(LPFRAME lpSrcFrame, FRMTYPEINFO OutTypeInfo, CFrameTypeConvert *pTypeConvert)
/***********************************************************************/
{
int	y, Xsize, Ysize;
LPFRAME lpDstFrame;
FRMTYPEINFO InTypeInfo;
LPTR lpSrc, lpDst;
CFrameTypeConvert TypeConvert;

Xsize = FrameXSize(lpSrcFrame);
Ysize = FrameYSize(lpSrcFrame);
FrameGetTypeInfo(lpSrcFrame, &InTypeInfo);
if (!pTypeConvert)
	{
	if (!TypeConvert.Init(InTypeInfo, OutTypeInfo, Xsize))
		{
		Message(IDS_EMEMALLOC);
		return(NULL);
		}
	pTypeConvert = &TypeConvert;
	}

lpDstFrame = FrameOpen(OutTypeInfo, Xsize, Ysize, FrameResolution(lpSrcFrame));
if (!lpDstFrame)
	{
	FrameError(IDS_EPROCESSOPEN);
	return(NULL);
	}

ProgressBegin(1, 0);
for (y = 0; y < Ysize; ++y)
	{
	if (AstralClockCursor(y, Ysize, YES))
		{
		FrameClose(lpDstFrame);
		goto ExitError;
		}
	if (!(lpSrc = FramePointerRaw(lpSrcFrame, 0, y, NO)))
		continue;
	if (!(lpDst = FramePointerRaw(lpDstFrame, 0, y, YES)))
		continue;
	pTypeConvert->ConvertData(lpSrc, lpDst, y, Xsize);
	}

ProgressEnd();
return(lpDstFrame);

ExitError:
ProgressEnd();
return(NULL);
}
示例#2
0
void FramePutRGB(
	LPFRAME lpFrame,
	LPRGB   lpSrcRGB,
	LPTR    lpDst,
	int     iPixelCount)
{
	CFrameTypeConvert TypeConvert;
	FRMTYPEINFO SrcTypeInfo, DstTypeInfo;

	if (!lpFrame) return;

	FrameSetTypeInfo(&SrcTypeInfo, FDT_RGBCOLOR);
	FrameGetTypeInfo(lpFrame, &DstTypeInfo);

	if (!TypeConvert.Init(SrcTypeInfo, DstTypeInfo, iPixelCount, DT_NONE))
		return;

	TypeConvert.ConvertData((LPTR)lpSrcRGB, lpDst, 0, iPixelCount);
}
示例#3
0
//  Gets the current mask if any.
//  If no mask exists then create one using fOn and fNoUndo.
//  bCreated is TRUE if a new mask was created. 
LPMASK CImage::GetMaskEx(BOOL fOn, BOOL fNoUndo, LPINT bCreated, LPRECT lpUpdateRect)
{
    LPMASK lpMask;
    LPFRAME lpFrame;
    FRMTYPEINFO TypeInfo;
    FRMDATATYPE FrameType = FDT_GRAYSCALE;

    AstralSetRectEmpty(lpUpdateRect);
    if (lpMask = GetMask())
    {
        if (bCreated)
            *bCreated = FALSE;
        return(lpMask);
    }
    lpFrame = GetBaseEditFrame();
    FrameGetTypeInfo(lpFrame, &TypeInfo);
    if (TypeInfo.DataType == FDT_LINEART && Mask.OneBitMask)
       FrameType = FDT_LINEART;
    if (!(lpMask = MaskCreate(NULL, FrameXSize(lpFrame),
                                FrameYSize(lpFrame),
                                fOn, 
                                fNoUndo, FrameType)))
    {
        Message( IDS_EMEMALLOC );
        return(NULL);
    }
	// sync up the resolution of the image data and the mask
	// don't ever rely on the mask's resolution being correct
	// cause other size can change the image data resolution
	// without changing the mask's resolution.  Also, there are
	// other places the mask gets created without syncing up
	// the resolution.  I am doing it here so we can begin
	// to track it correctly (Ted)
	FrameSetResolution(AlphaGetEditFrame(lpMask), FrameResolution(lpFrame));
    if (bCreated)
        *bCreated = TRUE;
    if (!Control.UseMaskAndObjects)
        GetObjectMarqueeRect(this, lpUpdateRect);
    SetMask(lpMask);
    return(lpMask);
}
示例#4
0
void ImgInitDisplay(LPIMAGE lpImage, BOOL fGeneratePaletteLUT)
/***********************************************************************/
{
LPTR lpPaletteLUT;
RGBS RGBmap[256];
LPRGB lpRGBmap;
int nColors;
FRMTYPEINFO TypeInfo, DstTypeInfo = ColorManager.Monitor.dst;
LPOBJECT lpObject;

lpObject = lpImage->GetDisplayObject();
if (!lpObject)
	return;
FrameGetTypeInfo(ObjGetEditFrame(lpObject), &TypeInfo);

if ( lpBltScreen->BitMapInfo.bmiHeader.biBitCount == 8 &&
        !lpImage->lpPaletteLUT)
    {
    ProgressBegin(1, PROGRESS_ID(IDS_UNDOSETUPDISPLAY));
    if (TypeInfo.DataType == FDT_PALETTECOLOR)
        lpPaletteLUT = Alloc(32768L);
    else
        lpPaletteLUT = NULL;
    if (lpPaletteLUT)
        {
        if (TypeInfo.ColorMap->NumEntries > MAX8BITCOLORS)
            {
            nColors = MAX8BITCOLORS;
            lpRGBmap = RGBmap;
            if (!ReducePalette(TypeInfo.ColorMap->RGBData,  TypeInfo.ColorMap->NumEntries,
                                lpRGBmap, nColors))
                {
                FreeUp(lpPaletteLUT);
                lpPaletteLUT = NULL;
                }
            }
        else
            {
            lpRGBmap = TypeInfo.ColorMap->RGBData;
            nColors = TypeInfo.ColorMap->NumEntries;
            }
        }
    if (lpPaletteLUT)
        {
		if (fGeneratePaletteLUT)
	        CreatePaletteLut15(lpRGBmap, nColors, lpPaletteLUT, AstralClockCursor);
        lpImage->lpPaletteLUT = lpPaletteLUT;
        lpImage->PaletteType = PT_CUSTOMPALETTE;
        lpImage->hPal = CreateLogicalPalette(lpRGBmap, nColors);
		  GetObject(lpImage->hPal, sizeof(nColors), (void *)&nColors);
        lpImage->nPaletteEntries = GetPaletteEntries(lpImage->hPal,
                        0, nColors, lpImage->Palette);
        }
    else
        {
        if ( FrameType(ImgGetBaseEditFrame(lpImage)) <= FDT_GRAYSCALE)
            {
            lpImage->hPal = lpBltScreen->hGrayPal;
            lpImage->nPaletteEntries = lpBltScreen->nGrayEntries;
            lpImage->PaletteType = lpBltScreen->GrayPaletteType;
            lpImage->lpPaletteLUT = lpBltScreen->lpGrayPaletteLUT;
            copy((LPTR)lpBltScreen->GrayPalette,
                 (LPTR)lpImage->Palette,
                 sizeof(lpImage->Palette));
            }
        else
            {
            lpImage->hPal = lpBltScreen->hColorPal;
            lpImage->nPaletteEntries = lpBltScreen->nColorEntries;
            lpImage->PaletteType = lpBltScreen->ColorPaletteType;
            lpImage->lpPaletteLUT = lpBltScreen->lpColorPaletteLUT;
            copy((LPTR)lpBltScreen->ColorPalette,
                 (LPTR)lpImage->Palette,
                 sizeof(lpImage->Palette));
            }
        }
    ProgressEnd();
    }

if (lpImage->m_cmsXform)
	{
	if( Control.CMSEnabled && lpKCMSFreeProc )
		{
		if (lpImage->PtInfo.toRCS != TypeInfo.ptInfo.toRCS &&
			lpImage->PtInfo.frRCS != TypeInfo.ptInfo.frRCS )
			{
			( lpKCMSFreeProc )( lpImage->m_cmsXform );
			lpImage->m_cmsXform = NULL;
			}
		}
	else
		lpImage->m_cmsXform = NULL;
	}

	
if( Control.CMSEnabled &&
	IsSrcPTSelected( &TypeInfo.ptInfo ) &&
	IsDstPTSelected( &DstTypeInfo.ptInfo ) &&
	lpKCMSCnctProc )
	{
	lpImage->m_bDoCmsGamma = YES;
	if (!lpImage->m_cmsXform)
		{
		if( ( !FrameTypeInfoEqual( TypeInfo, DstTypeInfo ) ) &&
				ConvertCRCtoUID( &TypeInfo, &DstTypeInfo ) )
			{
			// save for later check to avoid a monitor reconnect.
			lpImage->PtInfo = TypeInfo.ptInfo;
			lpImage->m_cmsXform = ( *lpKCMSCnctProc )( &TypeInfo, &DstTypeInfo );
			}
		else
			lpImage->m_cmsXform = NULL;
		}
	}
else
	lpImage->m_cmsXform = NULL;
}
示例#5
0
BOOL ObjGetLine(LPOBJECT lpObject, int x, int y, int dx, LPTR lpOut)
/************************************************************************/
{
	LPALPHA     lpAlpha;
	LPTR        lp;
	LPPROCESSPROC lpProcessProc;
	RECT        rLine, rSect;
	int         nPixels, ox, oy, depth;
	FRMTYPEINFO TypeInfo;
	FRMDATATYPE DataType;
	long        lOffset;
	LPFRAME		lpFrame;

	// fill buffer with base image object
	// use depth of base image object
	lpFrame = ObjGetEditFrame(lpObject);
	FrameGetTypeInfo(lpFrame, &TypeInfo);
	DataType = TypeInfo.DataType;
	depth = FrameDepth(lpFrame);
	if (TypeInfo.DataType == FDT_LINEART)
	{
    	depth = 1;
    	TypeInfo.DataType = FDT_GRAYSCALE;
	}

	if (!ObjGetLineAlloc(dx, depth))
   	{
    	//Message(IDS_EMEMALLOC);
    	return(FALSE);
   	}

	if (!FrameRead(lpFrame, x, y, dx, lpOut, dx))
    	return(FALSE);

	// setup rect for this line for intersect check
	rLine.left = x;
	rLine.right = x + dx - 1;
	rLine.top = rLine.bottom = y;
	// start with first object on top of base image

	while(lpObject = lpObject->lpNext)
   	{
    	// if object cannot be rendered through raster means
    	if (lpObject->fDeleted || 
        	!AstralIntersectRect(&rSect, &lpObject->rObject, &rLine))
        	continue;

        // get merge proc for this object
        lpProcessProc = GetProcessProc(lpObject->MergeMode, DataType);

        ox = rSect.left-lpObject->rObject.left;
        oy = y-lpObject->rObject.top;
        nPixels = (rSect.right - rSect.left + 1);
        lOffset = (long)(rSect.left - rLine.left) * depth;
        lp = FramePointer(ObjGetEditFrame(lpObject), ox, oy, NO, nPixels);
        if (lp)
        {
        	if (lpAlpha = ObjGetAlpha(lpObject))
            {
            	MaskLoad(lpAlpha, ox, oy, nPixels, lpGLMaskBuf);
            	if (lpObject->Opacity != 255)
                	ScaleData8(lpGLMaskBuf, nPixels, lpObject->Opacity);
            }
        	else
            	set(lpGLMaskBuf, nPixels, lpObject->Opacity);
        	(*lpProcessProc)(lpOut+lOffset, lp, lpGLMaskBuf, nPixels);
        }
    }
	return(TRUE);
}
示例#6
0
BOOL ConvertImage(LPIMAGE lpImage, LPCONVERT_PARMS lpParms)
/***********************************************************************/
{
BOOL fRet = FALSE;
LPFRAME lpDstFrame, lpBaseFrame;
LPOBJECT lpBase, lpObject;
BOOL fError, fOptimize, fProgressSet;
INTERNAL_DATA data;
int	inDepth, iMaxWidth, nColors, i;
LPCOLORMAP lpColorMap;
LPRGB lpRGB;
FRMTYPEINFO InTypeInfo, OutTypeInfo;
CFrameTypeConvert TypeConvert;
DITHER_TYPE DitherType = DT_DEFAULT;

if (ImgInMaskEditMode(lpImage))
	return(TRUE);

lpColorMap = NULL;

lpBase = ImgGetBase(lpImage);
lpBaseFrame = ObjGetEditFrame(lpBase);
inDepth = FrameDepth(lpBaseFrame);

OutTypeInfo = lpParms->cmsInfo.dst;
FrameGetTypeInfo(lpBaseFrame, &InTypeInfo);

// are we try to convert to a color managed image?
if (Control.CMSEnabled && IsDstPTSelected(&OutTypeInfo.ptInfo))
	{
	// see if our image already has a color managed source
	if (!IsSrcPTSelected(&InTypeInfo.ptInfo))
		{
		// nope, see if the source passed in is valid for this image
		if (IsSrcPTSelected(&lpParms->cmsInfo.src.ptInfo) &&
			(lpParms->cmsInfo.src.DataType == InTypeInfo.DataType))
			{	
			InTypeInfo = lpParms->cmsInfo.src;
			}
		// go get a source from the user
		else
			{
			CMSINFO CmsInfo2;
			if( CmsGetSrcPTType( &InTypeInfo, &CmsInfo2) )
				InTypeInfo = CmsInfo2.src;
			}
		}
	}
else
 	FrameSetTypeInfo(&InTypeInfo, InTypeInfo.DataType, InTypeInfo.ColorMap);

// no conversion necessary
if (FrameTypeInfoEqual(InTypeInfo, OutTypeInfo))
	return(TRUE);

DitherType = lpParms->DitherType;
fOptimize = lpParms->ConvertType == CT_OPTIMIZED;
fProgressSet = FALSE;


if ( OutTypeInfo.DataType == FDT_PALETTECOLOR/* && inDepth >= 3 */)
	{
	if (lpParms->ConvertType == CT_CUSTOM)
		{
		FNAME szFileName;

		if ( !LookupExtFileN( lpParms->szPalette, szFileName, IDN_PALETTE, NO ) )
			return(FALSE);
		if (!(lpColorMap = Palette_ReadColorMap(szFileName)))
			return(FALSE);
		}
	else
		{
		// allocate a map to carry around with image
		lpColorMap = FrameCreateColorMap();
		if (!lpColorMap)
			{
			Message(IDS_EMEMALLOC);
			goto MemError;
			}

		lpColorMap->NumEntries = lpParms->iLevels;

		if (InTypeInfo.DataType == FDT_GRAYSCALE && lpColorMap->NumEntries == 256 &&
			fOptimize)
			{
			DitherType = DT_NONE;
			lpRGB = lpColorMap->RGBData;
			for (i = 0; i < lpColorMap->NumEntries; ++i)
				{
				lpRGB->red = lpRGB->green = lpRGB->blue = i;
				++lpRGB;
				}
			}
		else
			{
			// 1. CreateOptimizedPalette phase - only if fOptimize
			// 2. Mapping phase
			ProgressBegin(fOptimize ? 2 : 1,
					lpParms->Common.idDirty-IDS_UNDOFIRST+IDS_PROGFIRST);
			fProgressSet = TRUE;
			if (fOptimize)
				ProgressBegin(1, 0);
			if (!CreateOptimizedPalette(lpBase, ObjGetEditFrame(lpBase),
									lpColorMap->RGBData, &lpColorMap->NumEntries,
									fOptimize,
									fOptimize ? AstralClockCursor : NULL))
				{
				if (fOptimize)
					ProgressEnd();
				Message(IDS_EMEMALLOC);
				goto ExitFalse;
				}
			if (fOptimize)
				ProgressEnd();
			}
		}
	if (lpColorMap->NumEntries <= 16)
		lpColorMap->NumEntries = 16;
	else
		lpColorMap->NumEntries = 256;
	FrameSetTypeInfo(&OutTypeInfo, FDT_PALETTECOLOR, lpColorMap);
	}

if (!fProgressSet)
	ProgressBegin(1, lpParms->Common.idDirty-IDS_UNDOFIRST+IDS_PROGFIRST);
fProgressSet = TRUE;
	
iMaxWidth = 0;
lpObject = NULL;
while (lpObject = ImgGetNextObject(lpImage, lpObject, YES, NO))
	{
	if (RectWidth(&lpObject->rObject) > iMaxWidth)
		iMaxWidth = RectWidth(&lpObject->rObject);
	}
if (!TypeConvert.Init(InTypeInfo, OutTypeInfo, iMaxWidth, DitherType))
	{
	Message(IDS_EMEMALLOC);
	goto ExitFalse;
	}

if (ImgMultipleObjects(lpImage))
	{
	ProgressBegin(ImgCountObjects(lpImage), 0);
	
	if ( !ImgEditInit(lpImage, ET_ALLOBJECTS, UT_NEWDATA|UT_COLORMAP, lpBase) )
		goto ExitFalse;

	fError = NO;
	lpObject = NULL;
	while (lpObject = ImgGetNextObject(lpImage, lpObject, YES, NO))
		{
		lpDstFrame = ConvertFrame(ObjGetEditFrame(lpObject), OutTypeInfo, &TypeConvert);
		if (!lpDstFrame)
			{
			fError = YES;
			break;
			}
 		ImgEditedObjectFrame( lpImage, lpObject, lpParms->Common.idDirty, NULL,
						lpDstFrame, NULL);
		}

	if (fError)
		{
		lpObject = NULL;
		while (lpObject = ImgGetNextObject(lpImage, lpObject, YES, NO))
			{
			if (lpObject->Pixmap.UndoFrame)
				{
		 		lpDstFrame = lpObject->Pixmap.EditFrame;
		 		lpObject->Pixmap.EditFrame = lpObject->Pixmap.UndoFrame;
		 		lpObject->Pixmap.UndoFrame = NULL;
		 		FrameClose(lpDstFrame);
		 		}
			}
		}
	ProgressEnd();
	}
else
	{
	if ( !ImgEditInit(lpImage, ET_OBJECT, UT_NEWDATA|UT_COLORMAP, lpBase) )
		goto ExitFalse;

	ProgressBegin(1, 0);
	lpDstFrame = ConvertFrame(lpBaseFrame, OutTypeInfo, &TypeConvert);
	ProgressEnd();

	if (!lpDstFrame)
		goto ExitFalse;
	/* Setup the new image and bring up the new image window */
	ImgEditedObjectFrame( lpImage, lpBase, lpParms->Common.idDirty, NULL,
						lpDstFrame, NULL);
	}

switch (lpParms->cmsInfo.dst.DataType)
	{
	case FDT_LINEART:
		lpImage->DataType = IDC_SAVELA;
		break;
	case FDT_GRAYSCALE:
		lpImage->DataType = IDC_SAVECT;
		break;
	case FDT_PALETTECOLOR:
		lpImage->DataType = IDC_SAVE8BITCOLOR;
		break;
	case FDT_RGBCOLOR:
		lpImage->DataType = IDC_SAVE24BITCOLOR;
		break;
	case FDT_CMYKCOLOR:
		lpImage->DataType = IDC_SAVE32BITCOLOR;
		break;
	}
ImgColorMapChanged(lpImage);
lpParms->Common.UpdateType = UT_DATATYPE;

fRet = TRUE;

ExitFalse:
if (fProgressSet)
	ProgressEnd();
MemError:
if (lpColorMap)
	FrameDestroyColorMap(lpColorMap);
return(fRet);
}
示例#7
0
void CImage::GetTypeInfo(LPFRMTYPEINFO lpTypeInfo)
{
    FrameGetTypeInfo(GetBaseEditFrame(), lpTypeInfo);
}
示例#8
0
static LPTR FrameToColorDIB( LPFRAME lpFrame, LPRECT lpRect )
{
	int y, bpl;
	LPTR lpSrc, lpDIBMem, lpConvertLine;
	HPTR hpDstLine;
	DWORD lCount, lImageSize, lInfoSize;
	int dx, dy;
	LPBITMAPINFO lpInfo;
	FRMTYPEINFO SrcTypeInfo, DstTypeInfo;
	CFrameTypeConvert TypeConvert;

	if ( !lpFrame )
		return( NULL );

	FrameGetTypeInfo(lpFrame, &SrcTypeInfo);
	FrameSetTypeInfo(&DstTypeInfo, FDT_RGBCOLOR);

	dx = (lpRect->right  - lpRect->left) + 1;
	dy = (lpRect->bottom - lpRect->top)  + 1;

	lInfoSize = sizeof(BITMAPINFOHEADER);
	bpl = dx * 3;  // Always 24-bit color out

	bpl        = 4 * ((bpl + 3) / 4); // DIB packing
	lImageSize = (long)bpl * dy;
	lCount     = lInfoSize + lImageSize;

	// Allocate the memory to hold the DIB
	if ( !(lpDIBMem = Alloc( lCount )) )
	{
		FrameSetError( ERR_MALLOC );
		return( NULL );
	}

	if ( !(lpConvertLine = Alloc( bpl )) )
	{
		FreeUp(lpDIBMem);
		FrameSetError( ERR_MALLOC );
		return( NULL );
	}

	lpInfo = (LPBITMAPINFO)lpDIBMem;
	lpInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
	lpInfo->bmiHeader.biWidth         = dx;
	lpInfo->bmiHeader.biHeight        = dy;
	lpInfo->bmiHeader.biPlanes        = 1;
	lpInfo->bmiHeader.biCompression   = BI_RGB;
	lpInfo->bmiHeader.biBitCount      = 24;
	lpInfo->bmiHeader.biSizeImage     = lImageSize;
	lpInfo->bmiHeader.biXPelsPerMeter = (10000L * (long) FrameResolution(lpFrame)) / 254L;
	lpInfo->bmiHeader.biYPelsPerMeter = (10000L * (long) FrameResolution(lpFrame)) / 254L;
	lpInfo->bmiHeader.biClrUsed       = 0;
	lpInfo->bmiHeader.biClrImportant  = 0;

	hpDstLine = (HPTR)lpDIBMem;
	hpDstLine += lInfoSize;

	if (!TypeConvert.Init(SrcTypeInfo, DstTypeInfo, dx))
	{
		FreeUp(lpDIBMem);
		FreeUp(lpConvertLine);
		FrameSetError( ERR_MALLOC );
		return( NULL );
	}

	// This goes backwards...
	for (y = lpRect->bottom; y >= lpRect->top; y--)
	{
		lpSrc = FramePointer(lpFrame, lpRect->left, y, NO);
		if (lpSrc)
		{
			TypeConvert.ConvertData(lpSrc, lpConvertLine, y, dx);
			swapBGR( lpConvertLine, lpConvertLine, dx);
			CopyToHuge(lpConvertLine, hpDstLine, bpl);
		}
		hpDstLine += bpl;
	}

	FreeUp(lpConvertLine);

	return( lpDIBMem );
}
示例#9
0
BOOL GradientImage( LPIMAGE lpImage, LPGRADIENT_PARMS lpParms)
{
	LPFRAME lpFrame;
	RECT rMask;
	LPINT lpD;
	FRMTYPEINFO TypeInfo;
	int dx, dy, iCount;
	int index, prev, next, pi, ni;
	long ldx, ldy, x, y, xs, xe, ys, ye, asqrd, bsqrd, r;
	LPDATAPROC lpVignetteProc;
	ENGINE Engine;
	BOOL   DoHSL;
	GRADIENT_DATA data;
	int res;

   FRMDATATYPE type;
	ImgGetInfo(lpImage, NULL, NULL, NULL, &type);
	if (type == FDT_LINEART)
		return(FALSE);
	if (!(lpFrame = ImgGetBaseEditFrame(lpImage)))
		return(FALSE);
	res = FrameResolution(lpFrame);
	data.x1 = lpParms->x1;
	data.y1 = lpParms->y1;
	data.x2 = lpParms->x2;
	data.y2 = lpParms->y2;
	ResConvertUL(lpParms->iBaseRes, res, &data.x1, &data.y1);
	ResConvertLR(lpParms->iBaseRes, res, &data.x2, &data.y2);
	dx = data.x2 - data.x1;
	dy = data.y2 - data.y1;
	data.SoftTransition = lpParms->SoftTransition;
	data.lpPaletteLUT = NULL;

	if (lpParms->Gradient == IDC_VIGLINEAR || lpParms->Gradient == IDC_VIGRADIAL)
	{
		if (abs(dx) <= 3 && abs(dy) <= 3)
			return(FALSE);
	}
	else
	{
		if (abs(dx) <= 3 || abs(dy) <= 3)
			return(FALSE);
	}

	data.xc = (data.x1 + data.x2) / 2;
	data.yc = (data.y1 + data.y2) / 2;

	if ( (data.nRepetitions = lpParms->RepeatCount) <= 0 )
		data.nRepetitions = 1;

	FrameGetTypeInfo(lpFrame, &TypeInfo);

	DoHSL = (lpParms->VigColorModel+IDC_FIRST_MODEL) != IDC_MODEL_RGB &&
				(TypeInfo.DataType > FDT_GRAYSCALE);

	switch (lpParms->Gradient)
	{
		case IDC_VIGLINEAR:
			data.D = lsqrt(((long)dx*(long)dx)+((long)dy*(long)dy));
			data.sine = FGET(-dy, data.D);
			data.cosine = FGET(dx, data.D);
			data.xr = WHOLE(( rotx(data.x2, data.y2, data.x1, data.y1,
            data.cosine, data.sine) ));
			lpVignetteProc = (LPDATAPROC)linear_vignette_proc;
		break;

		case IDC_VIGRADIAL:
			data.D = lsqrt(((long)dx*(long)dx)+((long)dy*(long)dy));
			lpVignetteProc = (LPDATAPROC)radial_vignette_proc;
		break;

		case IDC_VIGCIRCLE:
			data.x1 = data.xc;
			data.y1 = data.yc;
			data.y2 = data.yc;
			dx = data.x2 - data.x1;
			dy = data.y2 - data.y1;
			if (!dx && !dy)
				return(FALSE);
			data.D = lsqrt(((long)dx*(long)dx)+((long)dy*(long)dy));
			lpVignetteProc = (LPDATAPROC)radial_vignette_proc;
		break;

		case IDC_VIGSQUARE:
		case IDC_VIGRECTANGLE:
			data.ymin = min(data.y1, data.y2);
			data.ymax = max(data.y1, data.y2);
			data.xmin = min(data.x1, data.x2);
			data.xmax = max(data.x1, data.x2);

			ldx = data.xmin-data.xc;		// upper left
			ldy = data.ymin-data.yc;
			data.m1 = (256L * ldy) / ldx;
			data.b1 = data.ymin - ((data.m1 * data.xmin)/256L);
			data.D1 = lsqrt((ldx*ldx)+(ldy*ldy));

			ldx = data.xmax-data.xc;		// upper right
			ldy = data.ymin-data.yc;
			data.m2 = (256L * ldy) / ldx;
			data.b2 = data.ymin - ((data.m2 * data.xmax)/256L);
			data.D2 = lsqrt((ldx*ldx)+(ldy*ldy));

			ldx = data.xmax-data.xc;		// lower right
			ldy = data.ymax-data.yc;
			data.m3 = (256L * ldy) / ldx;
			data.b3 = data.ymax - ((data.m3 * data.xmax)/256L);
			data.D3 = lsqrt((ldx*ldx)+(ldy*ldy));

			ldx = data.xmin-data.xc;		// lower left
			ldy = data.ymax-data.yc;
			data.m4 = (256L * ldy) / ldx;
			data.b4 = data.ymax - ((data.m4 * data.xmin)/256L);
			data.D4 = lsqrt((ldx*ldx)+(ldy*ldy));

			lpVignetteProc = (LPDATAPROC)rectangle_vignette_proc;
		break;

		case IDC_VIGELLIPSE:
			if ( !(data.lpD = (LPINT)Alloc((long)sizeof(int)*(TSIZE+1))) )
			{
				Message(IDS_EMEMALLOC);
				return(FALSE);
			}
			iCount = TSIZE+1;
			lpD = data.lpD;
			while (--iCount >= 0)
				*lpD++ = -1;				
			data.ymin = min(data.y1, data.y2);
			data.ymax = max(data.y1, data.y2);
			data.xmin = min(data.x1, data.x2);
			data.xmax = max(data.x1, data.x2);
			data.ea = dx/2;
			data.eb = dy/2;
			if (!data.ea || !data.eb)
			{
				FreeUp((LPTR)data.lpD);
				return(FALSE);
			}
			asqrd = data.ea*data.ea;
			bsqrd = data.eb*data.eb;

			// fill in a table with radius information for the
			// ellipse.  The radius for a given point would be
			// starting from the center of the ellipse, going 
			// through to point, and where it intersects the 
			// edge of the ellipse.  We need the radius for
			// the D value used in the ellipse_proc, which is
			// the maximum distance used for determining how to
			// calculate the gradient, which is d/D.  d is the 
			// distance of the point from the center, D is extracted
			// from the table built below.  The index of the table is
			// formed from the ratio of sides of the triangle formed.
			// This is like looking up the angle to see where the
			// point would intersect the circle.  But we calculate
			// the radii ahead of time to speed things up.
			if (data.ea > data.eb)	// step in x
			{
				xs = data.xc - data.xc;
				xe = data.xmax - data.xc;
				for (x = xs; x <= xe; ++x)
				{
					y = ((data.eb*(long)lsqrt(asqrd - (x*x)))+(data.ea/2))/data.ea;
					r = (x*x)+(y*y);
					if (r <= 0)
						r = 1;
					index = ((x * x * (long)TSIZE)+(r/2)) / r;
					index = bound(abs(index), 0, TSIZE);
					data.lpD[index] = lsqrt(r);
				}
			}
			else		// step in y
			{
				ys = data.yc - data.yc;
				ye = data.ymax - data.yc;
				for (y = ys; y <= ye; ++y)
				{
					x = ((data.ea*(long)lsqrt(bsqrd - (y*y)))+(data.eb/2))/data.eb;
					r = (x*x)+(y*y);
					if (r <= 0)
						r = 1;
					index = ((y * y * (long)TSIZE)+(r/2)) / r;
					index = bound(abs(index), 0, TSIZE);
					data.lpD[index] = lsqrt(r);
				}
			}
			// find the first valid entry in our table
			for (index = 0; index <= TSIZE && data.lpD[index] < 0; ++index)
				;

			// see if we have any entries
			if (index > TSIZE)
			{
				FreeUp((LPTR)data.lpD);
				return(FALSE);
			}

			// fill in all entries before first with value of first
			while (--index >= 0)
				data.lpD[index] = data.lpD[index+1];

			// find last valid entry in table
			for (index = TSIZE; index >= 0 && data.lpD[index] < 0; --index)
				;

			// see if we have any entries
			if (index < 0)
			{
				FreeUp((LPTR)data.lpD);
				return(FALSE);
			}

			// fill in all entries after last with value of last
			while (++index <= TSIZE)
				data.lpD[index] = data.lpD[index-1];

			// interpolate values of all empty cells
			for (index = 0; index <= TSIZE; ++index)
			{
				if (data.lpD[index] < 0)
				{
					pi = index - 1;
					prev = data.lpD[pi];
					ni = index;
					while (data.lpD[ni] < 0)
						++ni;
					next = data.lpD[ni];
					// remember here that (index-pi) == 1
					data.lpD[index] = prev + ((next-prev)/(ni-pi));
				}
			}
			lpVignetteProc = (LPDATAPROC)ellipse_vignette_proc;
		break;

		default:
			return(FALSE);
		break;
	}

	switch(TypeInfo.DataType)
	{
		case FDT_LINEART :
		case FDT_GRAYSCALE :
			data.lpProcessProc = (LPVIGPROC)ProcessVignette8;
		break;

		case FDT_PALETTECOLOR:
			data.lpProcessProc = (LPVIGPROC)ProcessVignette8P;
			data.lpPaletteLUT = CreatePaletteLut15(TypeInfo.ColorMap->RGBData,
					TypeInfo.ColorMap->NumEntries, NULL, NULL);
		break;

		case FDT_RGBCOLOR :
			data.lpProcessProc = (LPVIGPROC)ProcessVignette24;
		break;

		case FDT_CMYKCOLOR :
			data.lpProcessProc = (LPVIGPROC)ProcessVignette32;
		break;
	}

	data.lpMidpointTable = BuildMidPointTable(
							DoHSL,
							TypeInfo.DataType,
							lpParms->Midpoint,
							&lpParms->StartColor,
							&lpParms->EndColor,
							&data );

	ImgGetMaskRect( lpImage, &rMask );
	data.lplD = (LPLONG)Alloc((long)sizeof(long)*(long)RectWidth(&rMask));
	data.lpld = (LPLONG)Alloc((long)sizeof(long)*(long)RectWidth(&rMask));

	if (!data.lpld || !data.lplD || !data.lpMidpointTable ||
		(TypeInfo.DataType == FDT_PALETTECOLOR && !data.lpPaletteLUT))
	{
		if (lpParms->Gradient == IDC_VIGELLIPSE)
			FreeUp((LPTR)data.lpD);
		if (data.lplD)
			FreeUp((LPTR)data.lplD);
		if (data.lpld)
			FreeUp((LPTR)data.lpld);
		if (data.lpMidpointTable)
			FreeUp((LPTR)data.lpMidpointTable);
		if (data.lpPaletteLUT)
			FreeUp(data.lpPaletteLUT);
		return(FALSE);
	}

	SetEngineDraw(&Engine,lpVignetteProc,lpParms->VigOpacity,lpParms->VigMergeMode);
	Engine.lpParam = &data;
	Engine.fThread = NO;
	lpParms->Common.StatusCode = LineEngineSelObj(lpImage,&Engine,lpParms->Common.idDirty);
	if (!AstralIsRectEmpty(&Engine.rUpdate))
	{
		lpParms->Common.UpdateType = UT_AREA;
		lpParms->Common.rUpdateArea = Engine.rUpdate;
	}

	FreeUp((LPTR)data.lpld);
	FreeUp((LPTR)data.lplD);
	FreeUp((LPTR)data.lpMidpointTable);
	if (data.lpPaletteLUT)
		FreeUp(data.lpPaletteLUT);

	if (lpParms->Gradient == IDC_VIGELLIPSE)
		FreeUp((LPTR)data.lpD);
	return(lpParms->Common.StatusCode == SC_SUCCESS);
}