2016-10-23 35 views
5

Tôi muốn tạo ra một điểm ảnh UIImage bởi pixel với nhanh chóng 3Làm thế nào để tạo ra một điểm ảnh pixel

Tôi đã tìm kiếm nhưng tôi không thể tìm thấy một mã số người thực sự hoạt động

Vì vậy, hãy để tôi giải thích, tôi có một mảng với các nhân vật

var array = ["w", "x", "y", "x", "y", "y", "y", "x", "x", "x", "w", "x", "y", "w", "y"] //there will be something like 26 millions of those 

nếu nó w, màu sắc của điểm ảnh là màu xanh

nếu đó là x, màu sắc của các điểm ảnh màu đỏ

nếu nó y, màu sắc của các điểm ảnh là màu xanh lá cây

nếu nó v, màu sắc của các pixel đen

Tôi muốn tạo ra một hình ảnh từ những nhân vật và lưu trữ nó trong các bức ảnh

Bất kỳ suy nghĩ nào ??

Cám ơn câu trả lời của bạn

Trả lời

4

Bạn có thể tạo một CGContext và sau đó lấy đệm data cho hình ảnh đó, và sau đó điền vào đệm rằng với các giá trị tương ứng với các giá trị chuỗi của bạn:

func createImage(width: Int, height: Int, from array: [String], completionHandler: @escaping (UIImage?, String?) -> Void) { 
    DispatchQueue.global(qos: .utility).async { 
     let colorSpace  = CGColorSpaceCreateDeviceRGB() 
     let bytesPerPixel = 4 
     let bitsPerComponent = 8 
     let bytesPerRow  = bytesPerPixel * width 
     let bitmapInfo  = RGBA32.bitmapInfo 

     guard array.count == width * height else { 
      completionHandler(nil, "Array size \(array.count) is incorrect given dimensions \(width) x \(height)") 
      return 
     } 

     guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else { 
      completionHandler(nil, "unable to create context") 
      return 
     } 

     guard let buffer = context.data else { 
      completionHandler(nil, "unable to get context data") 
      return 
     } 

     let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height) 

     for (index, string) in array.enumerated() { 
      switch string { 
      case "w": pixelBuffer[index] = .blue 
      case "x": pixelBuffer[index] = .red 
      case "y": pixelBuffer[index] = .green 
      case "v": pixelBuffer[index] = .black 
      default: completionHandler(nil, "Unexpected value: \(string)"); return 
      } 
     } 

     let cgImage = context.makeImage()! 

     let image = UIImage(cgImage: cgImage) 

     // or 
     // 
     // let image = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up) 

     completionHandler(image, nil) 
    } 

} 

Nếu có 26 triệu pixel, bạn có thể muốn làm điều này không đồng bộ để tránh chặn hàng đợi chính.

Bằng cách này, ở trên sử dụng này struct:

struct RGBA32: Equatable { 
    private var color: UInt32 

    var redComponent: UInt8 { 
     return UInt8((color >> 24) & 255) 
    } 

    var greenComponent: UInt8 { 
     return UInt8((color >> 16) & 255) 
    } 

    var blueComponent: UInt8 { 
     return UInt8((color >> 8) & 255) 
    } 

    var alphaComponent: UInt8 { 
     return UInt8((color >> 0) & 255) 
    } 

    init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8) { 
     color = (UInt32(red) << 24) | (UInt32(green) << 16) | (UInt32(blue) << 8) | (UInt32(alpha) << 0) 
    } 

    static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue 

    static func ==(lhs: RGBA32, rhs: RGBA32) -> Bool { 
     return lhs.color == rhs.color 
    } 

    static let black = RGBA32(red: 0, green: 0, blue: 0, alpha: 255) 
    static let red = RGBA32(red: 255, green: 0, blue: 0, alpha: 255) 
    static let green = RGBA32(red: 0, green: 255, blue: 0, alpha: 255) 
    static let blue = RGBA32(red: 0, green: 0, blue: 255, alpha: 255) 
} 

Để lưu hình ảnh, bạn có thể làm:

createImage(width: width, height: height, from: array) { image, errorMessage in 
    guard let image = image, errorMessage == nil else { 
     print(errorMessage!) 
     return 
    } 

    DispatchQueue.main.async { 
     self.imageView.image = image 
     UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil) 
    } 
} 

đâu

func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: Any?) { 
    guard error == nil else { 
     print(error!.localizedDescription) 
     return 
    } 

    print("image saved") 
} 
+0

nhờ Rob nhưng tôi có một câu hỏi cuối cùng Tôi đã tạo hình ảnh nhưng tôi không thể lưu trữ vì: "Ứng dụng này đã gặp sự cố vì nó đã cố gắng ccess dữ liệu nhạy cảm về quyền riêng tư mà không cần mô tả sử dụng. Info.plist của ứng dụng phải chứa khóa NSPhotoLibraryUsageDescription có giá trị chuỗi giải thích cho người dùng cách ứng dụng sử dụng dữ liệu này. " –

+0

@lbdev Yep, lỗi đó nói lên tất cả: Bạn phải thêm khóa' NSPhotoLibraryUsageDescription' vào thông tin của mình. plist và cung cấp một thông báo sẽ được hiển thị trong hộp thoại yêu cầu sự cho phép vào thư viện ảnh – Rob

+0

chỉ để chắc chắn Bạn có biết nếu tôi lấy lại hình ảnh từ thư viện ảnh, và cố gắng tìm ra mảng, sẽ Tôi nhận được cùng một mảng hoặc nó sẽ khác nhau (bc hình ảnh có thể nén)? –

Các vấn đề liên quan