I am using the code below for fetching an image:
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:CGSizeMake(800, 600)
contentMode:PHImageContentModeAspectFill
options:options
resultHandler:^(UIImage *result, NSDictionary *info) {
NSLog(@"size:%@",NSStringFromCGSize(result.size));
}];
I'm requesting an image size of 800 x 600, but I'm getting an image size of 45 x 60, which is very poor-quality.
How can i get the requested image size using PhotoKit
?
Your (Unnati's) self answer will work, however it misses out on a number of the optimisations which Apple give you in their framework which get images for you do display more quickly.
Your original code was pretty much correct, but you include an options
object which you probably don't need, and may have been causing you problems if you had set the resizeMode
incorrectly on it. Here is the code which should work for you, I've just removed your options object.
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)asset
targetSize:CGSizeMake(800, 600)
contentMode:PHImageContentModeAspectFit
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
NSLog(@"Image size:%@",NSStringFromCGSize(result.size));
}];
This should be simpler, and give you all the optimisations Apple provide with their framework for free. Here's the explanation of what you get:
The framework will call your result handler multiple times with increasing quality images, allowing you to display something to the user while they wait for the final image. From the documentation:
Photos may call your result handler block more than once. Photos first calls the block to provide a low-quality image suitable for displaying temporarily while it prepares a high-quality image. (If low-quality image data is immediately available, the first call may occur before the method returns.) When the high-quality image is ready, Photos calls your result handler again to provide it.
This means your resultHandler
block needs to be safe to call more than once - the block in your code is as it just logs the size, and for my test image I get two log messages, first one with a low quality 40x26 px image, and then again with a high quality image. If you open the iOS Photos app, you can see low quality images very briefly before they appear to sharpen - this is what's happening here.
Using options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat
prevents this behaviour, and your resultHandler
will only be called once with the final image, so I would suggest not setting this option unless you can't devise a handler block (in your real code) which can be called multiple times.
To provide the final image quickly, the framework will provide an image close to the requested size in the final call to your resultHandler
block, if it has one cached already. If you're using a UIImageView
set with a contentMode
of aspect fill or fit, this won't be a problem, just specify the matching contentMode
in your image request. For example, against my test image, the second call to my resultHandler
is with a 1280x850 image, larger than what I requested but the right ballpark. However, setting options.resizeMode = PHImageRequestOptionsResizeModeExact
will prevent this behaviour and force the framework to resize a fresh copy of the image rather than using a cached copy, which takes time.
Since the Photos framework doesn't crop images (even if you ask it to, but that's a bug ;-)), you won't necessarily get the exact size you request, even using the PHImageRequestOptionsResizeModeExact
option. For example, if you request 800x600 for an image which is not in a 4:3 ratio, Photos can't return an image of that size, it just gets as close as it can - on my latest image, a request like that gets an image of 800x531. This means that you need to be able to handle images which aren't the exact size that you request, so you might as well take advantage of the optimisations in the framework and avoid using PHImageRequestOptionsResizeModeExact
. From the documentation again:
Resizing to exactly match a target size is less efficient than using the fast resizing option.
(Did you have this set to PHImageRequestOptionsResizeModeFast
in your original options
object, which was not included in the question? That may have been causing your issue.)
It's possible to request different versions of an image, as you do in your self answer with options.version = PHImageRequestOptionsVersionCurrent
. This one is not required however, as the default is the current version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With