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);
}