NSImage to NSBitmapImageRep
@Julius: Your code is way too complicated and contains several bugs. I will make a correction for only the first lines:
- (NSBitmapImageRep *)bitmapImageRepresentation
{
for( NSImageRep *rep in [self representations] )
if( [rep isKindOfClass:[NSBitmapImageRep class]] ) return rep;
return nil;
}
This will extract the first NSBitmapImageRep
if it is member in the representations or will return nil, if there is no NSBitmapImageRep
. I'll give you another solution which will always work whatever NSImageReps
are in the representations: NSBitmapImageRep
, NSPDFImageRep
or NSCGImageSnapshotRep
or ...
- (NSBitmapImageRep *)bitmapImageRepresentation
{
CGImageRef CGImage = [self CGImageForProposedRect:nil context:nil hints:nil];
return [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease];
}
Or to avoid subclassing of NSImage you may write:
NSImage *img = [[[NSImage alloc] initWithContentsOfFile:filename] autorelease];
CGImageRef CGImage = [img CGImageForProposedRect:nil context:nil hints:nil];
NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithCGImage:CGImage] autorelease];
This will only return a single NSBitmapImageRep
which maybe not good enough if the image contains more than one representation (e.g. a lot of NSBitmapImageRep
s from TIFF files). But adding some code is straightforward.
You could try this method adapted from Mike Ash's "Obtaining and Interpreting Image Data" blog post:
- (NSBitmapImageRep *)bitmapImageRepresentation {
int width = [self size].width;
int height = [self size].height;
if(width < 1 || height < 1)
return nil;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: NULL
pixelsWide: width
pixelsHigh: height
bitsPerSample: 8
samplesPerPixel: 4
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSDeviceRGBColorSpace
bytesPerRow: width * 4
bitsPerPixel: 32];
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep: rep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: ctx];
[self drawAtPoint: NSZeroPoint fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1.0];
[ctx flushGraphics];
[NSGraphicsContext restoreGraphicsState];
return [rep autorelease];
}
Maybe late to the party, but this is the Swift 3 version from the @mrwalker response:
extension NSImage {
func bitmapImageRepresentation(colorSpaceName: String) -> NSBitmapImageRep? {
let width = self.size.width
let height = self.size.height
if width < 1 || height < 1 {
return nil
}
if let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(width), pixelsHigh: Int(height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: colorSpaceName, bytesPerRow: Int(width) * 4, bitsPerPixel: 32)
{
let ctx = NSGraphicsContext.init(bitmapImageRep: rep)
NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.setCurrent(ctx)
self.draw(at: NSZeroPoint, from: NSZeroRect, operation: NSCompositingOperation.copy, fraction: 1.0)
ctx?.flushGraphics()
NSGraphicsContext.restoreGraphicsState()
return rep
}
return nil
}
}