在 Swift 中,过滤器 CIAreaMinMax 提供不正确的输出
In Swift, filter CIAreaMinMax provide incorrect output
我正在使用滤镜 CIAreaMinMax
从图像中获取最亮和最暗的颜色信息。
正常情况下,过滤器应输出具有两个像素(最亮和最暗)的图像。但是,当我将此过滤器应用于包含两种相似颜色的图像时,结果将不正确。结果不正确的现象是,两个像素的红色通道已经切换了,但是G
和B
的值没有问题。
我使用的测试图片是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.
也就是说最小像素的红色值将包含该区域所有像素中最小的红色值。其他频道也一样。所以红色值最小的像素的实际颜色将不会被保留。
这可以通过一些技巧来完成。
- 首先,拍摄你的图像并应用一个自定义的 CIColorKernel 来放置亮度
在像这样的 Alpha 通道中:
kernel vec4 prepImage (__sample s, vec3 lumaWeights)
{
return vec4(s.rgb, dot(s.rgb, lumaWeights));
}
- 对上图应用 CIAreaMinimumAlpha 滤镜。
- 将生成的 1x1 像素图像渲染到未预乘的 CIRenderDestination。
我正在使用滤镜 CIAreaMinMax
从图像中获取最亮和最暗的颜色信息。
正常情况下,过滤器应输出具有两个像素(最亮和最暗)的图像。但是,当我将此过滤器应用于包含两种相似颜色的图像时,结果将不正确。结果不正确的现象是,两个像素的红色通道已经切换了,但是G
和B
的值没有问题。
我使用的测试图片是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.
也就是说最小像素的红色值将包含该区域所有像素中最小的红色值。其他频道也一样。所以红色值最小的像素的实际颜色将不会被保留。
这可以通过一些技巧来完成。
- 首先,拍摄你的图像并应用一个自定义的 CIColorKernel 来放置亮度 在像这样的 Alpha 通道中:
kernel vec4 prepImage (__sample s, vec3 lumaWeights)
{
return vec4(s.rgb, dot(s.rgb, lumaWeights));
}
- 对上图应用 CIAreaMinimumAlpha 滤镜。
- 将生成的 1x1 像素图像渲染到未预乘的 CIRenderDestination。