Last active
August 27, 2015 12:35
-
-
Save Tricertops/9f145fb3e92920211d8a to your computer and use it in GitHub Desktop.
Converting colors on OS X between RGB color spaces without clamping their values. Will not work on iOS, because kCGBitmapFloatComponents is not supported.
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
// © 2015 PixelCut, provided under MIT license. | |
//! Inputs | |
CGColorSpace sourceSpace; // Display RGB, Generic RGB, sRGB, any RGB | |
CGFloat sourceRed; // Can be out of 0..1 range. | |
CGFloat sourceGreen; // Can be out of 0..1 range. | |
CGFloat sourceBlue; // Can be out of 0..1 range. | |
CGColorSpaceRef targetSpace; // Display RGB, Generic RGB, sRGB, any RGB | |
//! Setup all required values | |
NSUInteger const componentsPerPixel = CGColorSpaceGetNumberOfComponents(targetSpace) + 1; // alpha | |
NSUInteger const bytesPerComponent = sizeof(float); | |
NSUInteger const bitsPerComponent = bytesPerComponent * CHAR_BIT; | |
NSUInteger const bitsPerPixel = bitsPerComponent * componentsPerPixel; | |
NSUInteger const dimension = 1; | |
NSUInteger const bytesPerRow = bytesPerComponent * componentsPerPixel * dimension; | |
CGFloat const* decode = nil; | |
BOOL const shouldInterpolate = NO; | |
CGBitmapInfo const options = (kCGBitmapFloatComponents | kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast); | |
//! Populate source bitmap. | |
NSMutableData* sourceBitmap = [NSMutableData dataWithLength: bytesPerRow]; | |
float* sourceComponents = sourceBitmap.mutableBytes; | |
sourceComponents[0] = sourceRed; | |
sourceComponents[1] = sourceGreen; | |
sourceComponents[2] = sourceBlue; | |
sourceComponents[3] = 1; | |
//! Create source image. | |
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)sourceBitmap); | |
CGImageRef sourceImage = CGImageCreate(dimension, dimension, | |
bitsPerComponent, bitsPerPixel, bytesPerRow, | |
sourceSpace, options, | |
provider, | |
decode, shouldInterpolate, kCGRenderingIntentDefault); | |
CFRelease(sourceSpace); | |
CFRelease(provider); | |
//! Create target context. | |
NSMutableData* bitmap = [NSMutableData dataWithLength: bytesPerRow]; | |
CGContextRef context = CGBitmapContextCreate(bitmap.mutableBytes, | |
dimension, dimension, | |
bitsPerComponent, bytesPerRow, | |
targetSpace, | |
options); | |
//! Convert the single sample | |
CGContextDrawImage(context, CGRectMake(0, 0, dimension, dimension), sourceImage); | |
CFRelease(sourceImage); | |
CFRelease(context); | |
CFRelease(targetSpace); | |
//! Grab the converted components. | |
const float* targetComponents = bitmap.bytes; | |
CGFloat targetRed = targetComponents[0]; // Can be out of 0..1 range. | |
CGFloat targetGreen = targetComponents[1]; // Can be out of 0..1 range. | |
CGFloat targetBlue = targetComponents[2]; // Can be out of 0..1 range. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment