【问题标题】:Crop byte array image in swift快速裁剪字节数组图像
【发布时间】:2022-10-23 23:47:05
【问题描述】:

我正在尝试在 UInt8 数组上裁剪图像。这是我尝试过的方法:

func cropImageArray(byteArray: [UInt8], sourceWidth: Int32, bitsPerPixel: Int32, rect: Int32Rect) -> [UInt8] {
    var blockSize = bitsPerPixel / 8
    
    var outputPixels = [UInt8]()
    
    for _ in 0..<(rect.width * rect.height * blockSize) {
        outputPixels.append(UInt8(0.0))
    }
    
    for line in Int32(0) ..< rect.height {
        var sourceIndex = (((rect.y + line) * sourceWidth) + rect.x) * blockSize
        var destinationIndex = (line * rect.width) * blockSize
        
        for i in Int32(0) ..< Int32(rect.width * blockSize) {
            outputPixels[Int(destinationIndex + i)] = byteArray[Int(sourceIndex + i)]
        }
    }
    return outputPixels
}

它不能正常工作。它给出了破碎的图像。你有想法吗?

编辑:这是我获取字节数组的方式。

let img: UIImage! = UIImage(named: "example")
let d: Data! = img.pngData()
let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: d.count)
d.withUnsafeBytes { (buff) -> Void in
        ptr.initialize(from: buff.bindMemory(to: UInt8.self).baseAddress!, count: d.count)
}
let byteArray = UnsafeMutableBufferPointer(start: ptr, count: d.count).map({$0})

编辑2: 由于性能很高,我用作solution 的功能。

【问题讨论】:

  • 您是如何获得byteArray 的?
  • 我已经编辑了这个问题。

标签: arrays swift image crop uint8array


【解决方案1】:

所以在转换成PNG之后,你不能只是剪切一些字节,认为它们是像素,因为PNG format包含签名,每个字节不仅仅是RGB的编码。您有 3 个选项:

  1. 更简单。从 UIImage 中获取实际源 - CIImage 或 CGImage,并使用CIImage.cropped(to:)CGImage.cropping(to:) 对其进行裁剪。链接页面包含每个页面的示例代码。请注意, UIImage 将包含任何一个CGImage 作为其来源,或 CIImage,绝不是两者兼而有之。 CGImage 和 CIImage 上的坐标系也不同,因此您需要找出合适的坐标进行裁剪。 Here好像有人想出了通用方法,但我没有尝试过,所以不确定它是否正确。

  2. 如果您真的想在像素级别操作图像,可以使用Accelerate framework。它允许您从 CGImage 创建image buffer(如果需要,您可以随时转换CIImage to CGImage)。然后该缓冲区(vImage_Buffer 可以作为原始图像进行操作,这就是您在上面尝试做的事情。一些示例可用here。它们没有显示裁剪,但有一些接近的示例。加速非常高性能,所以如果你有一个图形应用程序,学习和使用它可能是有意义的。

  3. 如果您真的想裁剪PNG图像,您需要从我在答案顶部发布的链接中了解它的格式,然后这样做。通常这不是一个好方法,因为你没有得到第一种方法的简单性,或者第二种方法的良好性能。

【讨论】:

  • 非常感谢您的回答。尤其是 PNG,我使用了 .pngData() 方法,因为它提供的字节数比 jpegData(compressionQuality: 1.0) 多。我已经尝试过您指定的第二个选项。该代码适用于 1920*1080 图像,裁剪为 600*600,结果是 16ms 内的 1000 张图像。非常感谢。我已经用实现代码链接编辑了这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多