MultiBright.C
This demonstrates the use of the multiprocessing calls to have a
plugin execute sections of code on multiple processors simultaneously.
The programmer needs to provide each call with its own section of the
image to work on. This is most easily accomplished through a passed
structure.
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <memory.h>
#include "cpi.h"
CPIDSOEXPORT void upiCreateParameters( void )
{
// First let's add a "Tab":
cpiAddTab( "Parameters" );
// Now let's add the brightness parameter
cpiAddFloat( "Brightness", 1.0F, 0.0F, 10.0F, P_ANIMATE );
}
// This is the data that the Bright routine will need - since
// multiprocess routines all take a single argument, this is
// the way to pass in multiple arguments
template <class TYPE>
struct Data
{
TYPE *image;
int numpix;
float brightness;
};
typedef Data<unsigned char> DataChar;
typedef Data<unsigned short> DataShort;
typedef Data<float> DataFloat;
/*
Need to define a separate routine for each pixel type - a copy
of the routine will be executed on each processor, with
proc = the processor number (starting from 0)
numProc = the number of available processors
*arg = a pointer to a block of data that the routine will need
*/
void MultiBrightChar( int proc, int numProc, void *arg )
{
// initialize the incoming data
DataChar *data = (DataChar *)arg;
unsigned char *image = data[proc].image;
float brightness = data[proc].brightness;
float max = UCHAR_MAX;
int numpix = data[proc].numpix;
float val;
// Go through all pixels
while( numpix-- )
{
// Apply the brightness
val = (float)*image * brightness;
// Clip the result to make sure it's within range
if( val > max ) val = max;
if( val < 0 ) val = 0;
// We're done, go to the next pixel
*image = val;
image++;
}
}
void MultiBrightShort( int proc, int numProc, void *arg )
{
// initialize the incoming data
DataShort *data = (DataShort *)arg;
unsigned short *image = data[proc].image;
float brightness = data[proc].brightness;
float max = USHRT_MAX;
int numpix = data[proc].numpix;
float val;
// Go through all pixels
while( numpix-- )
{
// Apply the brightness
val = (float)*image * brightness;
// Clip the result to make sure it's within range
if( val > max ) val = max;
if( val < 0 ) val = 0;
// We're done, go to the next pixel
*image = val;
image++;
}
}
void MultiBrightFloat( int proc, int numProc, void *arg )
{
// initialize the incoming data
Data<float> *data = (Data<float> *)arg;
float *image = data[proc].image;
float brightness = data[proc].brightness;
float max = 1.0F;
int numpix = data[proc].numpix;
float val;
// Go through all pixels
while( numpix-- )
{
// Apply the brightness
val = (float)*image * brightness;
// Clip the result to make sure it's within range
if( val > max ) val = max;
if( val < 0 ) val = 0;
// We're done, go to the next pixel
*image = val;
image++;
}
}
/*
We can't slice or do ROI
*/
CPIDSOEXPORT int upiCookFull( void )
{
return 1;
}
/*
Split the image up into pieces - this must be done by the
programmer prior to the multiprocessing. Each 'data' block
holds a pointer to the start of a separate section of image, a
number of pixels to process, and the brightness value to use on
this section of image. Each call to the MultiBright fuction (the
func() of the documentation) will use the data block indexed by
that processor number, eg processor 2 will use data[2] values
(processors are numbered from 0).
*/
template <class TYPE>
void SplitImagePixels( Data<TYPE> *data, CPI_Image *img,
int procs, float b )
{
int len = img->info.sizeX * img->info.sizeY * img->info.channels;
int piecesize = len/procs;
int i;
for( i = 0; i < procs; i++ )
{
data[i].image = ((TYPE *)img->data) + piecesize * i;
data[i].numpix = piecesize;
data[i].brightness = b;
}
// correct size of last piece
data[procs-1].numpix = len - piecesize * (procs - 1);
}
CPIDSOEXPORT
int upiProcessImage( CPI_Image *result )
{
float brightness;
int procs = cpiNumProcessors();
// First, we get the brightness parameter
if(cpiGetFloat("Brightness", result->info.time, &brightness) != 0)
{
cpiError( "Could not get brightness parameter" );
return -1;
}
switch( result->info.pelType)
{
// for each type of pixel, allocate the data and then
// call the appropriate routine
case P_INT8:
{
DataChar *data = new DataChar[procs];
SplitImagePixels( data, result, procs, brightness );
cpiMultiProcess( MultiBrightChar, (void *)data );
break;
}
case P_INT16:
{
DataShort *data = new DataShort[procs];
SplitImagePixels( data, result, procs, brightness );
cpiMultiProcess( MultiBrightShort, (void *)data );
break;
}
case P_FLOAT32:
{
DataFloat *data = new DataFloat[procs];
SplitImagePixels( data, result, procs, brightness );
cpiMultiProcess( MultiBrightFloat, (void *)data );
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