Marek H
Marek H

Reputation: 5576

NSImage resizing 10bit image using CGContext

I have 10 bit image file (HEIC, AVIF) loaded using NSImage. When attempting to resize using CGContext I get following message multiple times

This method should not be called on the main thread as it may lead to UI unresponsiveness.

I do not get this message when I use NSBitmapImageRep as a current context. I cannot use NSBitmapImageRep because it doesn't preserve colorspace (e.g. cannot do wide gamut).

What special configuration NSBitmapImageRep has that it doesn't emit this error? Is there a way to resize using NSBitmapImageRep while preserving colorspace?

Sample AVIF file: https://gregbenzphotography.com/assets/hdr/gallery/wide/Prana-hdr.avif

var bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue

//10-bit or 12-bit need to be drawn using 16 bpc context e.g. converted
var bitsPerComponent = cgImage.bitsPerComponent
if cgImage.bitsPerComponent > 8 && cgImage.bitsPerComponent <= 16 {
    bitsPerComponent = 16
}
var cgContext = CGContext(data: nil,
                          width: Int(newSize.width),
                          height: Int(newSize.height),
                          bitsPerComponent: bitsPerComponent,
                          bytesPerRow: 0,
                          space: cgImage.colorSpace ?? CGColorSpace(name: CGColorSpace.sRGB)!,
                          bitmapInfo: bitmapInfo)
if cgContext == nil {
    // context cannot be created with provided values. Continue with 8bps 32bpp RGBA context
    cgContext = CGContext(data: nil,
                          width: Int(newSize.width),
                          height: Int(newSize.height),
                          bitsPerComponent: 8,
                          bytesPerRow: 0,
                          space: CGColorSpace(name: CGColorSpace.sRGB)!,
                          bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)
}

guard cgContext != nil else { return self }
cgContext!.interpolationQuality = .high
cgContext!.draw(cgImage, in: CGRect(origin: .zero, size: newSize), byTiling: false)
guard let resizedCGImage = cgContext!.makeImage() else { return self }
let resizedImage = NSImage(cgImage: resizedCGImage, 
                           size: NSMakeSize(Double(resizedCGImage.width), Double(resizedCGImage.height)))

I get the same warning even if I try:

NSGraphicsContext.saveGraphicsState()
NSGraphicsContext.current = NSGraphicsContext(cgContext: cgContext!, flipped: false)
draw(in: NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height), from: .zero, operation: .copy, fraction: 1.0)
NSGraphicsContext.restoreGraphicsState()

Upvotes: 1

Views: 80

Answers (0)

Related Questions