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")
}
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. " –
@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
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)? –