Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIImage - implementing an auto levels algorithm

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 image processing methods in the APIs I should be using, for histograms, etc. Or should I just grab the underlying CGImage and process it? (I am new to iPhone dev.)

Thanks

MV

like image 539
M-V Avatar asked Jul 19 '10 05:07

M-V


3 Answers

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);
}
like image 197
tonklon Avatar answered Nov 04 '22 21:11

tonklon


I don't think there are existing APIs that do image processing, but I'm sure there are third-party libraries out there.

like image 22
tc. Avatar answered Nov 04 '22 21:11

tc.


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.

like image 25
Καrτhικ Avatar answered Nov 04 '22 23:11

Καrτhικ