ios - Cómo obtener miniaturas cuadradas de PHImageManager?
ios8 photosframework (4)
Para obtener un cuadrado exacto, deberá indicar que desea un tamaño exacto pasando las opciones, de esta manera:
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// No, really, we want this exact size
options.resizeMode = PHImageRequestOptionsResizeModeExact
[[PHImageManager defaultManager]
requestImageForAsset:(PHAsset *)_asset
targetSize:CGSizeMake(160, 160)
contentMode:PHImageContentModeAspectFill
options:options
resultHandler:^(UIImage *result, NSDictionary *info) {
// Happily, result is now a squared image
imageView.image = result;
}];
¿Alguien ha pensado en cómo obtener los pulgares al cuadrado de PHImageManager? La opción PHImageContentModeAspectFill no tiene ningún efecto.
[[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;
}];
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.resizeMode = PHImageRequestOptionsResizeModeExact;
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:options
resultHandler:^(UIImage *result, NSDictionary *info) {
imageView.image =[UIImage imageWithCGImage:result.CGImage scale:retinaMultiplier orientation:result.imageOrientation];
}];
Esto está funcionando bien para mí:
__block UIImage* imgThumb;
CGSize size=CGSizeMake(45, 45);// Size for Square image
[self.imageManager requestImageForAsset:<your_current_phAsset>
targetSize:size
contentMode:PHImageContentModeAspectFill
options:nil
resultHandler:^(UIImage *result, NSDictionary *info) {
imgThumb = result;
}];
Actualizar:
El error al recortar las imágenes tal como se recuperaron de parece que los errores aún existen, incluido iOS 8.4, puedo reprodúzcalos con imágenes estándar de la cámara posterior del iPhone 6s, tomando una cosecha cuadrada de tamaño completo. Están corregidos en iOS 9.0, donde incluso los grandes cultivos de un panorama de 63 megapíxeles funcionan bien. PHImageManager
se corrigió en iOS 8.3, por lo que para esa versión de iOS y posterior, mi ejemplo original funciona de la siguiente manera:
El enfoque que Apple define es pasar un CGRect
en el espacio de coordenadas de la imagen, donde el origen es (0,0) y el máximo es (1,1). PHImageRequestOptions
este rect en el objeto PHImageRequestOptions
, junto con un resizeMode
de PHImageRequestOptionsResizeModeExact
, y luego debe recuperar una imagen recortada.
- (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;
}];
}
Este ejemplo hace que su cropRect
de longitud lateral sea igual al menor del ancho y alto del activo, y luego lo transforma en el espacio de coordenadas de la imagen usando CGRectApplyAffineTransform
. Es posible que desee establecer el origen del square
en algo que no sea (0,0), con la frecuencia que desee que el cuadrado de recorte se centre en el eje de la imagen que se está recortando, pero lo dejaré como un ejercicio para el lector . :-)
Respuesta Original:
La respuesta de John me llevó la mayor parte del camino hasta allí, pero usando su código me estaba estirando y aplastando las imágenes. Así es como obtuve un imageView
para mostrar miniaturas cuadradas obtenidas de PHImageManager.
En primer lugar, asegúrese de que la propiedad UIImageView
para su UIImageView
esté configurada en ScaleAspectFill
. El valor predeterminado es ScaleToFill
, que no funciona correctamente para mostrar miniaturas cuadradas de PHImageManager
, así que asegúrese de cambiar esto si ha UIImageView
instancia de UIImageView
en el código o en el guión gráfico.
//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;
}];
resizeMode
es necesario especificar PHImageRequestOptionsResizeModeExact
para resizeMode
, ya que no le proporcionará una imagen recortada a menos que también proporcione resizeMode
normalizedCropRect
, y no debe usarse aquí ya que no ofrece ningún beneficio, y al usarlo no obtendrá los beneficios de una devolución rápida. imágenes en caché.
El UIImage
devuelto en el result
tendrá la misma relación de aspecto que la fuente, pero se escalará correctamente para su uso en un UIImageView
que se configura en relleno de aspecto para mostrarse como un cuadrado, por lo que si solo lo muestra, este es el camino a seguir . Si necesita recortar la imagen para imprimirla o exportarla fuera de la aplicación, esto no es lo que desea; busque el uso de normalizedCropRect
para eso. (edit- ver abajo, por ejemplo, de lo que debería funcionar ...)
Excepto que esto también se asegura de que establezca el modo de contenido de UIImageView en UIViewContentModeScaleAspectFill y que configure clipsToBounds = YES en las siguientes 2 líneas:
imageView.contentMode=UIViewContentModeScaleAspectFill;
imageView.clipsToBounds=YES;
Editar para agregar el ejemplo de uso de normalizedCropRect
ADVERTENCIA: esto no funciona, pero de acuerdo con la documentación de Apple .
El enfoque que Apple define es pasar un CGRect
en el espacio de coordenadas de la imagen, donde el origen es (0,0) y el máximo es (1,1). PHImageRequestOptions
este rect en el objeto PHImageRequestOptions
, junto con un resizeMode
de PHImageRequestOptionsResizeModeExact
, y luego debe recuperar una imagen recortada. El problema es que no, vuelve como la relación de aspecto original y la imagen completa.
Comprobé que el recorte se creó correctamente en el espacio de coordenadas de la imagen y seguí las instrucciones para usar PHImageRequestOptionsResizeModeExact
, pero al controlador de resultados todavía se le pasará una imagen en la relación de aspecto original. Esto parece ser un error en el marco, y cuando se soluciona, el siguiente código debería funcionar.
- (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;
}];
}
Todo lo que puedo sugerir es que si tienes este problema, ¡ archiva un radar con Apple para solicitar que lo arreglen!