【问题标题】:setColor on NSBitmapImageRep not working in SwiftNSBitmapImageRep 上的 setColor 在 Swift 中不起作用
【发布时间】:2021-12-18 01:12:42
【问题描述】:

我试图弄清楚 setColor 是如何工作的。我有以下代码:

    
    
    lazy var imageView:NSImageView = {
        let imageView = NSImageView(frame: view.frame)
        return imageView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        createColorProjection()
        view.wantsLayer = true
        view.addSubview(imageView)
        
        view.needsDisplay = true
    }
    
    func createColorProjection() {
        var bitmap = NSBitmapImageRep(cgImage: cgImage!)
        var x = 0
        while x < bitmap.pixelsWide {
            var y = 0
            while y < bitmap.pixelsHigh {
                //pixels[Point(x: x, y: y)] = (getColor(x: x, y: y, bitmap: bitmap))
                bitmap.setColor(NSColor(cgColor: .black)!, atX: x, y: y)
                y += 1
            }
            x += 1
        }
        
        let image = createImage(bitmap: bitmap)
        imageView.image = image
        imageView.needsDisplay = true
    }
    
    
    func createImage(bitmap:NSBitmapImageRep) -> NSImage {
        let image = bitmap.cgImage
        return NSImage(cgImage: image! , size: CGSize(width: image!.width, height: image!.height))
    }

代码的目的是将照片(彩虹)更改为全黑(我现在只是用黑色进行测试,以确保我了解它的工作原理)。但是,当我运行程序时,显示的是彩虹的未更改图片,而不是黑色照片。

我收到以下错误: Unrecognized colorspace number -1Unknown number of components for colorspace model -1

谢谢。

【问题讨论】:

  • 看起来这一直是一个 XY 问题。更改读取、修改和写回单个像素值可能不是实现您想要实现的目标的方法。这将使用大量的 CPU 和内存,因为位图图像变得非常大非常快。您可能应该使用 CIFilter API 到 make your own filter 来执行此操作。

标签: swift macos nsimage cgimage nsbitmapimagerep


【解决方案1】:

首先,你是对的:setColor 至少从 Catalina 开始就被破坏了。 Apple 没有修复它可能是因为它太慢且效率低下,而且没有人使用它。

其次,文档说NSBitmapImageRep(cgImage: CGImage) 会生成一个只读位图,因此即使setColor 有效,您的代码也不会有效。

正如 Alexander 所说,制作自己的 CIFilter 是将照片的像素更改为不同颜色的最佳方式。编写和实现 OpenGL 并不容易,但它是最好的。

如果您要像这样向NSBitmapImageRep 添加扩展名:

extension NSBitmapImageRep {
    func setColorNew(_ color: NSColor, atX x: Int, y: Int) {
        guard let data = bitmapData else { return }
        
        let ptr = data + bytesPerRow * y + samplesPerPixel * x
        
        ptr[0] = UInt8(color.redComponent * 255.1)
        ptr[1] = UInt8(color.greenComponent * 255.1)
        ptr[2] = UInt8(color.blueComponent * 255.1)
        
        if samplesPerPixel > 3 {
            ptr[3] = UInt8(color.alphaComponent * 255.1)
        }
    }
}

然后可以像这样简单地更改图像的像素:

func changePixels(image: NSImage, newColor: NSColor) -> NSImage {
    guard let imgData = image.tiffRepresentation,
          let bitmap = NSBitmapImageRep(data: imgData),
          let color = newColor.usingColorSpace(.deviceRGB)
    else { return image }
    
    var y = 0
    while y < bitmap.pixelsHigh {
        var x = 0
        while x < bitmap.pixelsWide {
            bitmap.setColorNew(color, atX: x, y: y)
            x += 1
        }
        y += 1
    }
    
    let newImage = NSImage(size: image.size)
    newImage.addRepresentation(bitmap)
    
    return newImage
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-16
    • 2016-07-02
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多