使用Swift进行图像处理具有随机效果。

4
我有一个用Swift编写的ImageProcessor(这不是我的),我正在尝试使用一些自己制作的过滤器,但在尝试过程中我注意到存在一些随机噪声。
为了测试这个问题,我制作了一个名为NoFilter的自定义过滤器,它什么也不做。
public class NoFilter : ImageFilterProtocol{
    public func apply(pixel: Pixel) -> Pixel {
        return pixel
    }   
}

这应该输出与获取的相同的图像,有时会在图像中出现随机错误。
例如:

enter image description here

注意代码是相同的,但每次生成的错误都不同。问题结尾有链接可以让你自己尝试运行,每次运行可能会产生不同的结果。是什么原因导致这种情况发生?
程序当前的流程是,ImageProcessor 接收一张图片并将其转换为 RGBAImage,然后当使用一个滤镜调用 apply 时,它会将该滤镜应用于 RGBAImage 中的每个像素(在本例中是没有滤镜的)。最后,当调用 getImage 时,它将 RGBAImage 转换回 UIImage。这表明可能存在从 RGBAImage 转换到/或者从中转换的问题,但我找不到任何问题。
public struct RGBAImage {
    public var pixels: UnsafeMutableBufferPointer<Pixel>
    
    public var width: Int
    public var height: Int
    
    public init?(image: UIImage) {
        guard let cgImage = image.CGImage else { return nil }
        
        // Redraw image for correct pixel format
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        var bitmapInfo: UInt32 = CGBitmapInfo.ByteOrder32Big.rawValue
        bitmapInfo |= CGImageAlphaInfo.PremultipliedLast.rawValue & CGBitmapInfo.AlphaInfoMask.rawValue
        
        width = Int(image.size.width)
        height = Int(image.size.height)
        let bytesPerRow = width * 4
        
        let imageData = UnsafeMutablePointer<Pixel>.alloc(width * height)
        
        guard let imageContext = CGBitmapContextCreate(imageData, width, height, 8, bytesPerRow, colorSpace, bitmapInfo) else { return nil }
        CGContextDrawImage(imageContext, CGRect(origin: CGPointZero, size: image.size), cgImage)
        
        pixels = UnsafeMutableBufferPointer<Pixel>(start: imageData, count: width * height)
    }
    
    public func toUIImage() -> UIImage? {
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        var bitmapInfo: UInt32 = CGBitmapInfo.ByteOrder32Big.rawValue
        bitmapInfo |= CGImageAlphaInfo.PremultipliedLast.rawValue & CGBitmapInfo.AlphaInfoMask.rawValue
        
        let bytesPerRow = width * 4
        
        let imageContext = CGBitmapContextCreateWithData(pixels.baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo, nil, nil)
        
        guard let cgImage = CGBitmapContextCreateImage(imageContext) else {return nil}
        let image = UIImage(CGImage: cgImage)
        
        return image
    }
}

我正在测试的代码是这个, 它与编程有关。请尝试。

有任何想法吗?

编辑:我已将我的代码上传到git,因此可以在线检查。


请在您的问题中编辑相关代码,形成最小完整可复制示例。没有人想从陌生的 URL 下载未知文件。 - Robotic Cat
@RoboticCat 好的,已经修复。 - rr1g0
1个回答

3

当您将图像绘制到图像上下文中时,您忘记清除图像上下文。尝试添加对CGContextClearRect的调用:

let rect = CGRect(origin: CGPointZero, size: image.size)
CGContextClearRect(imageContext, rect)    // Avoid undefined pixels!
CGContextDrawImage(imageContext, rect, cgImage)

那样可以避免未定义的像素从您的图像透明区域中窥视出来。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接