objective-c - 改变 NSImage 的颜色空间

标签 objective-c cocoa macos colors nsimage

有什么方法可以更改 NSimage 或 NSBitmapImageRep/CGimage 等的颜色空间。我对任何方式都持开放态度。最好是 photoshop 的处理方式。

最佳答案

你在下面看到的代码有问题

CGImageRef CGImageCreateCopyWithColorSpace (
CGImageRef image,
CGColorSpaceRef colorspace
);

不起作用,因为 Quartz2D 不支持 CMYK 图像或灰度图像的 alpha,它仅受 RGB 图像支持。 你应该做的是创建 2 个图像,然后在 CMYK 颜色空间和带 alpha 的图像的情况下组合。我搜索了很多关于这个主题的内容,终于找到了。可能是这个问题的作者不再需要它,但其他人可能需要它。

  1. 新建NSBitmapImageRep

    let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil,
                                          pixelsWide: Int(round(imageSize.width)),
                                          pixelsHigh: Int(round(imageSize.height)),
                                       bitsPerSample: 8,
                                     samplesPerPixel: 4,
                                            hasAlpha: false,
                                            isPlanar: false,
                                      colorSpaceName: NSDeviceCMYKColorSpace,
                                        bitmapFormat: NSBitmapFormat(rawValue: 0),
                                         bytesPerRow: Int(round(imageSize.width) * CGFloat(4)),
                                        bitsPerPixel: 0)
    
  2. 您需要将图像绘制到新位图中 假设你有 colorSpace: NSColorSpace

    let context = NSGraphicsContext(bitmapImageRep: imageRep)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.setCurrentContext(context)
    imageRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpace.ICCProfileData)
    // Do your drawing here
    NSGraphicsContext.restoreGraphicsState()
    
  3. 在此之后,您将拥有一个 imageRep,它是具有正确色彩空间但没有 alpha(透明度)的图像。

  4. 你需要一个 mask 位图。获取掩码很棘手。

    let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil,
                                          pixelsWide: Int(round(imageSize.width)),
                                          pixelsHigh: Int(round(imageSize.height)),
                                       bitsPerSample: 8,
                                     samplesPerPixel: 1,
                                            hasAlpha: false,
                                            isPlanar: false,
                                      colorSpaceName: NSDeviceWhiteColorSpace,
                                        bitmapFormat: NSBitmapFormat(rawValue: 0),
                                         bytesPerRow: Int(round(imageSize.width)),
                                        bitsPerPixel: 0)
    
  5. 用透明度将白色图像剪辑到您的图像

    if let graphicsPort = NSGraphicsContext.currentContext()?.graphicsPort {
        let context = unsafeBitCast(graphicsPort, CGContextRef.self)
        let imgRect = NSRect(origin: NSPoint.zero, size: image.extent.size)
        let ciContext = CIContext()
        let cgImage = ciContext.createCGImage(image, fromRect: image.extent)
        CGContextClipToMask(context, imgRect, cgImage)
    }
    
  6. 将所有像素着色为白色,这将被剪裁成图像。

    let context = NSGraphicsContext(bitmapImageRep: imageRep)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.setCurrentContext(context)
    imageRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpace.ICCProfileData)
    NSColor.whiteColor().setFill()
    NSBezierPath.fillRect(NSRect(origin: NSPoint.zero, size: imageSize))
    NSGraphicsContext.restoreGraphicsState()
    
  7. 在这一步中,您有一个图像和一个 mask 。接下来我们需要将它们组合起来。我正在使用这个小算法(您需要验证掩码和源图像具有相同的大小和相同的 colorSpaceModel):

    func createCMYKAImageRepByApplingAlphaMask(srcImageRep: NSBitmapImageRep, alphaMaskImageRep alphaMask: NSBitmapImageRep) -> NSBitmapImageRep? {
        if canApplyMaskRepOnImageRep(srcImageRep, maskRep: alphaMask) == false {
            return nil
        }
        let alphaData = alphaMask.bitmapData
        let srcData = srcImageRep.bitmapData
        if let imageWithAlphaMaskRep = createEmptyCMYKABitmapImageRep(alphaMask.size) {
            if let colorSpaceData = imageColorSpace?.ICCProfileData {
                 imageWithAlphaMaskRep.setProperty(NSImageColorSyncProfileData, withValue: colorSpaceData)
            }
            fillPixelsWithComponentsData(imageWithAlphaMaskRep, components: { (pixelIdx: Int) -> (UInt8, UInt8, UInt8, UInt8, UInt8) in
                let cyan = srcData[pixelIdx * 4 + 0]
                let magenta = srcData[pixelIdx * 4 + 1]
                let yellow = srcData[pixelIdx * 4 + 2]
                let black = srcData[pixelIdx * 4 + 3]
                let alpha = alphaData[pixelIdx]
                return (cyan, magenta, yellow, black, alpha)
            })
            return imageWithAlphaMaskRep
        }
        return nil
    }
    
    func createEmptyBitmapImageRep() -> NSBitmapImageRep? {
        let imageRep = NSBitmapImageRep(bitmapDataPlanes: nil,
                                              pixelsWide: Int(round(imageSize.width)),
                                              pixelsHigh: Int(round(imageSize.height)),
                                           bitsPerSample: 8,
                                         samplesPerPixel: 5,
                                                hasAlpha: true,
                                                isPlanar: false,
                                          colorSpaceName: NSDeviceCMYKColorSpace,
                                            bitmapFormat: NSBitmapFormat(rawValue: 0),
                                             bytesPerRow: Int(round(imageSize.width) * CGFloat(5)),
                                            bitsPerPixel: 0)
        return imageRep
    }
    
    private func fillPixelsWithComponentsData(imgRep: NSBitmapImageRep,
    components: (Int) -> (cyan:UInt8, magenta:UInt8, yellow:UInt8, black:UInt8, alpha:UInt8)) {
        let imageRawData = imgRep.bitmapData
        let imageWidth = Int(imgRep.size.width)
        let imageHeight = Int(imgRep.size.height)
        for pixelIdx in 0 ..< (imageWidth * imageHeight) {
            let (cyan, magenta, yellow, black, alpha) = components(pixelIdx)
            let fAlpha = Float(alpha) / 255
            imageRawData[pixelIdx * 5 + 0] = UInt8(Float(cyan) * fAlpha)
            imageRawData[pixelIdx * 5 + 1] = UInt8(Float(magenta) * fAlpha)
            imageRawData[pixelIdx * 5 + 2] = UInt8(Float(yellow) * fAlpha)
            imageRawData[pixelIdx * 5 + 3] = UInt8(Float(black) * fAlpha)
            imageRawData[pixelIdx * 5 + 4] = alpha
        }
    }
    

关于objective-c - 改变 NSImage 的颜色空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3253521/

相关文章:

iphone - Objective C - 当用户在 UITextField 中键入文本时更新 UILabel

cocoa - 全屏 NSAlert

objective-c - 如何在 IBAction 调用中使用发送者参数

macos - 应用程序加载程序 - 尝试对包进行身份验证时 Apple 服务器上发生错误

macos - 我可以快速进行SSH身份验证闪电吗?

iphone - 在显示 GLkit View 之前添加一些 View - 从 UIview 导航到 GLkit View

ios - 将 Assets 视频发送到网络服务 - iOS

ios - UIImage imageNamed 返回 nil

macos - NSImage TIFFRepresentation 未随 ARC 一起发布

macos - gdb 在 mac os catalina 上调用 `run` 后挂起