void releasePixels(void *info, const void *data, size_t size) {
free((void*)data);
}
-(UIImage *)boxblurImage:(UIImage *)image boxSize:(int)boxSize {
CGImageRef img = image.CGImage;
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
void *pixelBuffer;
//create vImage_Buffer with data from CGImageRef
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);
inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
//create vImage_Buffer for output
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
if(pixelBuffer == NULL)
NSLog(@"No pixelbuffer");
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(img);
outBuffer.height = CGImageGetHeight(img);
outBuffer.rowBytes = CGImageGetBytesPerRow(img);
//perform convolution
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
//create CGImageRef from vImage_Buffer output
//1 - CGBitmapContextCreateImage -
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
outBuffer.rowBytes,
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
//2 CGImageCreate - alternative - has a leak
/*
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, outBuffer.data, outBuffer.height * outBuffer.rowBytes, releasePixels);
CGImageRef imageRef = CGImageCreate(outBuffer.width, outBuffer.height, 8, 32, outBuffer.rowBytes, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, provider, NULL, NO, kCGRenderingIntentPerceptual);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
*/
//clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
//-CGColorSpaceRelease(colorSpace);
CGImageRelease(imageRef);
return returnImage;
}
//this method is eactly like the one above, except is performs the blur 30 times for benchmark testing
-(CGImageRef)thirtyBoxblurImage:(CGImageRef)img boxSize:(int)boxSize {
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
void *pixelBuffer;
//create vImage_Buffer with data from CGImageRef
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);
inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
//create vImage_Buffer for output
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
if(pixelBuffer == NULL)
NSLog(@"No pixelbuffer");
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(img);
outBuffer.height = CGImageGetHeight(img);
outBuffer.rowBytes = CGImageGetBytesPerRow(img);
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
//perform convolution
for (int i = 0; i < 30; i++) {
if (i % 2 == 0) {
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
} else {
error = vImageBoxConvolve_ARGB8888(&outBuffer, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
}
}
NSLog(@"finished in %f seconds, %ld pixels, %f seconds per 1,000 pixels", CFAbsoluteTimeGetCurrent() - start, outBuffer.width * outBuffer.height, (CFAbsoluteTimeGetCurrent() - start)/ ((float)(outBuffer.width * outBuffer.height) / 1000.0) / 30.0);
//create CGImageRef from vImage_Buffer output
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
outBuffer.rowBytes,
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
return imageRef;
}
-(CGImageRef)matchHistogramInImage:(CGImageRef)inImg withImage:(CGImageRef)matchImg {
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
vImage_Buffer buffer,
inBuffer,
outBuffer;
vImage_Error error;
void* pixelBuffer;
vImagePixelCount histogramA[256];
vImagePixelCount histogramR[256];
vImagePixelCount histogramG[256];
vImagePixelCount histogramB[256];
vImagePixelCount* histograms[4];
CGDataProviderRef inProvider = CGImageGetDataProvider(inImg);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
buffer.width = CGImageGetWidth(inImg);
buffer.height = CGImageGetHeight(inImg);
buffer.rowBytes = CGImageGetBytesPerRow(inImg);
buffer.data = (void*)CFDataGetBytePtr(inBitmapData);
histograms[0] = histogramA;
histograms[1] = histogramR;
histograms[2] = histogramG;
histograms[3] = histogramB;
error = vImageHistogramCalculation_ARGB8888(&buffer, histograms, 0);
NSLog(@"error from historgram calc, %ld", error);
CGDataProviderRef outProvider = CGImageGetDataProvider(matchImg);
CFDataRef outBitmapData = CGDataProviderCopyData(outProvider);
inBuffer.width = CGImageGetWidth(matchImg);
inBuffer.height = CGImageGetHeight(matchImg);
inBuffer.rowBytes = CGImageGetBytesPerRow(matchImg);
inBuffer.data = (void*)CFDataGetBytePtr(outBitmapData);
pixelBuffer = malloc(CGImageGetBytesPerRow(matchImg) * CGImageGetHeight(matchImg));
if(pixelBuffer == NULL)
NSLog(@"No pixelbuffer");
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(matchImg);
outBuffer.height = CGImageGetHeight(matchImg);
outBuffer.rowBytes = CGImageGetBytesPerRow(matchImg);
error = vImageHistogramSpecification_ARGB8888(&inBuffer, &outBuffer, (const vImagePixelCount**)histograms, 0);
NSLog(@"error from specification %ld", error);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
outBuffer.rowBytes,
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
NSLog(@"finished in %f seconds", CFAbsoluteTimeGetCurrent() - start);
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
return imageRef;
}
- (void)brightness {
}