如何在swift中从字节数组创建位图图像

时间:2016-07-06 16:27:25

标签: ios swift

我有一个来自指纹传感器设备的字节数组。我想用它创建一个位图。我尝试过几个例子,但我得到的只是一个无用的UIImage。

如果有任何措施,请告诉我。

感谢。

这就是我的功能所在:

func didFingerGrabDataReceived(data: [UInt8]) {
    if data[0] == 0 {
        let width1 = Int16(data[0]) << 8
        let finalWidth = Int(Int16(data[1]) | width1)

        let height1 = Int16(data[2]) << 8
        let finalHeight = Int(Int16(data[3]) | height1)

        var finalData:[UInt8] = [UInt8]()

// i dont want the first 8 bytes, so am removing it

        for i in 8 ..< data.count {
            finalData.append(data[i])
        }

     dispatch_async(dispatch_get_main_queue()) { () -> Void in

        let msgData = NSMutableData(bytes: finalData, length: finalData.count)

        let ptr = UnsafeMutablePointer<UInt8>(msgData.mutableBytes)


        let colorSpace = CGColorSpaceCreateDeviceGray()
        if colorSpace == nil {
            self.showToast("color space is nil")
            return
        }

        let bitmapContext = CGBitmapContextCreate(ptr, finalWidth, finalHeight, 8, 4 * finalWidth, colorSpace,  CGImageAlphaInfo.Only.rawValue);

        if bitmapContext == nil {
            self.showToast("context is nil")
            return
        }

        let cgImage=CGBitmapContextCreateImage(bitmapContext);
        if cgImage == nil {
            self.showToast("image is nil")
            return
        }

        let newimage = UIImage(CGImage: cgImage!)

            self.imageViewFinger.image = newimage
        }
}

我的图像变形了。有人请帮忙

1 个答案:

答案 0 :(得分:5)

这里的重要问题是,当您调用CGBitmapContextCreate时,您指定单独构建Alpha通道,您的data缓冲区显然每个像素使用一个字节,但对于“字节”每行“参数,您已指定4 * width。它应该是width。当你每个像素捕获四个字节时(例如RGBA),通常使用4x,但由于你的缓冲区每个像素使用一个字节,你应该删除那个4x因子。

就个人而言,我还会提出一系列其他改进建议,即:

  • 应该分配到主队列的唯一事情是更新UIKit控件

  • 您可以退出finalData,因为您不需要从一个缓冲区复制到另一个缓冲区,而是可以直接构建msgData

  • 你应该完全绕过你自己的缓冲区的创建,然后用CGBitmapContextCreate为数据参数调用nil,在这种情况下,它会创建自己的缓冲区可以通过CGBitmapContextGetData检索。如果你传递一个缓冲区,它会假设你自己管理这个缓冲区,我们在这里没有这样做。

    如果您创建自己的缓冲区并且没有正确管理该内存,那么在它看起来有效的情况下您将遇到难以重现的错误,但突然间您会看到缓冲区因为看似相似而无缘无故地损坏的情况。通过让Core Graphics管理内存,可以防止出现这些问题。

  • 我可能会将此字节缓冲区的转换与UIImage的更新分开UIImageView

因此产生类似的东西:

func maskFromData(data: [UInt8]) -> UIImage? {
    guard data.count >= 8 else {
        print("data too small")
        return nil
    }

    let width  = Int(data[1]) | Int(data[0]) << 8
    let height = Int(data[3]) | Int(data[2]) << 8

    guard data.count >= width * height + 8 else {
        print("data not large enough to hold \(width)x\(height)")
        return nil
    }

    guard let colorSpace = CGColorSpaceCreateDeviceGray() else {
        print("color space is nil")
        return nil
    }

    guard let bitmapContext = CGBitmapContextCreate(nil, width, height, 8, width, colorSpace, CGImageAlphaInfo.Only.rawValue) else {
        print("context is nil")
        return nil
    }

    let dataPointer = UnsafeMutablePointer<UInt8>(CGBitmapContextGetData(bitmapContext))
    for index in 0 ..< width * height {
        dataPointer[index] = data[index + 8]
    }

    guard let cgImage = CGBitmapContextCreateImage(bitmapContext) else {
        print("image is nil")
        return nil
    }

    return UIImage(CGImage: cgImage)
}

然后

 if let image = maskFromData(data) {
     dispatch_async(dispatch_get_main_queue()) { 
         self.imageViewFinger.image = image
     }
 }