fluttercandies / flutter_photo_manager

A Flutter plugin that provides images, videos, and audio abstraction management APIs without interface integration, available on Android, iOS, macOS and OpenHarmony.
https://pub.dev/packages/photo_manager
Apache License 2.0
647 stars 297 forks source link

[Bug report][ios] Getting low quality image when requesting for iCloud origin file #1118

Open ua741 opened 1 month ago

ua741 commented 1 month ago

Version

3.0.0

Platforms

iOS

Device Model

All iPhone Devices

flutter info

flutter 3.19.5

How to reproduce?

Unfortunately, we don't have any reliable way to reproduce this particular issue. On iOS, multiple customers have reported that the app is showing lowered quality photo.

Potential Root Cause

After a quick search on SO, I found following posts that are sort of related to this potential issue. https://stackoverflow.com/a/31784955

 PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
 options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; //I only want the highest possible quality
 options.synchronous = NO;
 options.networkAccessAllowed = YES;
 options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
        NSLog(@"%f", progress); //follow progress + update progress bar
    };

  [[PHImageManager defaultManager] requestImageForAsset:myPhAsset targetSize:self.view.frame.size contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *image, NSDictionary *info) {
        NSLog(@"reponse %@", info);
        NSLog(@"got image %f %f", image.size.width, image.size.height);
    }];

https://stackoverflow.com/a/27700985

If -[PHImageRequestOptions isSynchronous] returns NO (or options is nil), resultHandler may be called 1 or more times. Typically in this case, resultHandler will be called asynchronously on the main thread with the requested results. However, if deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic, resultHandler may be called synchronously on the calling thread if any image data is immediately available. If the image data returned in this first pass is of insufficient quality, resultHandler will be called again, asychronously on the main thread at a later time with the "correct" results. If the request is cancelled, resultHandler may not be called at all. If -[PHImageRequestOptions isSynchronous] returns YES, resultHandler will be called exactly once, synchronously and on the calling thread. Synchronous requests cannot be cancelled. resultHandler for asynchronous requests, always called on main thread


Current Photo Manager Implementation

Link

....
    PHAssetResourceRequestOptions *options = [PHAssetResourceRequestOptions new];
    [options setNetworkAccessAllowed:YES];
    [self notifyProgress:progressHandler progress:0 state:PMProgressStatePrepare];
    [options setProgressHandler:^(double progress) {
        if (progress != 1) {
            [self notifyProgress:progressHandler progress:progress state:PMProgressStateLoading];
        }
    }];

    PHAssetResourceManager *resourceManager = PHAssetResourceManager.defaultManager;
    NSURL *fileUrl = [NSURL fileURLWithPath:path];
    [resourceManager writeDataForAssetResource:imageResource
                                        toFile:fileUrl
                                       options:options
                             completionHandler:^(NSError *_Nullable error) {
        if (error) {
            NSLog(@"error = %@", error);
            [self notifyProgress:progressHandler progress:0 state:PMProgressStateFailed];
            [handler replyError:[NSString stringWithFormat:@"%@", error]];
        } else {
            [handler reply:path];
            [self notifySuccess:progressHandler];
        }
    }];

In PHAssetResourceRequestOptions (used by flutter_photo_manager), unlike PHImageRequestOptions, there's no way to specify deliveryMode of the image, that can impact the quality of the file.

Logs

NA

Example code (optional)

No response

Contact

No response