I\'d like to implement an \"auto levels\" option for a UIImage that I am displaying in my iPhone app. Before I try to implement it myself, I was wondering if there are any i
I don't think there are existing APIs that do image processing, but I'm sure there are third-party libraries out there.
One very easy approach is to use the decode array of a CGImageRef, but this is can only help for an range mapping (no gamma, etc.)
const CGFloat decode[6] = {blackPoint,whitePoint,blackPoint,whitePoint,blackPoint,whitePoint};
decodedImage = CGImageCreate(CGImageGetWidth(origImage),
CGImageGetHeight(origImage),
CGImageGetBitsPerComponent(origImage),
CGImageGetBitsPerPixel(origImage),
CGImageGetBytesPerRow(origImage),
CGImageGetColorSpace(origImage),
CGImageGetBitmapInfo(origImage),
CGImageGetDataProvider(origImage),
decode,
YES,
CGImageGetRenderingIntent(origImage)
);
Where whitePoint is a float between 0.0 and 1.0, that determines which brightness will to mapped to pure white in the output, and blackPoint is also a float, that determines which brightness is mapped to pure black.
The decode array's elements correspond to the components of the colorspace, so this code will only work for RBG images. You can set the components to different white and black values to create a simple color-correction.
You can calculate the whitePoint and the blackPoint with the following function (w/o color correction):
void CalculateAutocorretionValues(CGImageRef image, CGFloat *whitePoint, CGFloat *blackPoint) {
UInt8* imageData = malloc(100 * 100 * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(imageData, 100, 100, 8, 4 * 100, colorSpace, kCGImageAlphaNoneSkipLast);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(ctx, CGRectMake(0, 0, 100, 100), image);
int histogramm[256];
bzero(histogramm, 256 * sizeof(int));
for (int i = 0; i < 100 * 100 * 4; i += 4) {
UInt8 value = (imageData[i] + imageData[i+1] + imageData[i+2]) / 3;
histogramm[value]++;
}
CGContextRelease(ctx);
free(imageData);
int black = 0;
int counter = 0;
// count up to 200 (2%) values from the black side of the histogramm to find the black point
while ((counter < 200) && (black < 256)) {
counter += histogramm[black];
black ++;
}
int white = 255;
counter = 0;
// count up to 200 (2%) values from the white side of the histogramm to find the white point
while ((counter < 200) && (white > 0)) {
counter += histogramm[white];
white --;
}
*blackPoint = 0.0 - (black / 256.0);
*whitePoint = 1.0 + ((255-white) / 256.0);
}
This explains auto-levels (i.e., histogram equalization) really well:
http://www.generation5.org/content/2004/histogramEqualization.asp
They also have Java implementation of the same.
You could try the CImg library... They have histogram and equalize functions on the docs. The equalize() function has pretty decent results, from the sample image. The license is LGPL, which may not be suitable for your project but is compatible with selling on the app store.