简体   繁体   English

快速从 UIImage/CGImage 获取像素数据作为数组

[英]Get pixel data as array from UIImage/CGImage in swift

I have an app so far that allows the user to free draw (like a sketch pad) on a UIImageView element.到目前为止,我有一个应用程序,它允许用户在UIImageView元素上自由绘制(如素描板)。

I want to get the raw RGB pixel data (as 0 to 255 integer values) as a multidimensional array so I can feed it into a machine learning algorithm .我想将原始 RGB 像素数据(作为0255整数值)作为多维数组获取,以便我可以将其输入到机器学习算法中。 Or is there some other way I can send the raw image data over to separate C++ function?还是有其他方法可以将原始图像数据发送到单独的 C++ 函数?

Is there an easy way to do this in Swift?有没有一种简单的方法可以在 Swift 中做到这一点?

In Swift 3 and Swift 4, using Core Graphics, it is quite easy to do what you want:在 Swift 3 和 Swift 4 中,使用 Core Graphics,很容易做你想做的事:

extension UIImage {
    func pixelData() -> [UInt8]? {
        let size = self.size
        let dataSize = size.width * size.height * 4
        var pixelData = [UInt8](repeating: 0, count: Int(dataSize))
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let context = CGContext(data: &pixelData,
                                width: Int(size.width),
                                height: Int(size.height),
                                bitsPerComponent: 8,
                                bytesPerRow: 4 * Int(size.width),
                                space: colorSpace,
                                bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue)
        guard let cgImage = self.cgImage else { return nil }
        context?.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))

        return pixelData
    }
 }

Converting a CGImage to an array of intensity values将 CGImage 转换为强度值数组

My function takes a CGImage and returns an array of unsigned 8-bit integers as well as the width and height of the image.我的函数接受一个CGImage并返回一个无符号 8 位整数数组以及图像的宽度和高度。 I wrote this code for use with grayscale images.我编写了此代码用于灰度图像。 Extending this to color should be a matter of changing Gray to RGB and changing the bytes per pixel to 3 assuming no alpha channel.将此扩展到颜色应该是将灰色更改为 RGB 并将每个像素的字节数更改为 3(假设没有 alpha 通道)。

func pixelValues(fromCGImage imageRef: CGImage?) -> (pixelValues: [UInt8]?, width: Int, height: Int)
{
    var width = 0
    var height = 0
    var pixelValues: [UInt8]?
    if let imageRef = imageRef {
        width = imageRef.width
        height = imageRef.height
        let bitsPerComponent = imageRef.bitsPerComponent
        let bytesPerRow = imageRef.bytesPerRow
        let totalBytes = height * bytesPerRow

        let colorSpace = CGColorSpaceCreateDeviceGray()
        var intensities = [UInt8](repeating: 0, count: totalBytes)

        let contextRef = CGContext(data: &intensities, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: 0)
        contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))

        pixelValues = intensities
    }

    return (pixelValues, width, height)
}

func image(fromPixelValues pixelValues: [UInt8]?, width: Int, height: Int) -> CGImage?
{
    var imageRef: CGImage?
    if var pixelValues = pixelValues {
        let bitsPerComponent = 8
        let bytesPerPixel = 1
        let bitsPerPixel = bytesPerPixel * bitsPerComponent
        let bytesPerRow = bytesPerPixel * width
        let totalBytes = height * bytesPerRow

        imageRef = withUnsafePointer(to: &pixelValues, {
            ptr -> CGImage? in
            var imageRef: CGImage?
            let colorSpaceRef = CGColorSpaceCreateDeviceGray()
            let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue).union(CGBitmapInfo())
            let data = UnsafeRawPointer(ptr.pointee).assumingMemoryBound(to: UInt8.self)
            let releaseData: CGDataProviderReleaseDataCallback = {
                (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in
            }

            if let providerRef = CGDataProvider(dataInfo: nil, data: data, size: totalBytes, releaseData: releaseData) {
                imageRef = CGImage(width: width,
                                   height: height,
                                   bitsPerComponent: bitsPerComponent,
                                   bitsPerPixel: bitsPerPixel,
                                   bytesPerRow: bytesPerRow,
                                   space: colorSpaceRef,
                                   bitmapInfo: bitmapInfo,
                                   provider: providerRef,
                                   decode: nil,
                                   shouldInterpolate: false,
                                   intent: CGColorRenderingIntent.defaultIntent)
            }

            return imageRef
        })
    }

    return imageRef
}

Please try this.请试试这个。 This worked right for me.这对我有用。

func pixelValues(fromCGImage imageRef: CGImage?) -> [UInt8]?
    {
        var width = 0
        var height = 0
        var pixelValues: [UInt8]?

        if let imageRef = imageRef {
            width = imageRef.width
            height = imageRef.height
            let bitsPerComponent = imageRef.bitsPerComponent
            let bytesPerRow = imageRef.bytesPerRow
            let totalBytes = height * bytesPerRow
            let bitmapInfo = imageRef.bitmapInfo

            let colorSpace = CGColorSpaceCreateDeviceRGB()
            var intensities = [UInt8](repeating: 0, count: totalBytes)

            let contextRef = CGContext(data: &intensities,
                                      width: width,
                                     height: height,
                           bitsPerComponent: bitsPerComponent,
                                bytesPerRow: bytesPerRow,
                                      space: colorSpace,
                                 bitmapInfo: bitmapInfo.rawValue)
            contextRef?.draw(imageRef, in: CGRect(x: 0.0, y: 0.0, width: CGFloat(width), height: CGFloat(height)))

            pixelValues = intensities
        }

        return pixelValues
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM