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_countrow 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图像到字节数组的主要内容,如果未能解决你的问题,请参考以下文章

如何将RGBA字节串转换为灰度图像?

从 YUV 字节数组中获取像素矩阵

如何在java中从像素字节数组制作bmp图像

从 RGBA 像素字节数据重构 UIImage 的问题

如何从 jpeg 或 png 格式的字节数组在画布上绘制图像

将 PIL 图像转换为字节数组?