25

我想我通过运行一个将 Base SDK 设置为 iOS 6.1 的应用程序在最新的 iOS 7 中发现了一个错误(可能甚至更低的版本,还没有测试过)

我的照片库中有这张图片:http: //i.imgur.com/7KUIGLt.jpg

我通过以下方式呈现 UIImagePickerController:

UIImagePickerController *vc = [[UIImagePickerController alloc] init];
vc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
vc.delegate = self;
vc.allowsEditing = YES;
[self presentViewController:vc animated:YES completion:nil];

我将选择的图像保存到我的桌面(我在模拟器上运行它,但这也适用于设备)

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    UIImage* outputImage = [info objectForKey:UIImagePickerControllerEditedImage];
    if (outputImage == nil) {
        outputImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    }
    NSData *d = UIImagePNGRepresentation(outputImage);
    [d writeToFile:@"/Users/Admin/Desktop/test.png" atomically:YES];
    [self dismissViewControllerAnimated:YES completion:nil];
}

这是生成的图像: 在此处输入图像描述

注意右边的大黑条。这是什么原因造成的?

要重现这一点,您需要:

  • IOS 7
  • 将 Base SDK 设置为 6.1 的应用程序(也许甚至更低的 SDK,我还没有尝试过)
  • iPhone 5/5c/5s
  • 仅适用于使用 iPhone 5/5c/5s 相机拍摄的照片(您可以使用我上面链接的原始图像进行测试)

注意:为了清楚起见,黑条是实际图像的一部分。您在此处看到的图像不是 UIImageView 的屏幕截图,而是保存到磁盘并上传到此处的实际图像...

4

4 回答 4

22

您的问题是“是什么原因造成的?” 因此,我将专注于这一点,而不是提供解决方法。这绝对是 iOS 7 中处理较低基础 SDK 中编辑图像的错误。我们还可以排除 XCode 5 和 Base SDK 6.1 导致此问题,因为我在 iOS 7 模拟器上运行的 XCode 4.6.3 和 6.1 SDK 遇到了同样的问题。

问题的根源是SDK计算的CropRect值不对。如果你打印出info NSDictionaryfromimagePickerController:didFinishPickingMediaWithInfo你会看到:

iOS 7 运行任何低于 7 的 SDK,我们将获得:

UIImagePickerControllerCropRect = "NSRect: { {154, 495} , {1705, 1705}}";

在使用他们的 SDK 运行 iOS 6 或 5 时,我们会:

UIImagePickerControllerCropRect = "NSRect: {{ 0, 149 }, {1704, 1705}}";

您可能会说,嗯,这些 y 值也在 SDK 之间发生变化。好吧,是的,如果您将图片一直向下滑动并选择它,您还会在图片底部看到一个黑条。

在此处输入图像描述

建议的解决方案:

  1. 在此处向 Apple 提交错误报告……做到了!

  2. 不要使用UIImagePickerControllerEditedImage并拍摄原始照片。

  3. 计算并自己进行裁剪。

  4. 使用第 3 方裁剪库,例如PEPhotoCropEditorSSPhotoCropperViewController


编辑 - 答案的粉丝添加的非常简单的解决方案!

令人惊讶的是,自己裁剪它可以如此简单和优雅:

{
// There is a bug in iOS. When using ALBUM, you must crop it yourself:

fromAlbum = [info objectForKey:UIImagePickerControllerOriginalImage];
fromAlbum = [fromAlbum fixOrientation];

CGRect crop = [[info valueForKey:@"UIImagePickerControllerCropRect"] CGRectValue];
fromAlbum = [self ordinaryCrop:fromAlbum toRect:crop];
}

这是整个例程 normalCrop:toRect:

-(UIImage *)ordinaryCrop:(UIImage *)imageToCrop toRect:(CGRect)cropRect
 {
 CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], cropRect);
 UIImage *cropped = [UIImage imageWithCGImage:imageRef];
 CGImageRelease(imageRef);
 return cropped;
 }

现在正如 Jesse 指出的那样,正确旋转图像至关重要。Anomie 的这段绝对令人难以置信的代码完成了这项工作:

上传后iOS UIImagePickerController结果图像方向

修复 UIImage 方向 .. UIImage+fixOrientation.h

就是这么简单,希望对某人有所帮助。再次感谢这里无价的答案。

于 2013-10-20T16:10:25.997 回答
4

我相信我们最终解决了类似的问题,从不直接要求编辑过的图像;询问原始图像和裁剪信息 ( UIImagePickerControllerCropRect) 并自己进行裁剪。请注意,如果您自己进行裁剪,则需要担心源图像中的旋转。

您可能会发现此问题中的答案有助于实施此解决方法。

于 2013-10-18T13:56:25.310 回答
-1

尝试以编程方式查找和更改模式(Aspect Fit、Aspect Fill、Scale to Fill)。

于 2013-10-16T11:43:39.117 回答
-2

我正在尝试重现此错误。并且在模拟器、64 位模拟器和 iPad mini 上没有运气。全部运行 iOS 7.0。

我把你的代码放在我的应用程序中:

UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
if (!image)
    image = [info valueForKey:UIImagePickerControllerOriginalImage];

// Save photo to custom album only if taken by camera
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera)
    [ALAssetsLibrary saveImageToCustomAlbum:image
                                   assetURL:[info valueForKey:UIImagePickerControllerReferenceURL]];


NSData *d = UIImagePNGRepresentation(image);
[d writeToFile:@"/Volumes/Alko/Temp/test.png" atomically:YES];

UIImageWriteToSavedPhotosAlbum(image, nil, NULL, nil);

[self setImage:image];
[self dismissPicker:picker];
[self photoPickerDidFinish];

并且使用从http://i.imgur.com/7KUIGLt.jpg下载的图像可以正常工作。我认为您的应用程序有问题,而不是 UIImagePickerController。

于 2013-10-19T07:05:26.673 回答