更新
使用iPhone OS 3.0+,整个UIImagePickerController API已更改。应该考虑这个问题和答案2.2。遗留代码。
使用UIImagePickerController并允许编辑图像时。 iPhone允许用户调整图像大小并平移图像。但是,编辑图像的最大尺寸上限为320x320。
作为一个例子,我拍了一张iPhone屏幕截图并将其放在照片库中,这是一张480x320 png。当我使用UIImagePickerController选择该图像时,即使我没有缩放或平移图像,它也会在从UIImagePickerController返回之前被裁剪为320x320。但是,如果我关闭编辑,图像将返回正确的480x320尺寸。
我的理论: 非常巧妙地,iPhone显示2个覆盖图像的非标准半透明工具条。这些工具栏在照片上留下了一个无害的320x320“窗口”。在我看来,这个窗口有效地剪辑了底层照片。
注意: 回调还返回一个包含原始图像和剪切矩形的编辑字典,但当然矩形也是最大320x320。
有关如何缩放和平移大于320x320的图像的任何想法?
一些代码:
- (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];
}
答案 0 :(得分:7)
正如克雷格所说,这是开发论坛和苹果定期讨论板的一个问题。不过,我确实找到了解决办法。我正在使用以下代码:
这包括您需要的大部分内容,并负责所有相机方向问题。我添加了以下内容,它将包含编辑信息,并使用它来获取原始裁剪矩形:
- (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;
}
我将dev论坛帖子中的回调方法更新为以下内容:
- (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;
}
答案 1 :(得分:5)
我一定来不及回答这个问题,但我有更好的方法来完成这项工作。
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;
}
它仅使用相对的CropRect裁剪原始图像, 虽然这种方法不会缩放图像,但它对我来说简短而甜蜜。 仅供参考:)
答案 2 :(得分:2)
使用iPhone OS 3.0+,整体 UIImagePickerController API有 改变。这个问答 应该考虑2.2。遗留代码。
尽管你发出了警告,我花了一个宝贵的开发时间才意识到iOS 3.0+给了我们UIImagePickerControllerEditedImage,这使得处理手动裁剪到用户的捏合/缩放并处理不必要的方向。
这是因为任何人仍在使用UIImagePickerControllerOriginalImage并试图找出如何通过UIImagePickerControllerCropRect等应用裁剪的最佳方式。不再需要。
答案 3 :(得分:1)
这似乎是SDK的障碍,至少在图像选择器上将allowsImageEditing设置为TRUE时。 Apple论坛中有关于此主题的讨论:
答案 4 :(得分:1)
迟到总比没有好:这是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; }
答案 5 :(得分:0)
我写了一个提供全分辨率裁剪的category on UIImage。最简单的安装方法是CocoaPods,方法是将UIImage-ImagePickerCrop添加到podfile中。
#import <UIImage+ImagePickerCrop.h>
...
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info {
[self dismissViewControllerAnimated:YES completion:nil];
UIImage *croppedImage = [UIImage croppedImageWithImagePickerInfo:info];
...
}