swift - 如何快速正确地从图像中提取数字数组?
问题描述
我正在尝试快速从 UIImage 中提取数字数组,但最后我只得到了一堆零,根本没有有用的信息。
这就是我编写的尝试完成此操作的代码。
var photo = UIImage(named: "myphoto.jpg")!
var withAlpha = true
var bytesPerPixels: Int = withAlpha ? 4 : 3
var width: Int = Int(photo.size.width)
var height: Int = Int(photo.size.height)
var bitsPerComponent: Int = 8
var bytesPerRow = bytesPerPixels * width
var totalPixels = (bytesPerPixels * width) * height
var alignment = MemoryLayout<UInt32>.alignment
var data = UnsafeMutableRawPointer.allocate(byteCount: totalPixels, alignment: alignment )
var bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue).rawValue
var colorSpace = CGColorSpaceCreateDeviceRGB()
let ctx = CGContext(data: data, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)
let bindedPointer: UnsafeMutablePointer<UInt32> = data.bindMemory(to: UInt32.self, capacity: totalPixels)
var pixels = UnsafeMutableBufferPointer.init(start: bindedPointer, count: totalPixels)
for p in pixels{
print(p, Date())
}
最后,我尝试绑定 unsafeMutableRawPointer 以提取值但没有成功,我在这里可能缺少什么?
谢谢大家。
解决方案
几点观察:
- 您需要将图像绘制到上下文中。
- 我还建议您不要创建必须手动管理的缓冲区,而是传递
nil
并让操作系统为您创建(和管理)该缓冲区。 - 请注意,
totalPixels
应该只是width * height
. - 您的代码假定
scale
图像的 是1
。这并不总是一个有效的假设。我会抓住cgImage
并使用它的width
andheight
。 - 即使您只有三个组件,您仍然需要使用每个像素 4 个字节。
因此:
guard
let photo = UIImage(named: "myphoto.jpg”),
let cgImage = photo.cgImage
else { return }
let bytesPerPixels = 4
let width = cgImage.width
let height = cgImage.height
let bitsPerComponent: Int = 8
let bytesPerRow = bytesPerPixels * width
let totalPixels = width * height
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue).rawValue
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard
let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
let data = ctx.data
else { return }
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
let pointer = data.bindMemory(to: UInt32.self, capacity: totalPixels)
let pixels = UnsafeMutableBufferPointer(start: pointer, count: totalPixels)
for p in pixels {
print(String(p, radix: 16), Date())
}
推荐阅读
- scala - 为什么在 Scala REPL 中会抛出异常?
- ruby - 如何刷新大型数据库?
- firebase - 使用 Dialogflow-fulfillment 获取设备位置,而不是使用 Google Actions
- c++builder - C++ Builder XE4, 10.2 Tokyo > TStreamWriter > clWhite 无法复制
- angular - Error TS2322: Type 'Object' is not assignable to type 'Produit'
- javascript - 为什么淡入淡出在jquery函数中不起作用
- javascript - 如何在 JavaScript 中检查字符串是否包含数字和特殊字符?
- javascript - 为什么我不能使用括号表示法+变量将属性分配给对象?
- angular - 如何以角度使用rest api Web服务下载.xlsx文件?
- visual-studio-2017 - 在 Visual Studio 中构建测试项目时如何解决 Visual Studio 中的 MSB3277 警告消息?