Argilium
Argilium

Reputation: 512

Extracting RGB data from bitmapData (NSBitmapImageRep) Cocoa

I am working on an application which needs to compare two images, in order to see how different they are and the application does this repeatedly for different images. So the way I currently do this is by having both the images as NSBitmapImageRep, then using the colorAtX: y: function in order to get a NSColor object, and then examining the RGB components. But this approach is extremely slow. So researching around the internet I found posts saying that a better way would be to get the bitmap data, using the function bitmapData, which returns an unsigned char. Unfortunately for me I don't know how to progress further from here, and none of the posts I've found show you how to actually get the RGB components for each pixel from this bitmapData. So currently I have :

 NSBitmapImageRep* imageRep = [self screenShot]; //Takes a screenshot of the content displayed in the nswindow
unsigned char *data = [imageRep bitmapData]; //Get the bitmap data

//What do I do here in order to get the RGB components?

Thanks

Upvotes: 2

Views: 2331

Answers (1)

user1118321
user1118321

Reputation: 26375

The pointer you get back from -bitmapData points to the RGB pixel data. You have to query the image rep to see what format it's in. You can use the -bitmapFormat method which will tell you whether the data is alpha first or last (RGBA or ARGB), and whether the pixels are ints or floats. You need to check how many samples per pixel, etc. Here are the docs. If you have more specific questions about the data format, post those questions and we can try to help answer them.

Usually the data will be non-planar, which means it's just interleaved RGBA (or ARGB) data. You can loop over it like this (assuming 8-bit per channel, 4 channels of data) :

int width = [imageRep pixelsWide];
int height = [imageRep pixelsHight];
int rowBytes = [imageRep bytesPerRow];
char* pixels = [imageRep bitmapData];
int row, col;
for (row = 0; row < height; row++)
{
    unsigned char* rowStart = (unsigned char*)(pixels + (row * rowBytes));
    unsigned char* nextChannel = rowStart;
    for (col = 0; col < width; col++)
    {
        unsigned char red, green, blue, alpha;

        red = *nextChannel;
        nextChannel++;
        green = *nextChannel;
        nextChannel++;
        // ...etc...
    }
}

Upvotes: 6

Related Questions