Nanashi-soft○プログラマ専用○Photoshopプラグイン開発○
// ADOBE SYSTEMS INCORPORATED
// Copyright 1993 - 2002 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute this
// file in accordance with the terms of the Adobe license agreement
// accompanying it. If you have received this file from a source
// other than Adobe, then your use, modification, or distribution
// of it requires the prior written permission of Adobe.
//-------------------------------------------------------------------------------
// project header files
#include "Dissolve.h"
#include "DissolveUI.h"
#include "DissolveScripting.h"
#include "DissolveRegistry.h"
#include "FilterBigDocument.h"
#include
//-------------------------------------------------------------------------------
// global variables
//-------------------------------------------------------------------------------
// parameters passed into PluginMain that need to be global to the project
FilterRecord * gFilterRecord = NULL;
intptr_t * gDataHandle = NULL;
int16 * gResult = NULL; // all errors go here
SPBasicSuite * sSPBasic = NULL;
// pointers to our data and parameters defined in Dissolve.h
Data * gData = NULL;
Parameters * gParams = NULL;
//-------------------------------------------------------------------------------
// local routines
//-------------------------------------------------------------------------------
// the six main routines of the plug in
void DoAbout(void);
void DoParameters(void);
void DoPrepare(void);
void DoStart(void);
void DoContinue(void);
void DoFinish(void);
void DoFilter(void);
void CalcProxyScaleFactor(void);
void ConvertRGBColorToMode(const int16 imageMode, FilterColor& color);
void ScaleRect(VRect& destination, const int16 num, const int16 den);
void ShrinkRect(VRect& destination, const int16 width, const int16 height);
void CopyRect(VRect& destination, const VRect& source);
void LockHandles(void);
void UnlockHandles(void);
void CreateParametersHandle(void);
void InitParameters(void);
void CreateDataHandle(void);
void InitData(void);
void DissolveRectangle(void* data,
int32 dataRowBytes,
void* mask,
int32 maskRowBytes,
VRect tileRect,
uint8 color,
int32 depth);
//-------------------------------------------------------------------------------
//
// PluginMain
//
// All calls to the plug in module come through this routine.
//
// Inputs:
// const int16 selector Host provides selector indicating what
// command to do.
//
// Inputs and Outputs:
// FilterRecord *filterRecord Host provides a pointer to parameter block
// containing pertinent data and callbacks.
// See PIFilter.h
//
// intptr_t *data Use this to store a handle or pointer to our global
// data structure, which is maintained by the
// host between calls to the plug in.
//
// Outputs:
// int16 *result Returns error result. Some errors are handled
// by the host, some are silent, and some you
// must handle. See PIGeneral.h.
//
//-------------------------------------------------------------------------------
DLLExport MACPASCAL void PluginMain(const int16 selector,
FilterRecordPtr filterRecord,
intptr_t * data,
int16 * result)
{
// update our global parameters
gFilterRecord = filterRecord;
gDataHandle = data;
gResult = result;
if (selector == filterSelectorAbout)
{
sSPBasic = ((AboutRecord*)gFilterRecord)->sSPBasic;
}
else
{
sSPBasic = gFilterRecord->sSPBasic;
if (gFilterRecord->bigDocumentData != NULL)
gFilterRecord->bigDocumentData->PluginUsing32BitCoordinates = true;
}
// do the command according to the selector
switch (selector)
{
case filterSelectorAbout:
DoAbout();
break;
case filterSelectorParameters:
DoParameters();
break;
case filterSelectorPrepare:
DoPrepare();
break;
case filterSelectorStart:
DoStart();
break;
case filterSelectorContinue:
DoContinue();
break;
case filterSelectorFinish:
DoFinish();
break;
default:
break;
}
// unlock our handles used by gData and gParams
if (selector != filterSelectorAbout)
UnlockHandles();
}
//-------------------------------------------------------------------------------
//
// DoParameters
//
// Makes sure we have valid Data and Parameters handle(s). Locks and initializes
// these items.
//
// NOTE:
// This routine is NOT guaranteed to be called by Photoshop. If a user enters the
// CTRL-F keyboard shortcut to invoke the last filter command this routine will
// NOT be called. If the filter is ran by the actions pallete or an automation
// plug in this routine will NOT be called.
//
// NOTE:
// The fields in the gFilterRecord are not all valid at this stage.
//-------------------------------------------------------------------------------
void DoParameters(void)
{
if (gFilterRecord->parameters == NULL)
CreateParametersHandle();
if ((*gDataHandle) == 0)
CreateDataHandle();
if (*gResult == noErr)
{
LockHandles();
InitParameters();
InitData();
}
}
//-------------------------------------------------------------------------------
//
// DoPrepare
//
// Almost identical to DoParameters. Make sure we have valid Data and Parameters
// handle(s) and lock and initialize as necessary. Sets the bufferSpace and
// maxSpace variables in the gFilterRecord so memory is used at an optimum.
//
// NOTE:
// The fields in the gFilterRecord are not all valid at this stage. We will take a
// guess at the actual tile size information.
//
//-------------------------------------------------------------------------------
void DoPrepare(void)
{
if (gFilterRecord->parameters != NULL && (*gDataHandle) != 0)
LockHandles();
else
{
if (gFilterRecord->parameters == NULL)
CreateParametersHandle();
if ((*gDataHandle) == 0)
CreateDataHandle();
if (*gResult == noErr)
{
LockHandles();
InitParameters();
InitData();
}
}
// we don't need any buffer space
gFilterRecord->bufferSpace = 0;
// give as much memory back to Photoshop as you can
// we only need a tile per plane plus the maskData
// inTileHeight and inTileWidth are invalid at this
// point. Assume the tile size is 256 max.
VRect filterRect = GetFilterRect();
int32 tileHeight = filterRect.bottom - filterRect.top;
int32 tileWidth = filterRect.right - filterRect.left;
if (tileHeight > 256)
tileHeight = 256;
if (tileWidth > 256)
tileWidth = 256;
int32 tileSize = tileHeight * tileWidth;
int32 planes = gFilterRecord->planes;
if (gFilterRecord->maskData != NULL)
planes++;
// duplicate because we have two copies, inData and outData
planes *= 2;
int32 totalSize = tileSize * planes;
// this is worst case and can be dropped considerably
if (gFilterRecord->maxSpace > totalSize)
gFilterRecord->maxSpace = totalSize;
}
//-------------------------------------------------------------------------------
//
// DoStart
//
// The main filtering routine for this plug in. See if we have any registry
// parameters from the last time we ran. Determine if the UI needs to be
// displayed by reading the script parameters. Save the last dialog parameters
// in case something goes wrong or the user cancels.
//
//-------------------------------------------------------------------------------
void DoStart(void)
{
LockHandles();
// see if we have any information in the Photoshop registry
ReadRegistryParameters();
// save parameters
int16 lastDisposition = gParams->disposition;
int16 lastPercent = gParams->percent;
Boolean lastIgnoreSelection = gParams->ignoreSelection;
// does the user want a dialog
Boolean isOK = true;
Boolean displayDialog;
OSErr err = ReadScriptParameters(&displayDialog);
err; // turn off compiler warning for now
// run the dialog on the specific OS
if (!err && displayDialog)
isOK = DoUI();
// we know we have enough information to run without next time
gData->queryForParameters = false;
if (isOK)
{
// the main processing routine
DoFilter();
}
else
{
// restore if the user hit cancel
gParams->disposition = lastDisposition;
gParams->percent = lastPercent;
gParams->ignoreSelection = lastIgnoreSelection;
*gResult = userCanceledErr;
}
}
//-------------------------------------------------------------------------------
//
// DoContinue
//
// If we get here we probably did something wrong. This selector was needed
// before advanceState() was in the FilterRecord*. Now that we use advanceState()
// there is nothing for us to do but set all the rectangles to 0 and return.
//
//-------------------------------------------------------------------------------
void DoContinue(void)
{
VRect zeroRect = { 0, 0, 0, 0 };
SetInRect(zeroRect);
SetOutRect(zeroRect);
SetMaskRect(zeroRect);
}
//-------------------------------------------------------------------------------
//
// DoFinish
//
// Everything went as planned and the pixels have been modified. Now record
// scripting parameters and put our information in the Photoshop Registry for the
// next time we get called. The Registry saves us from keeping a preferences file.
//
//-------------------------------------------------------------------------------
void DoFinish(void)
{
LockHandles();
WriteScriptParameters();
WriteRegistryParameters();
}
//-------------------------------------------------------------------------------
//
// DoFilter
//
// Randomly change the pixel values based on the parameters the user gave us from
// our dialog box or scripting. We do this a tile at a time making sure the rect.
// we ask for is in the bounds of the filterRect.
//
//-------------------------------------------------------------------------------
void DoFilter(void)
{
// make the random number generated trully random
srand((unsigned)time(NULL));
int32 tileHeight = gFilterRecord->outTileHeight;
int32 tileWidth = gFilterRecord->outTileWidth;
if (tileWidth == 0 || tileHeight == 0)
{
*gResult = filterBadParameters;
return;
}
VRect filterRect = GetFilterRect();
int32 rectWidth = filterRect.right - filterRect.left;
int32 rectHeight = filterRect.bottom - filterRect.top;
CreateDissolveBuffer(tileWidth, tileHeight);
// round up to the nearest horizontal and vertical tile count
int32 tilesVert = (tileHeight - 1 + rectHeight) / tileHeight;
int32 tilesHoriz = (tileWidth - 1 + rectWidth) / tileWidth;
// Fixed numbers are 16.16 values
// the first 16 bits represent the whole number
// the last 16 bits represent the fraction
gFilterRecord->inputRate = (int32)1 << 16;
gFilterRecord->maskRate = (int32)1 << 16;
// variables for the progress bar, our plug in is so fast
// we probably don't need these
int32 progressTotal = tilesVert * tilesHoriz;
int32 progressDone = 0;
// loop through each tile makeing sure we don't go over the bounds
// of the rectHeight or rectWidth
for (int32 vertTile = 0; vertTile < tilesVert; vertTile++)
{
for (int32 horizTile = 0; horizTile < tilesHoriz; horizTile++)
{
UpdateDissolveBuffer(tileWidth, tileHeight);
VRect filterRect = GetFilterRect();
VRect inRect = GetInRect();
inRect.top = vertTile * tileHeight + filterRect.top;
inRect.left = horizTile * tileWidth + filterRect.left;
inRect.bottom = inRect.top + tileHeight;
inRect.right = inRect.left + tileWidth;
if (inRect.bottom > rectHeight)
inRect.bottom = rectHeight;
if (inRect.right > rectWidth)
inRect.right = rectWidth;
SetInRect(inRect);
// duplicate what's in the inData with the outData
SetOutRect(inRect);
// get the maskRect if the user has given us a selection
if (gFilterRecord->haveMask)
{
SetMaskRect(inRect);
}
for (int16 plane = 0; plane < gFilterRecord->planes; plane++)
{
// we want one plane at a time, small memory foot print is good
gFilterRecord->outLoPlane = gFilterRecord->inLoPlane = plane;
gFilterRecord->outHiPlane = gFilterRecord->inHiPlane = plane;
// update the gFilterRecord with our latest request
*gResult = gFilterRecord->advanceState();
if (*gResult != noErr) return;
// muck with the pixels in the outData buffer
uint8 color = 255;
int16 expectedPlanes = CSPlanesFromMode(gFilterRecord->imageMode, 0);
if (plane < expectedPlanes)
color = gData->color[plane];
color=(uint8)plane;
DissolveRectangle(gFilterRecord->outData,
gFilterRecord->outRowBytes,
gFilterRecord->maskData,
gFilterRecord->maskRowBytes,
GetOutRect(),
color,
gFilterRecord->depth);
}
// uh, update the progress bar
gFilterRecord->progressProc(++progressDone, progressTotal);
// see if the user is impatient or didn't mean to do that
if (gFilterRecord->abortProc())
{
*gResult = userCanceledErr;
return;
}
}
}
DeleteDissolveBuffer();
}
//-------------------------------------------------------------------------------
//
// DissolveRectangle
//
// This is our core algorithm for changing pixels randomly to a new color. We
// have to look at the maskPixel and the ignoreSelection parameter to know if we
// should or should not modify the pixel. This routine gets a little messy
// because it handles both 8 bit, 16 bit and 32 bit images.
//
//-------------------------------------------------------------------------------
void DissolveRectangle(void* data,
int32 dataRowBytes,
void* mask,
int32 maskRowBytes,
VRect tileRect,
uint8 color,
int32 depth)
{
static int8 amari[4]={0,0,0,0}; //余りを保持する変数
static uint8 oldcolor[4]={0,0,0,0}; //1つ前のドットの色
uint8* pixel = (uint8*)data;
uint16* bigPixel = (uint16*)data;
float* fPixel = (float*)data;
uint8* maskPixel = (uint8*)mask;
// Ptr dissolve = gData->dissolveBuffer;
int32 rectHeight = tileRect.bottom - tileRect.top;
int32 rectWidth = tileRect.right - tileRect.left;
uint16 bigColor = (uint16)(((uint32)color * 1285 + 5) / 10);
float fColor = (float)((float)color / (float)255);
for(int32 pixelY = 0; pixelY < rectHeight; pixelY++)
{
for(int32 pixelX = 0; pixelX < rectWidth; pixelX++)
{
bool leaveItAlone = false;
if (maskPixel != NULL && !(*maskPixel) && !gParams->ignoreSelection)
leaveItAlone = true;
// if (*dissolve && !leaveItAlone)
if (!leaveItAlone)
{
if (depth == 32)
*fPixel = fColor;
else if (depth == 16)
*bigPixel = bigColor;
else {
uint8 savecolor=*pixel;
if(*pixel != oldcolor[color]){
if(0xff < (int)*pixel + (int)amari[color]){
*pixel = 0xff;
}else if((int)*pixel + (int)amari[color] < 0){
*pixel = 0x00;
}else{
*pixel = *pixel + amari[color];
}
}
oldcolor[color]=savecolor;
if(*pixel & 0x08){
amari[color] = -0x0f + (*pixel & 0x0f);
*pixel = *pixel | 0x0f;
}else{
amari[color] = *pixel & 0x0f;
*pixel = *pixel & 0xf0;
}
}
}
pixel++;
bigPixel++;
fPixel++;
// dissolve++;
if (maskPixel != NULL)
maskPixel++;
}
pixel += (dataRowBytes - rectWidth);
bigPixel += (dataRowBytes / 2 - rectWidth);
fPixel += (dataRowBytes / 4 - rectWidth);
if (maskPixel != NULL)
maskPixel += (maskRowBytes - rectWidth);
}
}
//-------------------------------------------------------------------------------
//
// CreateParametersHandle
//
// Create a handle to our Parameters structure. Photoshop will take ownership of
// this handle and delete it when necessary.
//-------------------------------------------------------------------------------
void CreateParametersHandle(void)
{
gFilterRecord->parameters = gFilterRecord->handleProcs->newProc(sizeof(Parameters));
if (gFilterRecord->parameters == NULL)
*gResult = memFullErr;
}
//-------------------------------------------------------------------------------
//
// InitParameters
//
// Initialize our UI parameters. gParams is guaranteed to point at something
//-------------------------------------------------------------------------------
void InitParameters(void)
{
gParams->disposition = 1;
gParams->ignoreSelection = false;
gParams->percent = 50;
}
//-------------------------------------------------------------------------------
//
// CreateDataHandle
//
// Create a pointer to our Data structure. Photoshop will take ownership of this
// and give it back to use on any future calls.
//-------------------------------------------------------------------------------
void CreateDataHandle(void)
{
Handle h = gFilterRecord->handleProcs->newProc(sizeof(Data));
if (h != NULL)
*gDataHandle = (intptr_t)h;
else
*gResult = memFullErr;
}
//-------------------------------------------------------------------------------
//
// InitData
//
// Initialize the gData pointer
//-------------------------------------------------------------------------------
void InitData(void)
{
CopyColor(gData->colorArray[0], gFilterRecord->backColor);
SetColor(gData->colorArray[1], 0, 0, 255, 0);
SetColor(gData->colorArray[2], 255, 0, 0, 0);
SetColor(gData->colorArray[3], 0, 255, 0, 0);
for(int a = 1; a < 4; a++)
ConvertRGBColorToMode(gFilterRecord->imageMode, gData->colorArray[a]);
CopyColor(gData->color, gData->colorArray[gParams->disposition]);
gData->proxyRect.left = 0;
gData->proxyRect.right = 0;
gData->proxyRect.top = 0;
gData->proxyRect.bottom = 0;
gData->scaleFactor = 1.0;
gData->queryForParameters = true;
gData->dissolveBufferID = NULL;
gData->dissolveBuffer = NULL;
gData->proxyBufferID = NULL;
gData->proxyBuffer = NULL;
gData->proxyWidth = 0;
gData->proxyHeight = 0;
gData->proxyPlaneSize = 0;
}
//-------------------------------------------------------------------------------
//
// CreateDissolveBuffer
//
// Updates the dissolve array varaibles in the gData block. This allows us to
// process one plane at a time
//
// Global Inputs and Outputs:
// BufferID gData->dissolveBufferID ID number of the current buffer in use
// if it exists we must delete and get
// another one.
//
// Ptr gData->dissolveBuffer Actual array containing the dissolve
// from the current settings of
// gParams->percent
//
//-------------------------------------------------------------------------------
void CreateDissolveBuffer(const int32 width, const int32 height)
{
BufferProcs *bufferProcs = gFilterRecord->bufferProcs;
bufferProcs->allocateProc(width * height, &gData->dissolveBufferID);
gData->dissolveBuffer = bufferProcs->lockProc(gData->dissolveBufferID, true);
}
//-------------------------------------------------------------------------------
//
// UpdateDissolveBuffer
//
// Updates the dissolve buffer array varaibles in the gData block. This allows us
// to process one plane at a time
//
// Global Inputs and Outputs:
// Ptr gData->dissolveBuffer Actual array containing the dissolve
// from the current settings of
// gParams->percent
//
//-------------------------------------------------------------------------------
void UpdateDissolveBuffer(const int32 width, const int32 height)
{
if (gData->dissolveBuffer != NULL)
{
Ptr dissolve = gData->dissolveBuffer;
for (int32 x = 0; x < width; x++)
{
for (int32 y = 0; y < height; y++)
{
*dissolve = ((unsigned16) rand()) % 100 < gParams->percent;
dissolve++;
}
}
}
}
//-------------------------------------------------------------------------------
//
// DeleteDissolveBuffer
//
// Deletes the dissolve array varaibles in the gData block.
//
// Global Inputs and Outputs:
// BufferID gData->dissolveBufferID ID number of the current buffer in use
// if it exists we must delete and get
// another one.
//
// Ptr gData->dissolveBuffer Actual array containing the dissolve
// from the current settings of
// gParams->percent
//
//-------------------------------------------------------------------------------
void DeleteDissolveBuffer(void)
{
if (gData->dissolveBufferID != NULL)
{
gFilterRecord->bufferProcs->unlockProc(gData->dissolveBufferID);
gFilterRecord->bufferProcs->freeProc(gData->dissolveBufferID);
gData->dissolveBufferID = NULL;
gData->dissolveBuffer = NULL;
}
}
//-------------------------------------------------------------------------------
//
// SetupFilterRecordForProxy
//
// Called by the UI routine to set up the gFilterRecord with the proxy view
// information. CalcProxyScaleFactor sizes the proxy rectangle and calculates the
// scale factor. Then set up gFilterRecord and call advanceState() to init the
// inData with the pixel data for the display.
//
// Global Inputs and Outputs:
// FilterRecord *gFilterRecord inRect, inRowBytes, maskRect, etc. has all
// the information needed to call
// advanceState so inData points to the proxy
// pixel data and maskRect points to the
// selection data
//
//-------------------------------------------------------------------------------
void SetupFilterRecordForProxy(void)
{
CalcProxyScaleFactor();
SetInRect(GetFilterRect()); // gFilterRecord->inRect = gFilterRecord->filterRect;
VRect tempRect = GetInRect();
ScaleRect(tempRect, 1, (int16)gData->scaleFactor);
SetInRect(tempRect);
SetMaskRect(GetInRect()); // gFilterRecord->maskRect = gFilterRecord->inRect;
// Fixed numbers are 16.16 values
// the first 16 bits represent the whole number
// the last 16 bits represent the fraction
gFilterRecord->inputRate = (int32)gData->scaleFactor << 16;
gFilterRecord->maskRate = (int32)gData->scaleFactor << 16;
gFilterRecord->inputPadding = 255;
gFilterRecord->maskPadding = gFilterRecord->inputPadding;
gData->proxyWidth = gData->proxyRect.right - gData->proxyRect.left;
gData->proxyHeight = gData->proxyRect.bottom - gData->proxyRect.top;
gData->proxyPlaneSize = gData->proxyWidth * gData->proxyHeight;
}
//-------------------------------------------------------------------------------
//
// CalcProxyScaleFactor
//
// Called by the UI routine to change the size of the Proxy rectangle and
// calculate the scale factor. This information is needed by the displayPixels
// routine and the advanceState routine.
//
// Global Inputs:
// Rect gFilterRecord->filterRect Rectangle to filter
//
// Global Inputs and Outputs:
// Rect gData->proxyRect Rectangle for the Proxy to display in
// float gData->scaleFactor Scale factor of the filterRect
// to the ProxyRect
//
//-------------------------------------------------------------------------------
void CalcProxyScaleFactor(void)
{
int32 filterHeight, filterWidth, itemHeight, itemWidth;
VPoint fraction;
VRect filterRect = GetFilterRect();
// we place a black frame around the proxy and leave a black
// between the frame and the actual pixel data
ShrinkRect(gData->proxyRect, 2, 2);
filterHeight = filterRect.bottom - filterRect.top;
filterWidth = filterRect.right - filterRect.left;
itemHeight = (gData->proxyRect.bottom - gData->proxyRect.top);
itemWidth = (gData->proxyRect.right - gData->proxyRect.left);
// make sure the proxy isn't bigger than the image after the calculation
// this will make the proxy half the size for images smaller than the proxy
if (itemHeight > filterHeight)
itemHeight = filterHeight;
if (itemWidth > filterWidth)
itemWidth = filterWidth;
fraction.h = ((filterWidth + itemWidth) / itemWidth);
fraction.v = ((filterHeight + itemHeight) / itemHeight);
// calculate the scale factor based on the smaller of height or width
if (fraction.h > fraction.v)
gData->scaleFactor = ((float)filterWidth + (float)itemWidth) / (float)itemWidth;
else
gData->scaleFactor = ((float)filterHeight + (float)itemHeight) / (float)itemHeight;
CopyRect(gData->proxyRect, filterRect);
ScaleRect(gData->proxyRect, 1, (int16)gData->scaleFactor);
// recalculate the scale factor based on the actual proxy size
// this will reduce rounding errors in the proxy view
if (fraction.h > fraction.v)
gData->scaleFactor = (float)filterWidth / (float)(gData->proxyRect.right - gData->proxyRect.left);
else
gData->scaleFactor = (float)filterHeight / (float)(gData->proxyRect.bottom - gData->proxyRect.top);
}
//-------------------------------------------------------------------------------
//
// ConvertRGBColorToMode
//
// Convert the FilterColor from RGB mode to the imageMode using the color
// services call backs.
//
// Inputs:
// int16 imageMode Mode to convert the color to
// Inputs and Outputs:
// FilterColor& color RGB color to convert
//
//-------------------------------------------------------------------------------
void ConvertRGBColorToMode(const int16 imageMode, FilterColor& color)
{
if (imageMode != plugInModeRGBColor)
{
ColorServicesInfo csInfo;
csInfo.selector = plugIncolorServicesConvertColor;
csInfo.sourceSpace = plugIncolorServicesRGBSpace;
csInfo.reservedSourceSpaceInfo = NULL;
csInfo.reservedResultSpaceInfo = NULL;
csInfo.reserved = NULL;
csInfo.selectorParameter.pickerPrompt = NULL;
csInfo.infoSize = sizeof(csInfo);
csInfo.resultSpace = CSModeToSpace(gFilterRecord->imageMode);
for (int16 a = 0; a < 4; a++)
csInfo.colorComponents[a] = color[a];
if (!(gFilterRecord->colorServices(&csInfo)))
for (int16 b = 0; b < 4; b++)
color[b] = (int8)csInfo.colorComponents[b];
}
}
//-------------------------------------------------------------------------------
//
// LockHandles
//
// Lock the handles and get the pointers for gData and gParams
// Set the global error, *gResult, if there is trouble
//
//-------------------------------------------------------------------------------
void LockHandles(void)
{
if (gFilterRecord->parameters == NULL || (*gDataHandle) == 0)
{
*gResult = filterBadParameters;
return;
}
gParams = (Parameters*)gFilterRecord->handleProcs->lockProc(gFilterRecord->parameters, TRUE);
gData = (Data*)gFilterRecord->handleProcs->lockProc((Handle)*gDataHandle, TRUE);
if (gParams == NULL || gData == NULL)
{
*gResult = memFullErr;
return;
}
}
//-------------------------------------------------------------------------------
//
// UnlockHandles
//
// Unlock the handles used by the data and params pointers
//
//-------------------------------------------------------------------------------
void UnlockHandles(void)
{
if ((*gDataHandle) != 0)
gFilterRecord->handleProcs->unlockProc((Handle)*gDataHandle);
if (gFilterRecord->parameters != NULL)
gFilterRecord->handleProcs->unlockProc(gFilterRecord->parameters);
}
//-------------------------------------------------------------------------------
//
// ScaleRect
//
// Utility routine for scaling a rectangle by a rational
//
//-------------------------------------------------------------------------------
void ScaleRect(VRect& destination, const int16 num, const int16 den)
{
if (den != 0)
{
destination.left = (int16)((destination.left * num) / den);
destination.top = (int16)((destination.top * num) / den);
destination.right = (int16)((destination.right * num) / den);
destination.bottom = (int16)((destination.bottom * num) / den);
}
}
//-------------------------------------------------------------------------------
//
// ShrinkRect
//
// Utility routine for shrinking a Rect by a width and height
//
//-------------------------------------------------------------------------------
void ShrinkRect(VRect& destination, const int16 width, const int16 height)
{
destination.left = (int16)(destination.left + width);
destination.top = (int16)(destination.top + height);
destination.right = (int16)(destination.right - width);
destination.bottom = (int16)(destination.bottom - height);
}
//-------------------------------------------------------------------------------
//
// CopyRect
//
// Utility routine for setting a Rect from a VRect
//
//-------------------------------------------------------------------------------
void CopyRect(VRect& destination, const VRect& source)
{
destination.left = source.left;
destination.top = source.top;
destination.right = source.right;
destination.bottom = source.bottom;
}
//-------------------------------------------------------------------------------
//
// CopyColor
//
// Utility routine for setting a FilterColor array from a FilterColor
//
//-------------------------------------------------------------------------------
void CopyColor(FilterColor& destination, const FilterColor& source)
{
for (int a = 0; a < sizeof(FilterColor); a++)
destination[a] = source[a];
}
//-------------------------------------------------------------------------------
//
// SetColor
//
// Utility routine for setting a FilterColor array from 4 color components
//
//-------------------------------------------------------------------------------
void SetColor(FilterColor& destination,
const uint8 a,
const uint8 b,
const uint8 c,
const uint8 d)
{
destination[0] = a;
destination[1] = b;
destination[2] = c;
destination[3] = d;
}
//-------------------------------------------------------------------------------
//
// CreateProxyBuffer
//
//-------------------------------------------------------------------------------
void CreateProxyBuffer(void)
{
int32 proxySize = gData->proxyPlaneSize * gFilterRecord->planes;
gFilterRecord->bufferProcs->allocateProc(proxySize, &gData->proxyBufferID);
gData->proxyBuffer = gFilterRecord->bufferProcs->lockProc(gData->proxyBufferID, true);
}
//-------------------------------------------------------------------------------
//
// ResetProxyBuffer
//
//-------------------------------------------------------------------------------
extern "C" void ResetProxyBuffer(void)
{
uint8* proxyPixel = (uint8*)gData->proxyBuffer;
if (proxyPixel != NULL)
{
for (int16 plane = 0; plane < gFilterRecord->planes; plane++)
{
gFilterRecord->inLoPlane = plane;
gFilterRecord->inHiPlane = plane;
*gResult = gFilterRecord->advanceState();
if (*gResult != noErr) return;
uint8* inPixel = (uint8*)gFilterRecord->inData;
for (int32 y = 0; y < gData->proxyHeight; y++)
{
uint8* start = inPixel;
for (int32 x = 0; x < gData->proxyWidth; x++)
{
if (gFilterRecord->depth == 32)
{
float * reallyBigPixel = (float*)inPixel;
if ( *reallyBigPixel > 1.0 )
*reallyBigPixel = 1.0;
if ( *reallyBigPixel < 0.0 )
*reallyBigPixel = 0.0;
*proxyPixel = (uint8)(*reallyBigPixel * 255);
inPixel+=4;
} else if (gFilterRecord->depth == 16)
{
uint16* bigPixel = (uint16*)inPixel;
*proxyPixel = (uint8)(*bigPixel * 10 / 1285);
inPixel+=2;
}
else
{
*proxyPixel = *inPixel;
inPixel++;
}
proxyPixel++;
}
inPixel = start + gFilterRecord->inRowBytes;
// inPixel += (gFilterRecord->inRowBytes - gData->proxyWidth);
// if (gFilterRecord->depth == 16)
// inPixel -= gData->proxyWidth;
}
}
}
}
//-------------------------------------------------------------------------------
//
// UpdateProxyBuffer
//
//-------------------------------------------------------------------------------
extern "C" void UpdateProxyBuffer(void)
{
Ptr localData = gData->proxyBuffer;
if (localData != NULL)
{
UpdateDissolveBuffer(gData->proxyWidth, gData->proxyHeight);
for (int16 plane = 0; plane < gFilterRecord->planes; plane++)
{
uint8 color = 255;
uint16 expectedPlanes = CSPlanesFromMode(gFilterRecord->imageMode, 0);
if (plane < expectedPlanes)
color = gData->color[plane];
color=(uint8)plane;
DissolveRectangle(localData,
gData->proxyWidth,
gFilterRecord->maskData,
gFilterRecord->maskRowBytes,
gData->proxyRect,
color,
8);
localData += (gData->proxyPlaneSize);
}
}
}
//-------------------------------------------------------------------------------
//
// DeleteProxyBuffer
//
//-------------------------------------------------------------------------------
void DeleteProxyBuffer(void)
{
gFilterRecord->bufferProcs->unlockProc(gData->proxyBufferID);
gFilterRecord->bufferProcs->freeProc(gData->proxyBufferID);
gData->proxyBufferID = NULL;
gData->proxyBuffer = NULL;
}
//-------------------------------------------------------------------------------
//
// DisplayPixelsMode
//
// Convert the imageMode into a display mode so we can use displayPixels.
// All of the 16 bit data is converted to 8 bit.
//
//-------------------------------------------------------------------------------
int32 DisplayPixelsMode(int16 mode)
{
int32 returnMode = mode;
switch (mode)
{
case plugInModeGray16:
case plugInModeGray32:
returnMode = plugInModeGrayScale;
break;
case plugInModeRGB96:
case plugInModeRGB48:
returnMode = plugInModeRGBColor;
break;
case plugInModeLab48:
returnMode = plugInModeLabColor;
break;
case plugInModeCMYK64:
returnMode = plugInModeCMYKColor;
break;
case plugInModeDeepMultichannel:
returnMode = plugInModeMultichannel;
break;
case plugInModeDuotone16:
returnMode = plugInModeDuotone;
break;
}
return (returnMode);
}
// end Dissolve.cpp