October 14, 2009

Reading RGB Info from Images on the iPhone using MonoTouch

MonoTouch is an intriguing new software development kit from Novell. It utilizes the open source Mono project to allow developers to write code in C# that can then be statically compiled into native iPhone applications and deployed to devices or even to the App Store. A free evaluation version is available if the product interests you.

I downloaded the evaluation version and decided to take this new development kit for a spin by using it to read RGB color information from all pixels in an image saved on the device. I ended up creating a CGBitmapContext to do this and then marshaling the results into a byte array. Please see the code below for more details:

//_selectedImage refers to the UIImage object of interest
int width = _selectedImage.CGImage.Width;
int height = _selectedImage.CGImage.Height;
//4 color settings for every pixel (RGBA)
int pixelDataCount = width * height * 4;
IntPtr data = Marshal.AllocHGlobal(pixelDataCount);
int bitsPerComponent = 8;
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * width;
//Draw image to an RGB bitmap context
CGBitmapContext imgContext = new CGBitmapContext(data,
width, height, bitsPerComponent, bytesPerRow,
CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedLast);
imgContext.DrawImage(new RectangleF(0.0F, 0.0F, width, height),
byte[] pixelData = new byte[pixelDataCount];
Marshal.Copy(data, pixelData, 0, pixelDataCount);

//Milk the color settings for each pixel in the image
int red;
int green;
int blue;
int currentPixelIndex = 0;
for (int countHeight = 0; countHeight < height; countHeight++)
for (int countWidth = 0; countWidth < width; countWidth++)
red = pixelData[currentPixelIndex];
green = pixelData[currentPixelIndex];
blue = pixelData[currentPixelIndex];

//Currently ignoring the alpha byte

//Probably will want to Cache RGB values here for later use


Ben Daniel said...

Sweet. How do you find the speed (and on what size image?).

Mark said...

Using the simulator on a 640 x 425 image the code took about 2 - 3 seconds. I'm sure folks could find ways to optimize this.

Hope this helps!