I'm trying to write an RBGA pixel array to file using code found here [stackoverflow.com], but it fails.
I store my pixel information in a 1-dimensional array of 32-bit integers, so the first bit of this method (hopefully) takes the relevant bits from the 32-bit integer, storing them into an array of chars.
When run, the method below a) prints that we didn't create the image (CGBitmapContextCreateImage(bitmapContext)
returned NULL) and b) dies when trying to release the image (RayTracerProject[33126] <Error>: CGBitmapContextCreateImage: invalid context 0x0
ImageIO: <ERROR> CGImageDestinationAddImage image parameter is nil
), which makes sense because cgImage
is null.
The method:
-(void) write{
char* rgba = (char*)malloc(width*height);
for(int i=0; i < width*height; ++i) {
rgba[4*i] = (char)[Image red:pixels[i]];
rgba[4*i+1] = (char)[Image green:pixels[i]];
rgba[4*i+2] = (char)[Image blue:pixels[i]];
rgba[4*i+3] = (char)[Image alpha:pixels[i]];
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate(
rgba,
width,
height,
8, // bitsPerComponent
width, // bytesPerRow
colorSpace,
kCGImageAlphaNoneSkipLast);
CFRelease(colorSpace);
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
if ( cgImage == NULL )
printf("Couldn't create cgImage correctly").
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("image.png"), kCFURLPOSIXPathStyle, false);
CFStringRef type = kUTTypePNG; // or kUTTypeBMP if you like
CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url, type, 1, 0);
CGImageDestinationAddImage(dest, cgImage, 0);
CFRelease(cgImage);
CFRelease(bitmapContext);
CGImageDestinationFinalize(dest);
free(rgba);
};
For completeness, my bit shifting methods:
// Extract the 8-bit red component from a 32bit color integer.
+(int) red:(int) color{
return (color >> 16) & 0xff;
};
// Extract the 8-bit green component from a 32bit color integer.
+(int) green:(int) color{
return (color >> 8) & 0xff;
};
// Extract the 8-bit blue component from a 32bit color integer.
+(int) blue:(int) color{
return (color & 0xff);
};
// Extract the 8-bit alpha component from a 32bit color integer.
+(int) alpha:(int) color{
return (color >> 24) & 0xff;
};
According to the docs found here [developer.apple.com], CGBitmapContextCreateImage
will return A new bitmap context, or NULL if a context could not be created
, but won't help me understand why a context couldn't be created.
What am I doing wrong? [Also, if there is a much smarter way to write a pixel array to file in Objective-C, I'm not tied to this particular way of doing things - this project is a port from a Java one I did a few years ago - I used a FileOutputStream, but can't find an equivalent in Objective-C].