ColorRamp.C
This demonstrates a node with no inputs, such as the color node.
This also shows how a node can change its size and/or type depending
on user input.
/*
Plugin Tutorial
example 6 - CircleRamp.C
Generate a circular ramp or matte image. This node works like
the color node, in that it takes no input and generates an image
of user-selectable size.
*/
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <math.h>
#include "cpi.h"
#define TRUE 1
#define FALSE 0
template <class T>
void make_ramp(T *image, float radii[], float values[], int oval,
int chans, T max, int sizeX, int sizeY)
{
int i, x, y;
float dx, dy, xcen, ycen, radius, d;
float minval=values[0], maxval=values[1];
float minrad=radii[0], maxrad=radii[1], scalefac;
T *ptr, val;
ptr = image;
xcen = (float)sizeX / 2.0;
ycen = (float)sizeY / 2.0;
// next 3 lines just for boundary conditions
d = maxrad - minrad;
if (fabs(d) < 0.0001)
minrad = maxrad - 0.0001;
scalefac = (maxval - minval)/(maxrad - minrad);
radius = (sizeX >= sizeY ? ycen : xcen);
for (y = 0; y < sizeY; y++)
{
for (x = 0; x < sizeX; x++)
{
// for each (x, y) compute d, the distance to the
// center of the image
dx = (float)x - xcen;
dy = (float)y - ycen;
d = sqrt(dx*dx + dy*dy) / radius;
// make it so that 0.0 <= d <= 1.0
if (d < minrad) d = minrad;
else if (d > maxrad) d = maxrad;
d = (d - minrad)*scalefac + minval;
val = d * max; // compute color
// put in color, update pointer
for (i = 0; i < chans; i++)
*ptr++ = val;
}
}
}
// Tell Chalice to put this plugin into the I/O menu
CPI_PluginType upiPluginType(void)
{
return T_IO;
}
// because we are computing pixel values based on distance from the
// center of the image, slicing the image would mess up our
// calculations. Deal with this by forcing Chalice to cook the
// image at full size.
int upiCookFull(void)
{
return TRUE;
}
// This section defines the user interface (UI)
#define RADIUS "In Out Radius"
#define AMOUNT "In Out Value"
#define SIZE "Width Height"
#define OUTPUT "Image Type"
#define BITS "Image Depth"
CPIDSOEXPORT void upiCreateParameters( void )
{
char *cmenu[] = {"RGBA", "RGB", "Alpha", NULL};
char *bmenu[] = {"8 bit", "16 bit", "Float", NULL};
float rvals[] = {0.0, 1.0};
float avals[] = {1.0, 0.0};
int svals[] = {512, 512};
cpiAddTab("Circle Ramp");
cpiAddFloatVector(RADIUS, 2, rvals, 0.0, 1.0, P_MINMAX|P_ANIMATE);
cpiAddFloatVector(AMOUNT, 2, avals, 0.0, 1.0, P_MINMAX|P_ANIMATE);
cpiAddIntVector( SIZE, 2, svals, 1, 1024, P_MIN|P_ANIMATE);
cpiAddMenu(OUTPUT, 0, cmenu, 0);
cpiAddMenu(BITS, 0, bmenu, 0);
}
CPIDSOEXPORT void upiNumberOfInputs( int *min, int *max )
{
*min = *max = 0;
}
// This tells Chalice that we are going to create a new output
CPIDSOEXPORT int upiResultInput( CPI_ImageContext *result )
{
return RESULT_SEPARATE;
}
// This tells Chalice that whenever a parameter is changed, the output
// will need to be recooked
void upiParameterChanged(char *name)
{
cpiInvalidateOutput();
}
// This is where the plugin decides how large an image, and of what
// type, it is supposed to create.
CPIDSOEXPORT int upiOutputContext(CPI_ImageContext *output, float time)
{
int chans, pelType, sizeX, sizeY;
cpiGetIntVector( SIZE, time, 0, &sizeX);
cpiGetIntVector( SIZE, time, 1, &sizeY);
output->fullX = sizeX;
output->fullY = sizeY;
cpiGetInteger(BITS, 0.0, &pelType);
if (pelType == 0)
output->pelType = P_INT8;
else if (pelType == 1)
output->pelType = P_INT16;
else if (pelType == 2)
output->pelType = P_FLOAT32;
else
{
cpiError("Unknown channel type");
return 1;
}
cpiGetInteger(OUTPUT, 0.0, &chans);
if (chans == 0)
output->channels = 4; // rgba
else if (chans == 1)
output->channels = 3; // rgb
else if (chans == 2)
output->channels = 1; // alpha only
else
{
cpiError("Unknown output type");
return 1;
}
output->offsetX = output->offsetY = 0;
return 0;
}
CPIDSOEXPORT int upiProcessImage( CPI_Image *result )
{
int sizeX, sizeY, type, oval, chans;
float radii[2], values[2], time;
// unload values from UI fields, and pass to ramp making
// subroutine
sizeX = result->info.sizeX;
sizeY = result->info.sizeY;
chans = result->info.channels;
time = result->info.time;
cpiGetFloatVector( RADIUS, time, 0, radii+0);
cpiGetFloatVector( RADIUS, time, 1, radii+1);
cpiGetFloatVector( AMOUNT, time, 0, values+0);
cpiGetFloatVector( AMOUNT, time, 1, values+1);
cpiGetInteger( OVAL, 0.0, &oval);
switch( result->info.pelType )
{
case P_INT8:
{
make_ramp( (unsigned char *)result->data,
radii, values, oval, chans,
(unsigned char)UCHAR_MAX, sizeX, sizeY);
break;
}
case P_INT16:
{
make_ramp( (unsigned short *)result->data,
radii, values, oval, chans,
(unsigned short)USHRT_MAX, sizeX, sizeY);
break;
}
case P_FLOAT32:
{
make_ramp( (float *)result->data,
radii, values, oval, chans,
(float)1.0F, sizeX, sizeY);
break;
}
default:
cpiError( "Unknown pixel type" );
return 1;
}
return 0;
}
[Table of Contents]
[Index]
Copyright © 1998 Silicon Grail Inc.
710 Seward Street, Hollywood, CA 90038