Ответ 1
Update:
Ошибка в обрезке изображений по мере их получения из
Кажется, что ошибки все еще существуют до IOS 8.4, включая IOS 8.4, я могу воспроизвести их со стандартными изображениями задней камеры iPhone 6s, взяв квадратную культуру размером в полный размер. Они правильно установлены в iOS 9.0, где даже большие посевы с разрешением 63 мегапикселя прекрасно работают.PHImageManager
была исправлена в iOS 8.3, поэтому для этой версии iOS и более поздних версий мой оригинальный пример работает следующим образом:
Подход Apple определяет, должен пройти a CGRect
в пространстве координат изображения, где начало координат (0,0), а максимальное - (1,1). Вы передаете этот прямоугольник в объекте PHImageRequestOptions
вместе с resizeMode
из PHImageRequestOptionsResizeModeExact
, а затем вы должны вернуть обрезанное изображение.
- (void)showSquareImageForAsset:(PHAsset *)asset
{
NSInteger retinaScale = [UIScreen mainScreen].scale;
CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale);
PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init];
cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact;
CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight);
CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength);
CGRect cropRect = CGRectApplyAffineTransform(square,
CGAffineTransformMakeScale(1.0 / asset.pixelWidth,
1.0 / asset.pixelHeight));
cropToSquare.normalizedCropRect = cropRect;
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)asset
targetSize:retinaSquare
contentMode:PHImageContentModeAspectFit
options:cropToSquare
resultHandler:^(UIImage *result, NSDictionary *info) {
self.imageView.image = result;
}];
}
Этот пример делает его cropRect
боковой длины равным меньшей ширины и высоты актива, а затем преобразует его в пространство координат изображения с помощью CGRectApplyAffineTransform
. Вы можете установить источник square
на что-то иное, чем (0,0), так как часто вы хотите, чтобы квадрат обрезки был центрирован вдоль оси изображения, которое обрезается, но я оставлю это как упражнение для читатель.: -)
Исходный ответ:
Джон ответ получил большую часть пути, но, используя его код, я получал растянутые и раздавленные изображения. Здесь, как я получил imageView
для отображения квадратных миниатюр, полученных из PHImageManager.
Во-первых, убедитесь, что для свойства contentMode
для вашего UIImageView
установлено значение ScaleAspectFill
. Значение по умолчанию - ScaleToFill
, которое не работает корректно для отображения квадратных эскизов из PHImageManager
, поэтому убедитесь, что вы изменили это, внесли ли вы экземпляр UIImageView
в код или в раскадровку.
//view dimensions are based on points, but we're requesting pixels from PHImageManager
NSInteger retinaMultiplier = [UIScreen mainScreen].scale;
CGSize retinaSquare = CGSizeMake(imageView.bounds.size.width * retinaMultiplier, imageView.bounds.size.height * retinaMultiplier);
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)_asset
targetSize:retinaSquare
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
// The result is not square, but correctly displays as a square using AspectFill
imageView.image = result;
}];
Указание PHImageRequestOptionsResizeModeExact
для resizeMode
не требуется, так как оно не даст вам обрезанного изображения, если вы также не поставляете normalizedCropRect
, и его не следует использовать здесь, поскольку нет никакой пользы, и использование этого означает, что вы не получают преимущества быстро возвращаемых кешированных изображений.
UIImage
, возвращенный в result
, будет иметь такое же соотношение сторон, что и исходный, но правильно масштабируется для использования в UIImageView
, который установлен на аспектное заполнение для отображения в виде квадрата, поэтому, если вы просто показывая это, это путь. Если вам нужно обрезать изображение для печати или экспорта за пределами приложения, это не то, что вы хотите - посмотрите на использование normalizedCropRect
для этого. (отредактируйте - см. ниже, например, что должно работать...)
Кроме того, убедитесь, что вы установили режим содержимого UIImageView в UIViewContentModeScaleAspectFill и установили clipToBounds = YES следующими двумя строками:
imageView.contentMode=UIViewContentModeScaleAspectFill;
imageView.clipsToBounds=YES;
Изменить, чтобы добавить пример использования normalizedCropRect
ПРЕДУПРЕЖДЕНИЕ - это не работает, но должно соответствовать документации Apple.
Подход Apple определяет, должен пройти a CGRect
в пространстве координат изображения, где начало координат (0,0), а максимальное - (1,1). Вы передаете этот прямоугольник в объекте PHImageRequestOptions
вместе с resizeMode
из PHImageRequestOptionsResizeModeExact
, а затем вы должны вернуть обрезанное изображение. Проблема в том, что вы этого не делаете, она возвращается как исходное соотношение сторон и полное изображение.
Я проверил, что прямоугольник обрезки создается правильно в пространстве координат изображения и следуют инструкции для использования PHImageRequestOptionsResizeModeExact
, но обработчик результата все равно будет передан образ в исходном соотношении сторон. Это похоже на ошибку в структуре, и когда она исправлена, следующий код должен работать.
- (void)showSquareImageForAsset:(PHAsset *)asset
{
NSInteger retinaScale = [UIScreen mainScreen].scale;
CGSize retinaSquare = CGSizeMake(100*retinaScale, 100*retinaScale);
PHImageRequestOptions *cropToSquare = [[PHImageRequestOptions alloc] init];
cropToSquare.resizeMode = PHImageRequestOptionsResizeModeExact;
CGFloat cropSideLength = MIN(asset.pixelWidth, asset.pixelHeight);
CGRect square = CGRectMake(0, 0, cropSideLength, cropSideLength);
CGRect cropRect = CGRectApplyAffineTransform(square,
CGAffineTransformMakeScale(1.0 / asset.pixelWidth,
1.0 / asset.pixelHeight));
cropToSquare.normalizedCropRect = cropRect;
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)asset
targetSize:retinaSquare
contentMode:PHImageContentModeAspectFit
options:cropToSquare
resultHandler:^(UIImage *result, NSDictionary *info) {
self.imageView.image = result;
}];
}
Все, что я могу предложить, это то, что если у вас есть эта проблема, вы файл радара с Apple, чтобы попросить их исправить!