我正在尝试生成HEIF 输出文件,但这样做时会得到奇怪的对角线。其他输出格式都没有出现这些奇怪的线条。见下图。问题似乎正在裁剪,但错误仅显示在 HEIF 输出文件中。
我可以使用以下操场代码复制此代码,您可以从此处下载https://duncangroenewald.com/files/SampleApps/CoreImageHEIFExporterBug-2.zip
我有一份苹果的错误报告,他们提到了“亚像素错误”——我不知道那是什么,也不知道为什么这些只会在 heif 输出格式中体现出来,或者如何防止它们——任何想法或这似乎只是一个苹果代码中的错误?
编辑。需要明确的是,这不是操场问题,因为问题发生在 macOS 应用程序中。
我怀疑这CIContext
在生成 HEIF 输出时一定是一个错误,因为它只显示在 heif 输出文件中。但是,我对亚像素错误或 Apple 认为它们应该与此问题相关的原因一无所知。也许拥有更多核心图像知识的人可能会提出一些可能的解决方案。
import Cocoa
let files = ["/Users/duncangroenewald/Development/Playgrounds/CoreImageHEIFExporterBug/DSC02022.ARW",
"/Users/duncangroenewald/Development/Playgrounds/CoreImageHEIFExporterBug/DSC02018.ARW"
]
let destFilePath = "/Users/duncangroenewald/Development/Playgrounds/CoreImageHEIFExporterBug"
let destUrl = URL(fileURLWithPath: destFilePath)
let exporter = Exporter()
var crops = [CGRect(x: 0, y: 0, width: 5310, height: 3212),
CGRect(x: 0, y: 0, width: 5311, height: 3212),
CGRect(x: 0, y: 0, width: 5312, height: 3212),
CGRect(x: 0, y: 0, width: 5313, height: 3212)]
for file in files {
exporter.processRAWFile(file, destPath: destFilePath, crops: crops)
}
print("Done!")
import AppKit
import CoreImage
import CoreImage.CIFilterBuiltins
import OSLog
public class Exporter {
var formats: [String] = ["heif", "png"]
// Get the CIContext
let ciContext = CIContext()
var imageOrientation: Int = 0
var imageNativeSize: CGSize = .zero
var crops: [CGRect] = [.zero]
public init() {
}
public func processRAWFile(_ path: String, destPath: String, crops: [CGRect]) {
print("processRAWFile XXX")
self.crops = crops
let url = URL(fileURLWithPath: path)
let filename = url.deletingPathExtension().lastPathComponent
let destDirUrl = URL(fileURLWithPath: destPath)
print("destDirUrl: \(destDirUrl)")
for crop in crops {
let cropName = "\(filename)_\(crop.width)x\(crop.height)_\(useDefaultRAW ? "default" : "")"
for format in formats {
let destUrl = destDirUrl.appendingPathComponent(cropName).appendingPathExtension(format)
print("destFile: \(destUrl)")
self.exportFile(url: url, destUrl: destUrl, crop: crop, format: format)
}
}
}
func exportFile(url: URL, destUrl: URL, crop: CGRect, format: String){
print("exportFile \(url)")
print("destFile: \(destUrl)")
guard let rawFilter = CIFilter(imageURL: url, options: nil), let outputImage = rawFilter.outputImage else {
print("Failed to load \(url.lastPathComponent) for exporting")
return
}
let processImage = self.crop(outputImage, rect: crop)
let options = [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: 1.0 as CGFloat]
let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)!
let imgFormat = CIFormat.RGBA16
do {
switch format {
case "tiff":
try ciContext.writeTIFFRepresentation(of: processImage, to: destUrl, format: imgFormat, colorSpace: colorSpace, options: options)
case "jpeg":
try ciContext.writeJPEGRepresentation(of: processImage, to: destUrl, colorSpace: colorSpace, options: options)
case "png":
try ciContext.writePNGRepresentation(of: processImage, to: destUrl, format: imgFormat, colorSpace: colorSpace, options: options)
case "heif":
try ciContext.writeHEIFRepresentation(of: processImage, to: destUrl, format: imgFormat, colorSpace: colorSpace, options: options)
default:
try ciContext.writePNGRepresentation(of: processImage, to: destUrl, format: imgFormat, colorSpace: colorSpace, options: options)
}
} catch {
print("Error exporting \(format): \(error.localizedDescription)")
}
}
var useDefaultRAW: Bool = true
func crop(_ ciImage: CIImage, rect: CGRect)->CIImage {
if let cropped = self.cropFilter(ciImage, rect: rect) {
return cropped
} else {
print("Error cropping image !")
return ciImage
}
}
func cropFilter(_ input: CIImage, rect: CGRect) -> CIImage? {
// Getting a dashed border !!
guard let cropFilter = CIFilter(name: "CICrop") else {
print("Error no CICrop filter found !")
return input
}
let ciVect = CIVector(cgRect: rect)
cropFilter.setValue(input, forKey: kCIInputImageKey)
cropFilter.setValue(ciVect, forKey: "inputRectangle")
return cropFilter.value(forKey: kCIOutputImageKey) as? CIImage
}
}