2016-07-06 156 views
1

我有一個來自指紋傳感器設備的字節數組。我想創建一個位圖。我已經嘗試了幾個例子,但我所得到的只是一個零UIImage。如何從swift中的字節數組創建位圖圖像

如果有任何步驟可以做到這一點,請告訴我。

謝謝。

這是我的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 
     } 
} 

我得到一個扭曲的圖像。有人請幫助

+0

請重新審視我的疑問句和幫助我。 –

+0

順便說一句,寬度和高度只佔用4個字節,但你跳過前8個字節。我在下面的答案中保留了這個,但我想確保這是你的實際意圖,在你跳過的寬度和高度之後有四個字節... – Rob

回答

3

這裏的一個重要問題是,當你調用CGBitmapContextCreate時,你指定你正在單獨構建一個alpha通道,你的data緩衝區顯然使用每個像素一個字節,但是對於「每行字節數」參數,您已指定4 * width。它應該是width。當您捕獲每像素四個字節(例如RGBA)時,通常使用4x,但由於緩衝區每像素使用一個字節,因此應刪除該4倍因子。


就個人而言,我還告訴了一系列其他方面的改進,即:

  • 應該被分發到主隊列的唯一的事情就是控制的UIKit的更新

  • 您可以退休finalData,因爲您不需要從一個緩衝區複製到另一個緩衝區,而是可以直接構建msgData

  • 你或許應該繞過您自己的緩衝區的建立完全,雖然和調用CGBitmapContextCreatenil的數據參數,在這種情況下,它會創建自己的緩衝區您可以通過CGBitmapContextGetData檢索。如果你將它傳遞給一個緩衝區,它假定你將自己管理這個緩衝區,這是我們在這裏沒有做的。

    如果您創建自己的緩衝區並且沒有正確管理該內存,那麼您會在看起來像是有效的情況下遇到難以重現的錯誤,但是突然間您會看到緩衝區無故崩潰類似的情況。通過讓Core Graphics管理內存,可以防止這些問題。

  • 我可能會將該字節緩衝區的轉換從更新UIImageViewUIImage中分離出來。

所以能產生類似:

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 
    } 
} 
+0

Heyyyyyyy :) :) :)它的工作方式類似於魅力:)非常感謝搶劫:)我不想要第一個8字節,因爲它包含寬度,高度和總字節數。所以我忽略它。 –