Search code examples
pngquartz-graphicsnsimagensimagerep

Saving NSImage as PNG with no alpha and 5 bit colour


I have an NSImage that I would like to save as a PNG, but remove the alpha channel and use 5 bit colour. I am currently doing this to create my PNG:

NSData *imageData = [image TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];

NSDictionary *imageProps = nil;
imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps];

[imageData writeToFile:fileNameWithExtension atomically:YES];

I've read though lots of similar questions on SO but am confused as to the best/correct approach to use. Do I create a new CGGraphics context and draw into that? Can I create a new imageRep with these parameters directly? Any help, with a code snippet would be greatly appreciated.

Cheers

Dave


Solution

  • I did this in the end. Looks ugly and smells to me. Any better suggestions greatly appreciated.

    // Create a graphics context (5 bits per colour, no-alpha) to render the tile
    static int const kNumberOfBitsPerColour = 5;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef tileGraphicsContext = CGBitmapContextCreate (NULL, rect.size.width, rect.size.height, kNumberOfBitsPerColour, 2 * rect.size.width, colorSpace, kCGBitmapByteOrder16Little | kCGImageAlphaNoneSkipFirst);
    
    // Draw the clipped part of the image into the tile graphics context
    NSData *imageData = [clippedNSImage TIFFRepresentation];
    CGImageRef imageRef = [[NSBitmapImageRep imageRepWithData:imageData] CGImage];
    CGContextDrawImage(tileGraphicsContext, rect, imageRef);
    
    // Create an NSImage from the tile graphics context
    CGImageRef newImage = CGBitmapContextCreateImage(tileGraphicsContext);
    NSImage *newNSImage = [[NSImage alloc] initWithCGImage:newImage size:rect.size];
    
    // Clean up
    CGImageRelease(newImage);
    CGContextRelease(tileGraphicsContext);
    CGColorSpaceRelease(colorSpace);