在我写的iOS应用程序中,我处理PNG因为我处理alpha通道。出于某种原因,我可以将PNG加载到我的imageView
中,但是当需要将图像从我的应用程序中复制到PasteBoard上或将图像保存到我的相机胶卷时,图像会旋转90度。
我在这里搜索过,我学到的一件事是,如果我使用JPEG,由于EXIF信息,我不会有这个问题(听起来)。
我的应用程序具有完整的复制/粘贴功能,这里是踢球者(我会分步编写,以便更容易理解):
我100%确定我的复制和粘贴代码不是错误的,因为如果我回到上面的第2步,然后点击“保存”,照片会保存到我的库中,但它会旋转90度!
更奇怪的是,它似乎可以正常使用从互联网上下载的图像,但是我手动用手机拍摄的图像非常受欢迎。有些它有效,有些则没有......
有人对此有任何想法吗?我可以使用任何可能的工作吗?我对代码非常有信心,因为它适用于大约75%的图像。我可以根据要求发布代码。
答案 0 :(得分:26)
对于那些需要Swift解决方案的人,请创建UIImage的扩展并添加以下方法:
func correctlyOrientedImage() -> UIImage {
if self.imageOrientation == .up {
return self
}
UIGraphicsBeginImageContextWithOptions(size, false, scale)
draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage ?? self;
}
答案 1 :(得分:14)
如果由于现有的图片imageOrientation
属性而遇到问题,您可以构建一个具有不同方向的其他相同图像,如下所示:
CGImageRef imageRef = [sourceImage CGImage];
UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];
您可能需要尝试在替换图像上设置的方向,可能会根据您开始时的方向进行切换。
还要留意你的记忆力。摄影应用程序经常耗尽,这会使每张照片的存储量翻倍,直到您发布源图像。
答案 2 :(得分:13)
花了几天时间,但由于@Dondragmer发布的答案,我终于想通了。但我想我会发布完整的解决方案。
所以基本上我必须编写一种方法来智能地自动旋转我的图像。缺点是我必须在我的代码中随处调用这种方法,这是一种处理器密集型,特别是在移动设备上工作时,但优点是我可以拍摄图像,复制图像,粘贴图像,保存图像和它们都旋转得很好。这是我最终使用的代码(该方法尚未100%完成,仍然需要编辑内存泄漏,什么不是)。
我最终了解到第一次将图像插入到我的应用程序中(无论是由于用户按下“拍摄图像”,“粘贴图像”或“选择图像”,由于某种原因它只是插入没有自动旋转就好了。此时,我将旋转值存储在名为imageOrientationWhenAddedToScreen
的全局变量中。这使我的生活更轻松,因为当操作图像并将图像保存到程序之外时,我只是检查了这个缓存的全局变量,并确定是否需要正确旋转图像。
- (UIImage*) rotateImageAppropriately:(UIImage*) imageToRotate {
//This method will properly rotate our image, we need to make sure that
//We call this method everywhere pretty much...
CGImageRef imageRef = [imageToRotate CGImage];
UIImage* properlyRotatedImage;
if (imageOrientationWhenAddedToScreen == 0) {
//Don't rotate the image
properlyRotatedImage = imageToRotate;
} else if (imageOrientationWhenAddedToScreen == 3) {
//We need to rotate the image back to a 3
properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:3];
} else if (imageOrientationWhenAddedToScreen == 1) {
//We need to rotate the image back to a 1
properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:1];
}
return properlyRotatedImage;
}
我仍然不能100%肯定为什么Apple有这种奇怪的图像旋转行为(试试这个......拿起你的手机并将其翻转并拍照,你会注意到最后的图片是正确的 - 也许这就是为什么Apple有这种功能?)。
我知道我花了很多时间搞清楚这一点,所以我希望它可以帮助其他人!
答案 3 :(得分:13)
这种“奇怪的旋转”行为真的不是那么奇怪。它很聪明,聪明的我指的是内存效率。旋转iOS设备时,相机硬件随之旋转。当您拍摄照片时,将拍摄照片,但相机是朝向的。 UIImage能够使用这些原始图片数据而无需复制,只需跟踪它应该处于的方向。当您使用UIImagePNGRepresentation()
时,您将丢失此方向数据并获取基础图像的PNG,因为它是由相机。要修复此问题而不是旋转,您可以告诉原始图像将自己绘制到新的上下文中,并从该上下文中获取正确定向的UIImage
。
UIImage *image = ...;
//Have the image draw itself in the correct orientation if necessary
if(!(image.imageOrientation == UIImageOrientationUp ||
image.imageOrientation == UIImageOrientationUpMirrored))
{
CGSize imgsize = image.size;
UIGraphicsBeginImageContext(imgsize);
[image drawInRect:CGRectMake(0.0, 0.0, imgsize.width, imgsize.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
NSData *png = UIImagePNGRepresentation(image);
答案 4 :(得分:0)
以下是实现这一目标的另一种方法:
@IBAction func rightRotateAction(sender: AnyObject) {
let imgToRotate = CIImage(CGImage: sourceImageView.image?.CGImage)
let transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
let rotatedImage = imgToRotate.imageByApplyingTransform(transform)
let extent = rotatedImage.extent()
let contex = CIContext(options: [kCIContextUseSoftwareRenderer: false])
let cgImage = contex.createCGImage(rotatedImage, fromRect: extent)
adjustedImage = UIImage(CGImage: cgImage)!
UIView.transitionWithView(sourceImageView, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
self.sourceImageView.image = self.adjustedImage
}, completion: nil)
}
答案 5 :(得分:0)
您可以使用图像I / O将PNG图像保存到文件(或NSMutableData
)相对于图像的方向。在下面的示例中,我将PNG图像保存到path
的文件中。
- (BOOL)savePngFile:(UIImage *)image toPath:(NSString *)path {
NSData *data = UIImagePNGRepresentation(image);
int exifOrientation = [UIImage cc_iOSOrientationToExifOrientation:image.imageOrientation];
NSDictionary *metadata = @{(__bridge id)kCGImagePropertyOrientation:@(exifOrientation)};
NSURL *url = [NSURL fileURLWithPath:path];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
if (!source) {
return NO;
}
CFStringRef UTI = CGImageSourceGetType(source);
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, UTI, 1, NULL);
if (!destination) {
CFRelease(source);
return NO;
}
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata);
BOOL success = CGImageDestinationFinalize(destination);
CFRelease(destination);
CFRelease(source);
return success;
}
cc_iOSOrientationToExifOrientation:
是UIImage
类别的方法。
+ (int)cc_iOSOrientationToExifOrientation:(UIImageOrientation)iOSOrientation {
int exifOrientation = -1;
switch (iOSOrientation) {
case UIImageOrientationUp:
exifOrientation = 1;
break;
case UIImageOrientationDown:
exifOrientation = 3;
break;
case UIImageOrientationLeft:
exifOrientation = 8;
break;
case UIImageOrientationRight:
exifOrientation = 6;
break;
case UIImageOrientationUpMirrored:
exifOrientation = 2;
break;
case UIImageOrientationDownMirrored:
exifOrientation = 4;
break;
case UIImageOrientationLeftMirrored:
exifOrientation = 5;
break;
case UIImageOrientationRightMirrored:
exifOrientation = 7;
break;
default:
exifOrientation = -1;
}
return exifOrientation;
}
您也可以使用NSData
将图片保存到CGImageDestinationCreateWithData
,然后在NSMutableData
中传递NSURL
代替CGImageDestinationCreateWithURL
。