How to write a simple image processing plugin?

Hi,

I’ve written some Xojo image processing code and would like to port certain methods to a plug in order to speed things up. I have written very simple plugins with methods that take and return standard variable types before, but when it comes to passing a picture into a plugin and manipulating it, I haven’t the foggiest as to where to begin.

Does someone have some example code I could learn from? I need to implement a few methods that take an original picture as argument, perform manipulations on the original at a pixel level (my Xojo code uses RGBSurface to do this) and return the processed picture. If it’s easier to do so, the method could also accept an RGBsurface as an argument instead of a picture, and return a new RGBSurface with the processed pixels.

Thanks in advance!

You would need to start with REALLockPictureDescription, and then poke around in its fields to see what type of image you get. And then cast its raw data handle to whatever handle it should be depending on the operating system and what the Lock picture description said.

You will get different type for each platform and sometimes more than one type per platform, and Console is like one extra platform, there you got a strange beast which is completely different, there suddenly you will get pointers of rows instead of one continuous data field, and on console the alpha filed will be 7 bit instead of 8.

Or in other words, it’s a lot of work, you implement 11 variants (counted in my plugins) for different image formats.
A lot of work, but maybe you don’t need to support some older targets like Carbon and remove a few.

Thanks your responses. Yes, that sounds like a lot of work :frowning:
Lazy as I am, I was looking for an easy way out, and it appears I may have found one. Xojo has a handy function (Picture.GetData) that lets you get raw image data for certain image formats such as BMP (which is uncompressed and whose data can be parsed relatively easily) in form of a MemoryBlock. This way, the plugin only has to deal with one image format. I’m ok with Xojo code making the conversion of a Picture to a BMP memory block because I’m really after getting the heavy lifting, such as pixel manipulation, done by the plugin. I wrote a small Xojo test project and test plugin code, and it works very well. My example simply inverts the color of each pixel by iterating through each pixel in the image, and the plugin performs this operation much faster than equivalent Xojo code (using RGBSurface).

The Xojo code to call the plugin method looks like this:

// convert picture to MemoryBlock dim m as MemoryBlock = p.GetData(Picture.FormatBMP, 100) // Invert dim m_dest as new MemoryBlock(m.Size) MyPlugin.Invert(m, m_dest) // convert MemoryBlock to Picture dim dest as Picture = picture.FromData(m_dest)
And the Plugin code looks like this:

[code]void Invert(REALmemoryBlock In, REALmemoryBlock Out)
{
BYTE *mIn, *mOut;
mIn = (BYTE *) REALMemoryBlockGetPtr(In);
mOut = (BYTE *) REALMemoryBlockGetPtr(Out);

// get the size of the BMP in bytes
int picsize;
picsize = *(signed long int *)&mIn[2]; // 4 bytes @ offset 0x02

// get width and height
signed long int w, h;
w = *(signed long int *)&mIn[18]; // 4 bytes @ offset 0x12
h = *(signed long int *)&mIn[22]; // 4 bytes @ offset 0x16
if (h < 0){
    h = abs(h); // if the height is a negative number, then the rows are from top to bottom
}

// get no of bits per pixel
int bits;
bits = mIn[28]; // 1 byte @ offset 0x1c
int bytes;
bytes = bits / 8;

// get the starting address of the pixel array
int offset;
offset = *(signed long int *)&mIn[10]; // 4 bytes @ offset 0x0a

// copy header
unsigned long int i;
for (i = 0; i < offset; i++) {
    mOut[i] = mIn[i];
}

// process
unsigned long int x, y; // coordinates, 0/0 is the bottom left corner (or top left if the height is negative)
for (y = 0; y < h; y++){
    for (x = 0; x < w; x++){
        //i = 54 + 4*(x + w*y); // pixel number
        i = offset + bytes*(x + w*y); // pixel number
        mOut[i] = 255-mIn[i]; // blue
        mOut[i+1] = 255-mIn[i+1]; // green
        mOut[i+2] = 255-mIn[i+2]; // red
        if (bytes == 3)
            mOut[i+3] = mIn[i+3]; // alpha
    }
}   

}[/code]

This works very well at least for my use case and I have tested this on Mac and Windows. I expect this to work on Linux also (although I’m not currently targeting Linux with this). I hope that someone might find this useful as well.

you just invert?

For that the normal Transform function on RGBSurface should do it quickly.

Yes, you’re correct. The transform function can be used to invert an image very quickly. I merely chose inverting as a proof of concept as it is a mathematically very simple function. Also, the code is short enough for a post to the forums :-).
Still, for such a simple example, the C++ code performs this very quickly compared to the equivalent Xojo code (not using the Transform function but rather using two nested loops to iterate through all the pixels of an RGBSurface). I’m seeing an almost 5x improvement for this particular example. Another almost as simple example I tested (a simple masking method) yielded an over 6x improvement.
I have some manipulations I need to implement which I have written in Xojo code before that are algorithmically more involved, and I expect the speed boost to be even more dramatic in these cases based on some signal processing functions I have ported to a Plugin a few years ago (such as an FFT function that runs almost 100x faster than the Xojo implementation).