gpt4 book ai didi

swift - 检索像素数据不能正确使用 UIGraphicsImageRenderer 图像

转载 作者:搜寻专家 更新时间:2023-11-01 06:54:03 35 4
gpt4 key购买 nike

我有以下代码从 UIImage 获取像素数据,这适用于大多数图像,但是当我使用 UIGraphicsImageRenderer 创建图像时不起作用。我希望有人知道解决这个问题的方法。

我当前的代码生成一个简单的图像,但随后访问数据会产生意想不到的结果。

func myDraw() {

let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200))
let image = renderer.image { context in

context.cgContext.setFillColor(UIColor.black.cgColor)
context.cgContext.addRect(CGRect(x: 0, y: 0, width: 100, height: 100))
context.cgContext.fillPath()

context.cgContext.setFillColor(UIColor.red.cgColor)
context.cgContext.addRect(CGRect(x: 100, y: 100, width: 100, height: 100))
context.cgContext.fillPath()

}

let providerData = image.cgImage!.dataProvider!.data
let data = CFDataGetBytePtr(providerData)!
var pixels = [PixelData]()
for i in stride(from: 0, to: 160000-1, by: 4) {
pixels.append(PixelData(a:data[i+3], r:data[i+0], g:data[i+1], b:data[i+2]))
}
self.canvas.image = self.imageFromARGB32Bitmap(pixels: pixels, width: 200, height: 200)

}

我已使用以下代码生成图像以查看其是否正常工作。

func imageFromARGB32Bitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? {
guard width > 0 && height > 0 else { return nil }
guard pixels.count == width * height else { return nil }

let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
let bitsPerComponent = 8
let bitsPerPixel = 32

var data = pixels // Copy to mutable []
guard let providerRef = CGDataProvider(data: NSData(bytes: &data,
length: data.count * MemoryLayout<PixelData>.size)
)
else { return nil }

guard let cgim = CGImage(
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: width * MemoryLayout<PixelData>.size,
space: rgbColorSpace,
bitmapInfo: bitmapInfo,
provider: providerRef,
decode: nil,
shouldInterpolate: true,
intent: .defaultIntent
)
else { return nil }

return UIImage(cgImage: cgim)
}

最佳答案

一些观察:

  1. 您的代码假定 UIGraphicsImageRenderer生成比例为 1 的图像,而默认为 0(即您的设备使用的任何比例)。

    相反,强制比例为 1:

    let format = UIGraphicsImageRendererFormat()
    format.scale = 1
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 200, height: 200), format: format)
  2. 这不是这里的问题,但我们必须注意,您的代码只是假定 UIGraphicsImageRendererFormat 的格式将是特定的字节顺序和格式,您的 imageFromARGB32Bitmap 也是如此.如果你看看 Apple Technical Note 1509 (您的代码无疑最初是从中改编的),他们不只是假设缓冲区将采用特定格式。当我们想要操作/检查缓冲区时,我们应该 (a) 创建所需格式的上下文,(b) 将我们的图像(或其他)绘制到该上下文,只有这样我们才能可靠地查看提供者数据。

  3. imageFromARGB32Bitmap有效,但这让我有点紧张。

    • 使用MemoryLayout<PixelData>.size : Apple advises :

      When allocating memory for multiple instances of T using an unsafe pointer, use a multiple of the type’s stride instead of its size.

      所以,我会使用 stride .

    • 如果 stride 会怎样4 不是像您期望的那样吗?我无法想象它永远不会是 4,但数据提供者假设它们将被打包。这是一个次要的观察,但我可能会将这个假设明确化。

    • 我们是否 100% 确信取消引用 &data会给我们一个连续的缓冲区?我倾向于 withContiguousStorageIfAvailable 只是为了安全。

    例如:

    func imageFromARGB32Bitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? {
    guard width > 0,
    height > 0,
    pixels.count == width * height else { return nil }

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
    let bitsPerComponent = 8
    let bitsPerPixel = 32

    let stride = MemoryLayout<PixelData>.stride
    assert(stride == 4)

    return pixels.withContiguousStorageIfAvailable { bufferPointer -> UIImage? in
    let data = Data(buffer: bufferPointer)

    return CGDataProvider(data: data as CFData)
    .flatMap { CGImage(width: width,
    height: height,
    bitsPerComponent: bitsPerComponent,
    bitsPerPixel: bitsPerPixel,
    bytesPerRow: width * stride,
    space: rgbColorSpace,
    bitmapInfo: bitmapInfo,
    provider: $0,
    decode: nil,
    shouldInterpolate: true,
    intent: .defaultIntent) }
    .flatMap { UIImage(cgImage: $0) }
    } ?? nil
    }

关于swift - 检索像素数据不能正确使用 UIGraphicsImageRenderer 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54970212/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com