在 Swift 中,过滤器 CIAreaMinMax 提供不正确的输出

In Swift, filter CIAreaMinMax provide incorrect output

我正在使用滤镜 CIAreaMinMax 从图像中获取最亮和最暗的颜色信息。

正常情况下,过滤器应输出具有两个像素(最亮和最暗)的图像。但是,当我将此过滤器应用于包含两种相似颜色的图像时,结果将不正确。结果不正确的现象是,两个像素的红色通道已经切换了,但是GB的值没有问题。

我使用的测试图片是here,一个png图片只有两种颜色:

RGB(37,62,88), GRB(10,132,255).

经过代码处理后,会输出一个包含两个像素的png图片:

RGB(10,62,88), GRB(37,132,255).

下面是 swift playground 的测试代码:

import Cocoa
import CoreImage
import CoreGraphics

func saveImage(_ image: NSImage, atUrl url: URL) {
  let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)!
  let newRep = NSBitmapImageRep(cgImage: cgImage)
  newRep.size = image.size
  let pngData = newRep.representation(using: .png, properties: [:])!
  try! pngData.write(to: url)
}

var sourceImage = CIImage.init(contentsOf: URL.init(fileURLWithPath: "/Users/ABC/Downloads/test.png"))!

let filter = CIFilter(name: "CIAreaMinMax")!
filter.setValue(sourceImage, forKey: kCIInputImageKey)
let civ = CIVector.init(x: sourceImage.extent.minX, y: sourceImage.extent.minY, z: sourceImage.extent.width, w: sourceImage.extent.height)
filter.setValue(civ, forKey: kCIInputExtentKey)

var filteredImage = filter.outputImage!
let context = CIContext(options: [.workingColorSpace: kCFNull!])

let filteredCGImageRef = context.createCGImage(
filteredImage,
from: filteredImage.extent)
let output = NSImage(cgImage: filteredCGImageRef!, size: NSSize.init(width: filteredImage.extent.width, height: filteredImage.extent.height))
saveImage(output, atUrl: URL.init(fileURLWithPath: "/Users/ABC/Downloads/output.png"))

来自文档(强调我的):

Calculates the per-component minimum and maximum value for the specified area in an image.

也就是说最小像素的红色值将包含该区域所有像素中最小的红色值。其他频道也一样。所以红色值最小的像素的实际颜色将不会被保留。

这可以通过一些技巧来完成。

  1. 首先,拍摄你的图像并应用一个自定义的 CIColorKernel 来放置亮度 在像这样的 Alpha 通道中:
kernel vec4 prepImage (__sample s, vec3 lumaWeights)
{
    return vec4(s.rgb, dot(s.rgb, lumaWeights));
}
  1. 对上图应用 CIAreaMinimumAlpha 滤镜。
  2. 将生成的 1x1 像素图像渲染到未预乘的 CIRenderDestination。