Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIImage size returned from 'requestImageForAsset' is not even close to the 'targetSize' setting

I've thoroughly read through the latest iOS8 photo frame work and I am trying to fetch some assets from the users library to display. I let the user edit 4 images at once. But because of this, I need to compress the images otherwise the app will crash.

I am using a PHImageManager to load the images via the following code:

func processImages()
    {
        println("Processing")
        _selectediImages = Array()
        _cacheImageComplete = 0
        for asset in _selectedAssets
        {
            var options:PHImageRequestOptions = PHImageRequestOptions()
            options.version = PHImageRequestOptionsVersion.Unadjusted
            options.synchronous = true
            var minRatio:CGFloat = 1
            if(CGFloat(asset.pixelWidth) > UIScreen.mainScreen().bounds.width || CGFloat(asset.pixelHeight) > UIScreen.mainScreen().bounds.height)
            {
               minRatio = min(UIScreen.mainScreen().bounds.width/(CGFloat(asset.pixelWidth)), (UIScreen.mainScreen().bounds.height/CGFloat(asset.pixelHeight)))
            }
            var size:CGSize = CGSizeMake((CGFloat(asset.pixelWidth)*minRatio),(CGFloat(asset.pixelHeight)*minRatio))
            println("Target size is \(size)")
            PHImageManager.defaultManager().requestImageForAsset(asset, targetSize:size, contentMode: .AspectFill, options: options)
                {
                    uiimageResult, info in
                    var image = iImage(uiimage: uiimageResult)
                    println("Result Size Is \(uiimageResult.size)")
            }

        }

    }

As you can see, I am calculating the target size to make sure the image is at least no bigger than the screen. If it is, I do a ratio scale down on the image. However here is a typical print log

Target size is (768.0,798.453531598513) Result Size Is (1614.0,1678.0)

Even though I am setting the target size to 768x798 (in that specific case) the resulting UIImage it's giving me is more than double that. Now according to the documentation, the targetSize parameter

"The target size of image to be returned."

Not the clearest explanation but from my experiments it is NOT matching this.

If you have some suggestions I'd love to hear it!

like image 228
Aggressor Avatar asked Oct 30 '14 21:10

Aggressor


4 Answers

This is because requestImageForAsset will be called twice.

The first time, it will return a very same size image, such as (60 * 45) which I think is the thumbnail of that image.

The second time, you will get the full size image.

I use

if ([[info valueForKey:@"PHImageResultIsDegradedKey"]integerValue]==0){ // Do something with the FULL SIZED image } else { // Do something with the regraded image }

to distinguish the two different images.

Reference: iOS 8 PhotoKit. Get maximum-size image from iCloud Photo Sharing albums

like image 186
Yuchao Zhou Avatar answered Nov 20 '22 04:11

Yuchao Zhou


In Swift, you want to do something like this:

var asset: PHAsset!
var imageSize = CGSize(width: 100, height: 100)

var options = PHImageRequestOptions()
options.resizeMode = PHImageRequestOptionsResizeMode.Exact
options.deliveryMode = PHImageRequestOptionsDeliveryMode.Opportunistic

PHImageManager.defaultManager().requestImage(asset, targetSize: imageSize, contentMode: PHImageContentMode.AspectFill, options: options) {
    (image, info) -> Void in
    // what you want to do with the image here
    print("Result Size Is \(image.size)")

}

In Objective-C, it looks something like this:

void (^resultHandler)(UIImage *, NSDictionary *) = ^(UIImage *result, NSDictionary *info) {
    // what you want to do with the image

};

CGSize cellSize = CGSizeMake(100, 100);

PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeExact;
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;

[[PHImageManager defaultManager] requestImageForAsset:self.imageAsset targetSize:cellSize contentMode:PHImageContentModeAspectFill options:options resultHandler:resultHandler];

Important Note: With the Opportunistic delivery mode, the result block may be called more than once with different sizes, but the last call will be the size you want. It's better to use Opportunistic so that the UI will load a low-quality placeholder first and then update it as the OS can generate a better image (rather than having a blank square).

like image 10
mikeho Avatar answered Nov 20 '22 03:11

mikeho


Try to set the resizeMode to PHImageRequestOptionsResizeModeExact and deliveryMode to PHImageRequestOptionsDeliveryModeHighQualityFormat;

PHImageRequestOptionsResizeModeExact, 
// same as above but also guarantees the delivered image is exactly targetSize (must be set when a normalizedCropRect is specified)
like image 6
gabbler Avatar answered Nov 20 '22 04:11

gabbler


You can use PHImageManagerMaximumSize as the targetSize for a PHImageManager request.

According to the docs in PHImageManagerMaximumSize: Size to pass when requesting the original image or the largest rendered image available (resizeMode will be ignored)

like image 3
Bruno Delgado Avatar answered Nov 20 '22 04:11

Bruno Delgado