Has anybody idea how to fetch squared thumbs from PHImageManager? PHImageContentModeAspectFill option has no effect.
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)_asset
targetSize:CGSizeMake(80, 80)
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
// sadly result is not a squared image
imageView.image = result;
}];
Update:
The bug in cropping images as they were retrieved fromIt seems the bugs are still there up to and including iOS 8.4, I can reproduce them with standard iPhone 6s back camera images, taking a full size square crop. They are properly fixed in iOS 9.0, where even large crops of a 63 megapixel panorama work fine.PHImageManager
was fixed in iOS 8.3, so for that version of iOS and later, my original example works, as follows:The approach Apple defines is to pass a
CGRect
in the co-ordinate space of the image, where the origin is (0,0) and the maximum is (1,1). You pass this rect in thePHImageRequestOptions
object, along with aresizeMode
ofPHImageRequestOptionsResizeModeExact
, and then you should get back a cropped image.This example makes its
cropRect
of side length equal to the smaller of the width and height of the asset, and then transforms it to the co-ordinate space of the image usingCGRectApplyAffineTransform
. You may want to set the origin ofsquare
to something other than (0,0), as often you want the crop square centred along the axis of the image which is being cropped, but I'll leave that as an exercise for the reader. :-)Original Answer:
John's answer got me most of the way there, but using his code I was getting stretched and squashed images. Here's how I got an
imageView
to display square thumbnails fetched from the PHImageManager.Firstly, ensure that the
contentMode
property for yourUIImageView
is set toScaleAspectFill
. The default is toScaleToFill
, which doesn't work correctly for displaying square thumbnails fromPHImageManager
, so make sure you change this whether you've instantiated theUIImageView
in code or in the storyboard.Specifying
PHImageRequestOptionsResizeModeExact
for theresizeMode
is not required, as it will not give you a cropped image unless you also supply anormalizedCropRect
, and should not be used here as there's no benefit, and using it means you don't get the benefits of quickly returned cached images.The
UIImage
returned inresult
will be the same aspect ratio as the source, but scaled correctly for use in aUIImageView
which is set to aspect fill to display as a square, so if you're just displaying it, this is the way to go. If you need to crop the image for print or export outside of the app, this isn't what you want - look into the use ofnormalizedCropRect
for that. (edit- see below for example of what should work...)Except this also make sure that the you set the content mode of the UIImageView to UIViewContentModeScaleAspectFill and that you set clipsToBounds = YES by the following 2 lines :
Edit to add normalizedCropRect usage example
WARNING - this doesn't work, but should according to Apple's documentation.
The approach Apple defines is to pass a
CGRect
in the co-ordinate space of the image, where the origin is (0,0) and the maximum is (1,1). You pass this rect in thePHImageRequestOptions
object, along with aresizeMode
ofPHImageRequestOptionsResizeModeExact
, and then you should get back a cropped image. The problem is that you don't, it comes back as the original aspect ratio and the full image.I've verified that the crop rect is created correctly in the image's co-ordinate space, and followed the instruction to use
PHImageRequestOptionsResizeModeExact
, but the result handler will still be passed an image in the original aspect ratio. This seems to be a bug in the framework, and when it is fixed, the following code should work.All I can suggest is that if you have this problem, you file a radar with Apple to request that they fix it!
To get an exact square, you'll have to indicate that you want an exact size by passing options, like so:
This is working fine for me :