Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create 8-, 4-, and 1-bit representations of NSImage

I had created 32 bit NSImage with following code.

 NSBitmapImageRep *sourceRep = [[NSBitmapImageRep alloc] initWithData: imageData];

        // create a new bitmap representation scaled down

            NSBitmapImageRep *newRep = 
                [[NSBitmapImageRep alloc] 
                    initWithBitmapDataPlanes: NULL
                    pixelsWide: imageSize
                    pixelsHigh: imageSize
                    bitsPerSample: 8
                    samplesPerPixel: 4
                    hasAlpha: YES
                    isPlanar: NO
                    colorSpaceName: NSCalibratedRGBColorSpace
                    bytesPerRow: 0
                    bitsPerPixel: 0];

            // save the graphics context, create a bitmap context and set it as current
            [NSGraphicsContext saveGraphicsState] ;
            NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: newRep];
            [NSGraphicsContext setCurrentContext: context] ;

            // draw the bitmap image representation in it and restore the context
            [sourceRep drawInRect: NSMakeRect(0.0f, 0.0f, imageSize, imageSize)] ;
            [NSGraphicsContext restoreGraphicsState] ;

            // set the size of the new bitmap representation
            [newRep setSize: NSMakeSize(imageSize,imageSize)] ;

            NSDictionary *imageProps2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                         [NSNumber numberWithFloat:1.0], kCGImageDestinationLossyCompressionQuality,
                                         nil];
            imageData = [newRep representationUsingType: NSPNGFileType properties: imageProps2];
  NSImage *bitImage  = [[NSImage alloc]initWithData:imageData];

Now I need to create 8 bit(256 Colors),4 bit(16 Colors),1 bit(Black & White) NSBitmapImageRep representation. what I want to do now?

like image 682
NewStack Avatar asked Aug 02 '13 11:08

NewStack


2 Answers

Unfortunately it seems that Cocoa doesn't support operating on paletted images.

I've been trying that before and my conclusion is that it's not possible for PNG. NSGIFFileType is a hardcoded exception, and Graphics Contexts are even more limited than bitmap representations (e.g. RGBA is supported only with premultiplied alpha).

To work around it I convert NSBitmapImageRep to raw RGBA bitmap, use libimagequant to remap it to a palette and then libpng or lodepng to write the PNG file.

like image 130
Kornel Avatar answered Sep 30 '22 17:09

Kornel


Sadly, I believe you can't using core graphics. Graphics contexts don't support anything with that few bits.

The documentation has a table of supported pixel formats.

Apparently Carbon had (has?) support for it, as seen referenced here where they also lament Cocoa's lack of support for it:

Turns out that basically Cocoa/Quartz does not support downsampling images to 8-bit colour. It supports drawing them, and it supports upsampling, but not going the other way. I guess this is a deliberate design on Apple's part to move away from indexed images as a standard graphics data type - after all, 32-bit colour is much simpler, right? Well, it is, but there are still useful uses for 8-bit. So..... what to do? One possibility is using Carbon, since General/QuickDraw's General/GWorld does support downsampling, etc.

From this thread

like image 30
cobbal Avatar answered Sep 30 '22 17:09

cobbal