300x300像素Png图像到字节数组
Posted
技术标签:
【中文标题】300x300像素Png图像到字节数组【英文标题】:300x300 pixel Png image to Byte Array 【发布时间】:2021-09-26 23:20:32 【问题描述】:我的目标是从 CVImageBuffer(相机流)中提取 300x300 像素帧并将其转换为 UInt 字节数组。从技术上讲,数组大小应该是 90,000。但是,我得到了更大的价值。任何帮助将不胜感激发现错误。
将Image缓冲区转换为UIImage的方法
func getImageFromSampleBuffer(image_buffer : CVImageBuffer?) -> UIImage?
if let imageBuffer = image_buffer
// Lock the base address of the pixel buffer
CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags.readOnly);
// Get the number of bytes per row for the pixel buffer
let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
// Get the number of bytes per row for the pixel buffer
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
// Get the pixel buffer width and height
let width = CVPixelBufferGetWidth(imageBuffer);
let height = CVPixelBufferGetHeight(imageBuffer);
// Create a device-dependent RGB color space
let colorSpace = CGColorSpaceCreateDeviceRGB();
// Create a bitmap graphics context with the sample buffer data
var bitmapInfo: UInt32 = CGBitmapInfo.byteOrder32Little.rawValue
bitmapInfo |= CGImageAlphaInfo.premultipliedFirst.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
//let bitmapInfo: UInt32 = CGBitmapInfo.alphaInfoMask.rawValue
let context = CGContext.init(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo)
// Create a Quartz image from the pixel data in the bitmap graphics context
let quartzImage = context?.makeImage();
// Unlock the pixel buffer
CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags.readOnly);
// Create an image object from the Quartz image
let image = UIImage.init(cgImage: quartzImage!);
return (image);
return nil
将图像数据转换为 UInt8 数组的扩展
extension Data
func toByteArray() -> [UInt8]?
var byteData = [UInt8](repeating:0, count: self.count)
self.copyBytes(to: &byteData, count: self.count)
return byteData
代码的使用
let image = getImageFromSampleBuffer(image_buffer: imageBuffer)
//Issue*******
if let byteArrayOfImage = image.copy(newSize: CGSize(width: 300, height: 300))?.pngData()?.toByteArray()
print(byteArrayOfImage.count) // Technically should print 90,000. However it prints a large value
我错过了什么
【问题讨论】:
pngData() 函数不返回像素数据。它返回一个 PNG 文件的数据,包括 PNG 文件头和压缩的像素数据,这与您的预期完全不同。正如其他答案中提到的,如果您的图像大小为 300x300,这并不意味着它应该有 90000 个字节,因为 1 个像素很可能需要 4 个字节的未压缩格式(如果这是 RGBA)。 【参考方案1】:你的期望Technically the array size should be 90,000
可能是错误的。
如果您的 CVPixelBuffer
的格式是 BRGA 或其他 4 通道类型,则数组大小将为 w*h*4=360,000
,其中 w*4
或更一般地说,w*channel_count
是 row stride
。
CVPixelBuffer
通常按 16 个字节对齐:
https://developer.apple.com/documentation/corevideo/kcvpixelbufferbytesperrowalignmentkey?language=objc
所以真正的row stride
可能比w*channel_count
还要多。
您应该检查值bytesPerRow
以了解您的整个问题。
【讨论】:
极好的答案,但是,如果您查看代码,我会将 CVImageBuffer 转换为 UIImage,然后我只尝试将 300x300 图像转换为 UInt 数组。为什么我的数组仍然会给我一个高密度值 另外,如果我可以将像素格式设置为 kCVPixelFormatType_8Indexed,我想问题可能就解决了?? 请用// Technically should print 90,000. However it prints a large value
的确切值更新您的问题
另外,请指定bytesPerRow
的值以上是关于300x300像素Png图像到字节数组的主要内容,如果未能解决你的问题,请参考以下文章