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