-
-
Save hyuni/89b3d008663e30ee3b0f to your computer and use it in GitHub Desktop.
vImage helpers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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