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

Ios 如何从swift中的字节数组创建位图图像,ios,swift,Ios,Swift,我有一个字节数组,它来自指纹传感器设备。我想用它创建一个位图。我尝试了几个例子,但我得到的只是一个零图像 如果有任何步骤可以做到这一点,请告诉我 谢谢 这就是我的func所做的: func didFingerGrabDataReceived(data: [UInt8]) { if data[0] == 0 { let width1 = Int16(data[0]) << 8 let finalWidth = Int(Int16(data[1])

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

如果有任何步骤可以做到这一点,请告诉我

谢谢

这就是我的func所做的:

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
        }
}
收到func didFingerGrabDataReceived(数据:[UInt8]){ 如果数据[0]==0{
让width1=Int16(数据[0])这里的一个重要问题是,当您调用
CGBitmapContextCreate
时,您指定单独构建一个alpha通道,您的
数据
缓冲区显然使用了每像素一个字节,但“每行字节”除外参数,您已经指定了
4*width
。它应该是
width
。当您捕获每个像素四个字节(例如RGBA)时,通常使用4x,但由于您的缓冲区使用的是每个像素一个字节,因此应该删除该4x因子


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

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

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

  • 不过,您可能应该完全绕过创建自己的缓冲区,并使用
    nil
    调用
    CGBitmapContextCreate
    作为数据参数,在这种情况下,它将创建自己的缓冲区,您可以通过
    CGBitmapContextGetData
    检索该缓冲区。如果向它传递一个缓冲区,它将假定您将管理该缓冲区我们自己,这不是我们在这里做的

    如果您创建了自己的缓冲区,但没有正确管理该内存,您将在看似有效的地方遇到难以重现的错误,但突然之间,您会发现在看似类似的情况下,缓冲区会无缘无故地损坏。通过让核心图形管理内存,可以防止此类问题

  • 我可以将此字节缓冲区转换为
    UIImage
    与更新
    UIImageView
    分开

这就产生了如下结果:

func mask(from 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

    let colorSpace = CGColorSpaceCreateDeviceGray()

    guard
        data.count >= width * height + 8,
        let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width, space: colorSpace, bitmapInfo: CGImageAlphaInfo.alphaOnly.rawValue),
        let buffer = context.data?.bindMemory(to: UInt8.self, capacity: width * height)
    else {
        return nil
    }

    for index in 0 ..< width * height {
        buffer[index] = data[index + 8]
    }

    return context.makeImage().flatMap { UIImage(cgImage: $0) }
}


有关Swift 2格式副本,请参见。

请重新阅读我的问题并帮助我。顺便说一下,宽度和高度仅占4个字节,但您跳过了前8个字节。我在下面的回答中保留了这一点,但我想确保这是您的真实意图,在宽度和高度之后有四个字节是您跳过的…嘿,YYYYYY:):):)它工作起来很有魅力:)非常感谢rob:)我不想要前8个字节,因为它包含宽度、高度和总字节数。所以我忽略它。
if let image = mask(from: data) {
    DispatchQueue.main.async {
        self.imageViewFinger.image = image
    }
}