Skip to content

Instantly share code, notes, and snippets.

@cookbrianj
Created May 30, 2012 20:47
Show Gist options
  • Save cookbrianj/2838856 to your computer and use it in GitHub Desktop.
Save cookbrianj/2838856 to your computer and use it in GitHub Desktop.
vImage helpers
//
// PixelBufferUtils.h
// IRStudio
//
// Created by Brian Cook on 5/30/12.
// Copyright (c) 2012 All rights reserved.
//
#import <Accelerate/Accelerate.h>
#import "BCNeonImageUtils.h"
#ifndef IRStudio_CVPixelBufferUtils_h
#define IRStudio_CVPixelBufferUtils_h
CGContextRef BCNEONCreateARGBBitmapContext(const size_t width,
const size_t height,
const size_t bytesPerRow) {
CGContextRef bmContext = CGBitmapContextCreate(NULL,
width,
height,
8,
bytesPerRow,
CGColorSpaceCreateDeviceRGB(),
kCGBitmapByteOrderDefault |
kCGImageAlphaPremultipliedFirst);
return bmContext;
}
CGContextRef ARGBBitmapContextFromBCNEONCategory (CGImageRef inImage) {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void * bitmapData;
int bitmapByteCount;
int bitmapBytesPerRow;
size_t pixelsWide = CGImageGetWidth(inImage);
size_t pixelsHigh = CGImageGetHeight(inImage);
bitmapBytesPerRow = (pixelsWide * 4);
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
// Use the generic RGB color space.
colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL) {
fprintf(stderr, "Error allocating color space\n");
return NULL;
}
bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL) {
CGColorSpaceRelease( colorSpace );
return NULL;
}
context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease( colorSpace );
return context;
}
CGImageRef swapRedAndBlueChannels(CGImageRef image) {
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
size_t bytesPerRow = width * 4;
CGContextRef bmContext = BCNEONCreateARGBBitmapContext(width, height, bytesPerRow);
CGContextDrawImage(bmContext, CGRectMake(0.0f, 0.0f, width, height), image);
UInt8* imageData = CGBitmapContextGetData(bmContext);
swapRedAndBlueChannelsARGB(imageData, width, height, bytesPerRow);
CGContextRelease(bmContext);
}
void swapRedAndBlueChannelsARGB(unsigned char *baseAddress, size_t width, size_t height, size_t bytesPerRow) {
const size_t n = sizeof(UInt8) * width * height * 4;
void *outBuffer = malloc(n);
vImage_Buffer src = {baseAddress, height, width, bytesPerRow};
vImage_Buffer dest = {outBuffer, height, width, bytesPerRow};
//ARGB to ABGR
const uint8_t map[4] = {0, 3, 2, 1};
vImagePermuteChannels_ARGB8888(&src, &dest, map, kVimageNoFlags);
}
void CalculateAutocorretionValues(CGImageRef image, CGFloat *whitePoint, CGFloat *blackPoint) {
UInt8* imageData = malloc(200 * 200 * 4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(imageData, 200, 200, 8, 4 * 200, colorSpace, kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(ctx, CGRectMake(0, 0, 200, 200), image);
int histogramm[256];
bzero(histogramm, 256 * sizeof(int));
for (int i = 0; i < 200 * 200 * 4; i += 4) {
UInt8 value = (imageData[i+1] + imageData[i+2] + imageData[i+3]) / 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);
}
void equalizeImageBufferImageARGB(unsigned char *baseAddress, int width, int height, int bytesPerRow) {
const size_t n = sizeof(UInt8) * width * height * 4;
void *outBuffer = malloc(n);
vImage_Buffer src = {baseAddress, height, width, bytesPerRow};
vImage_Buffer dest = {outBuffer, height, width, bytesPerRow};
vImage_Error err = vImageEqualization_ARGB8888(&src, &dest, kvImageCopyInPlace);
if (err == kvImageNoError) {
memcpy(baseAddress, outBuffer, n);
}
free(outBuffer);
}
void equalizeImageBufferBGRAtoRGBAImage(unsigned char *baseAddress, int width, int height, int bytesPerRow) {
neon_BGRA_to_ARGB(baseAddress, width, height);
equalizeImageBufferImageARGB(baseAddress, width, height, bytesPerRow);
}
void stretchImageContrastARGB(unsigned char *baseAddress, int width, int height, int bytesPerRow) {
const size_t n = sizeof(UInt8) * width * height * 4;
void *outBuffer = malloc(n);
vImage_Buffer src = {baseAddress, height, width, bytesPerRow};
vImage_Buffer dest = {outBuffer, height, width, bytesPerRow};
vImage_Error err = vImageContrastStretch_ARGB8888(&src, &dest, kvImageCopyInPlace);
if (err == kvImageNoError) {
memcpy(baseAddress, outBuffer, n);
}
free(outBuffer);
}
void stretchImageBufferBGRAtoRGBAImage(unsigned char *baseAddress, int width, int height, int bytesPerRow) {
neon_BGRA_to_ARGB(baseAddress, width, height);
stretchImageContrastARGB(baseAddress, width, height, bytesPerRow);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment