light at the end of the tunnel

This commit is contained in:
mertalev
2025-07-23 20:08:48 +03:00
parent a67374df75
commit af2a4ae3fc
23 changed files with 540 additions and 561 deletions
+5 -6
View File
@@ -70,7 +70,7 @@ class ThumbnailsPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol ThumbnailApi {
func setThumbnailToBuffer(pointer: Int64, assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], Error>) -> Void)
func setThumbnailToBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], Error>) -> Void)
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
@@ -83,11 +83,10 @@ class ThumbnailApiSetup {
if let api = api {
setThumbnailToBufferChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let pointerArg = args[0] as! Int64
let assetIdArg = args[1] as! String
let widthArg = args[2] as! Int64
let heightArg = args[3] as! Int64
api.setThumbnailToBuffer(pointer: pointerArg, assetId: assetIdArg, width: widthArg, height: heightArg) { result in
let assetIdArg = args[0] as! String
let widthArg = args[1] as! Int64
let heightArg = args[2] as! Int64
api.setThumbnailToBuffer(assetId: assetIdArg, width: widthArg, height: heightArg) { result in
switch result {
case .success(let res):
reply(wrapResult(res))
+29 -16
View File
@@ -14,7 +14,7 @@ class ThumbnailApiImpl: ThumbnailApi {
let requestOptions = PHImageRequestOptions()
requestOptions.isNetworkAccessAllowed = true
requestOptions.deliveryMode = .highQualityFormat
requestOptions.resizeMode = .exact
requestOptions.resizeMode = .fast
requestOptions.isSynchronous = true
requestOptions.version = .current
return requestOptions
@@ -23,31 +23,44 @@ class ThumbnailApiImpl: ThumbnailApi {
private static let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
private static let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue
func setThumbnailToBuffer(pointer: Int64, assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], any Error>) -> Void) {
guard let bufferPointer = UnsafeMutableRawPointer(bitPattern: Int(pointer))
else { completion(.failure(PigeonError(code: "", message: "Could not get buffer pointer for \(assetId)", details: nil))); return }
func setThumbnailToBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], any Error>) -> Void) {
Self.processingQueue.async {
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: Self.fetchOptions).firstObject
else { completion(.failure(PigeonError(code: "", message: "Could not get asset data for \(assetId)", details: nil))); return }
Self.cacheManager.requestImage(
for: asset,
targetSize: CGSize(width: Double(width), height: Double(height)),
contentMode: .aspectFill,
contentMode: .aspectFit,
options: Self.requestOptions,
resultHandler: { (image, info) -> Void in
guard let image = image,
let cgImage = image.cgImage,
let context = CGContext(
data: bufferPointer,
width: cgImage.width,
height: cgImage.height,
bitsPerComponent: 8,
bytesPerRow: cgImage.width * 4,
space: Self.rgbColorSpace,
bitmapInfo: Self.bitmapInfo
) else { completion(.failure(PigeonError(code: "", message: "Could not get pixel data for \(assetId)", details: nil))); return }
let cgImage = image.cgImage else {
completion(.failure(PigeonError(code: "", message: "Could not get pixel data for \(assetId)", details: nil)))
return
}
let pointer = UnsafeMutableRawPointer.allocate(
byteCount: Int(cgImage.width) * Int(cgImage.height) * 4,
alignment: MemoryLayout<UInt8>.alignment
)
guard let context = CGContext(
data: pointer,
width: cgImage.width,
height: cgImage.height,
bitsPerComponent: 8,
bytesPerRow: cgImage.width * 4,
space: Self.rgbColorSpace,
bitmapInfo: Self.bitmapInfo
) else {
pointer.deallocate()
completion(.failure(PigeonError(code: "", message: "Could not create context for \(assetId)", details: nil)))
return
}
context.interpolationQuality = .none
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: cgImage.width, height: cgImage.height))
completion(.success(["width": Int64(cgImage.width), "height": Int64(cgImage.height)]))
completion(.success(["pointer": Int64(Int(bitPattern: pointer)), "width": Int64(cgImage.width), "height": Int64(cgImage.height)]))
}
)
}