UIImagePickerController edição permitidas fechaduras UIImage ao tamanho máximo de 320x320
-
05-09-2019 - |
Pergunta
Update:
Com o iPhone OS 3.0 ou superior, todo o UIImagePickerController API mudou. Esta pergunta e resposta deve ser considerado 2.2. legado código.
Ao usar o UIImagePickerController e você permitir a edição da imagem. O iPhone permite que o usuário redimensionar e deslocar a imagem. No entanto, o tamanho máximo de uma imagem editada é limitado a 320x320.
Como um exemplo, eu levei uma captura de tela do iPhone e colocou-a na biblioteca de fotos, que é um png 480x320. Quando eu uso uma UIImagePickerController para selecionar a imagem, mesmo se eu não escala ou deslocar a imagem, ela é cortada para 320x320 antes de ser devolvido a partir do UIImagePickerController. No entanto, se eu virar a edição off, a imagem é devolvida a 480x320 tamanho adequado.
A minha teoria: Muito sutilmente, o iPhone exibe 2 barras de ferramentas translúcido fora do padrão que se sobrepõem sobre a imagem. Essas barras de ferramentas deixar uma inócua 320x320 "janela" em cima da foto. Parece-me que esta janela efetivamente clips foto subjacente.
Nota: O retorno de chamada também retorna um dicionário de edição com a imagem original e o rect recorte, mas é claro que o rect é também max 320x320.
Algumas ideias sobre como permitir que imagens maiores que 320x320 para ser escalado e garimpou?
Alguns código:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
self.myImageView.userInteractionEnabled=YES;
CGRect imageFrame = myImageView.frame;
CGPoint imageCenter = myImageView.center;
imageFrame.size = img.size;
myImageView.frame = imageFrame;
self.myImageView.image = img;
myImageView.center = imageCenter;
[self dismissModalViewControllerAnimated:YES];
[self performSelector:@selector(hideToolBars) withObject:nil afterDelay:2.0];
}
Solução
Como Craig disse, este é um problema nos fóruns dev e maçãs do conselho discussão regular. Eu, entretanto, encontrar uma maneira de contornar isso. Estou usando um pouco de código de:
Isto inclui a maioria do que você precisa, e cuida de todas as questões de orientação da câmera. Eu adicionei o seguinte, que terá na informação edição e usá-lo para obter o rect recorte original com esta adição:
- (UIImage*)scaleImage:(UIImage*)anImage withEditingInfo:(NSDictionary*)editInfo{
UIImage *newImage;
UIImage *originalImage = [editInfo valueForKey:@"UIImagePickerControllerOriginalImage"];
CGSize originalSize = CGSizeMake(originalImage.size.width, originalImage.size.height);
CGRect originalFrame;
originalFrame.origin = CGPointMake(0,0);
originalFrame.size = originalSize;
CGRect croppingRect = [[editInfo valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue];
CGSize croppingRectSize = CGSizeMake(croppingRect.size.width, croppingRect.size.height);
CGSize croppedScaledImageSize = anImage.size;
float scaledBarClipHeight = 80;
CGSize scaledImageSize;
float scale;
if(!CGSizeEqualToSize(croppedScaledImageSize, originalSize)){
scale = croppedScaledImageSize.width/croppingRectSize.width;
float barClipHeight = scaledBarClipHeight/scale;
croppingRect.origin.y -= barClipHeight;
croppingRect.size.height += (2*barClipHeight);
if(croppingRect.origin.y<=0){
croppingRect.size.height += croppingRect.origin.y;
croppingRect.origin.y=0;
}
if(croppingRect.size.height > (originalSize.height - croppingRect.origin.y)){
croppingRect.size.height = (originalSize.height - croppingRect.origin.y);
}
scaledImageSize = croppingRect.size;
scaledImageSize.width *= scale;
scaledImageSize.height *= scale;
newImage = [self cropImage:originalImage to:croppingRect andScaleTo:scaledImageSize];
}else{
newImage = originalImage;
}
return newImage;
}
Eu atualizei o método de chamada de volta a partir do dev fóruns correio para o seguinte:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
[self dismissModalViewControllerAnimated:YES];
self.myImageView.userInteractionEnabled=YES;
CGRect imageFrame = myImageView.frame;
CGPoint imageCenter = myImageView.center;
UIImage *croppedImage;
NSMutableDictionary *imageDescriptor = [editInfo mutableCopy];
// CGFloat scaleSize = 400.0f;
CGFloat scaleSize = 640.0f;
switch ([picker sourceType]) {
//done
case UIImagePickerControllerSourceTypePhotoLibrary:
croppedImage = [self scaleImage:img withEditingInfo:editInfo];
[imageDescriptor setObject:croppedImage forKey:@"croppedImage"];
break;
case UIImagePickerControllerSourceTypeCamera: {
UIImageOrientation originalOrientation = [[editInfo objectForKey:UIImagePickerControllerOriginalImage] imageOrientation];
if (originalOrientation != UIImageOrientationUp) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CGRect origRect;
[[editInfo objectForKey:UIImagePickerControllerCropRect] getValue:&origRect];
UIImage *rotatedImage = straightenAndScaleImage([editInfo objectForKey:UIImagePickerControllerOriginalImage], scaleSize);
CGFloat scale = scaleSize/1600.0f;
origRect.origin.x *= scale;
origRect.origin.y *= scale;
origRect.size.width *= scale;
origRect.size.height *= scale;
croppedImage = [self cropImage:rotatedImage to:origRect andScaleTo:CGSizeMake(320, 480)];
[imageDescriptor setObject:croppedImage forKey:@"croppedImage"];
[pool drain];
}
else {
croppedImage = [self scaleImage:img withEditingInfo:editInfo];
[imageDescriptor setObject:croppedImage forKey:@"croppedImage"];
}
}
break;
case UIImagePickerControllerSourceTypeSavedPhotosAlbum: {
UIImageOrientation originalOrientation = [[editInfo objectForKey:UIImagePickerControllerOriginalImage] imageOrientation];
if (originalOrientation != UIImageOrientationUp) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CGRect origRect;
[[editInfo objectForKey:UIImagePickerControllerCropRect] getValue:&origRect];
UIImage *rotatedImage = straightenAndScaleImage([editInfo objectForKey:UIImagePickerControllerOriginalImage], scaleSize);
CGFloat scale = scaleSize/640.0f;
origRect.origin.x *= scale;
origRect.origin.y *= scale;
origRect.size.width *= scale;
origRect.size.height *= scale;
croppedImage = [self cropImage:rotatedImage to:origRect andScaleTo:CGSizeMake(320, 480)];
[imageDescriptor setObject:croppedImage forKey:@"croppedImage"];
[pool drain];
}
else {
croppedImage = [self scaleImage:img withEditingInfo:editInfo];
[imageDescriptor setObject:croppedImage forKey:@"croppedImage"];
}
}
break;
default:
break;
}
imageFrame.size = croppedImage.size;
myImageView.frame = imageFrame;
myImageView.image = [imageDescriptor objectForKey:@"croppedImage"];
myImageView.center = imageCenter;
}
Outras dicas
Eu devo ser tarde demais para responder a esta pergunta, mas eu tenho uma maneira melhor de fazer este trabalho.
static inline double radians (double degrees) {return degrees * M_PI/180;}
+(UIImage*)editedImageFromMediaWithInfo:(NSDictionary*)info{
if(![info objectForKey:UIImagePickerControllerCropRect])return nil;
if(![info objectForKey:UIImagePickerControllerOriginalImage])return nil;
UIImage *originalImage=[info objectForKey:UIImagePickerControllerOriginalImage];
CGRect rect=[[info objectForKey:UIImagePickerControllerCropRect] CGRectValue];
CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
CGContextRef bitmap = CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
if (originalImage.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -rect.size.height);
} else if (originalImage.imageOrientation == UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -rect.size.width, 0);
} else if (originalImage.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (originalImage.imageOrientation == UIImageOrientationDown) {
CGContextTranslateCTM (bitmap, rect.size.width, rect.size.height);
CGContextRotateCTM (bitmap, radians(-180.));
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, rect.size.width, rect.size.height), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage *resultImage=[UIImage imageWithCGImage:ref];
CGImageRelease(imageRef);
CGContextRelease(bitmap);
CGImageRelease(ref);
return resultImage;
}
Ela só corta a imagem original com o CropRect relativa, embora este dosen't método dimensionar a imagem, mas é curto e doce para mim. Apenas para referência:)
Com o iPhone OS 3.0 ou superior, o todo UIImagePickerController API tem mudado. Esta pergunta e resposta deve ser considerado 2.2. legado código.
Apesar de seu aviso, ele me levou um hora dev preciosa para perceber iOS 3.0+ nos deu UIImagePickerControllerEditedImage o que torna a lidar com a colheita manualmente para pitada do usuário / zoom e lidar com orientação desnecessário.
Este é o caso de alguém ainda estava usando UIImagePickerControllerOriginalImage e tentando descobrir a melhor forma de aplicar corte via UIImagePickerControllerCropRect, etc. Não é mais necessário.
Este parece ser um obstáculo do SDK, pelo menos, ao definir o allowsImageEditing como TRUE no seletor de imagem. Há um pouco de discussão sobre este tema nos fóruns da Apple aqui:
Melhor tarde do que nunca: aqui é a fonte para a função orientationTransformForImage
CGAffineTransform orientationTransformForImage(UIImage *image, CGSize *newSize) { CGImageRef img = [image CGImage]; CGFloat width = CGImageGetWidth(img); CGFloat height = CGImageGetHeight(img); CGSize size = CGSizeMake(width, height); CGAffineTransform transform = CGAffineTransformIdentity; CGFloat origHeight = size.height; UIImageOrientation orient = image.imageOrientation; switch(orient) { /* EXIF 1 to 8 */ case UIImageOrientationUp: break; case UIImageOrientationUpMirrored: transform = CGAffineTransformMakeTranslation(width, 0.0f); transform = CGAffineTransformScale(transform, -1.0f, 1.0f); break; case UIImageOrientationDown: transform = CGAffineTransformMakeTranslation(width, height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationDownMirrored: transform = CGAffineTransformMakeTranslation(0.0f, height); transform = CGAffineTransformScale(transform, 1.0f, -1.0f); break; case UIImageOrientationLeftMirrored: size.height = size.width; size.width = origHeight; transform = CGAffineTransformMakeTranslation(height, width); transform = CGAffineTransformScale(transform, -1.0f, 1.0f); transform = CGAffineTransformRotate(transform, 3.0f * M_PI / 2.0f); break; case UIImageOrientationLeft: size.height = size.width; size.width = origHeight; transform = CGAffineTransformMakeTranslation(0.0f, width); transform = CGAffineTransformRotate(transform, 3.0f * M_PI / 2.0f); break; case UIImageOrientationRightMirrored: size.height = size.width; size.width = origHeight; transform = CGAffineTransformMakeScale(-1.0f, 1.0f); transform = CGAffineTransformRotate(transform, M_PI / 2.0f); break; case UIImageOrientationRight: size.height = size.width; size.width = origHeight; transform = CGAffineTransformMakeTranslation(height, 0.0f); transform = CGAffineTransformRotate(transform, M_PI / 2.0f); break; default: ; } *newSize = size; return transform; }
Eu escrevi uma categoria em UIImage que fornece uma cultura de resolução completa. A maneira mais fácil de instalar está com CocoaPods , adicionando UIImage-ImagePickerCrop ao seu podfile.
#import <UIImage+ImagePickerCrop.h>
...
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:nil];
UIImage *croppedImage = [UIImage croppedImageWithImagePickerInfo:info];
...
}