[英]UIImagePNGRepresentation issues? / Images rotated by 90 degrees
我想从UIImagePickerController加载图像,然后将选定的照片保存到我的应用程序的文档目录中。
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *data1 = UIImagePNGRepresentation(image);
NSString *fileName = "1.png";
NSString *path = //get Document path, then add fileName
BOOL succ = [data1 writeToFile:path atomically:YES];
但是在我将图像保存到我的文档后,我发现,图像旋转了90度,然后我将方法UIImagePNGRepresentation更改为UIImageJPEGRepresentation,这次没关系,有谁知道问题是什么?
我遇到了同样的问题并且弄清楚了原因:从iOS 4.0开始,当相机拍照时它不会在保存之前旋转它,它只是在JPEG的EXIF数据中设置一个旋转标记。
如果将UIImage保存为JPEG,则会设置旋转标志。
PNG不支持旋转标志,因此如果将UIImage保存为PNG,它将被错误地旋转,并且没有设置标志来修复它。 因此,如果你想要PNG,你必须自己旋转它们。
我会称这是PNG保存功能中的一个错误,但这只是一个意见(他们至少应该警告你这个)。
试试这个:
func rotateImage(image: UIImage) -> UIImage {
if (image.imageOrientation == UIImageOrientation.Up ) {
return image
}
UIGraphicsBeginImageContext(image.size)
image.drawInRect(CGRect(origin: CGPoint.zero, size: image.size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy
}
我用以下代码解决了这个问题。
- (UIImage *)scaleAndRotateImage:(UIImage *)image
{
int kMaxResolution = 640;
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = bounds.size.width / ratio;
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = bounds.size.height * ratio;
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
以下swift函数可以解决问题。
var rotatedCopy: UIImage {
if (imageOrientation == UIImageOrientation.Up) {
return self
}
UIGraphicsBeginImageContext(size)
drawInRect(CGRect(origin: CGPoint.zeroPoint, size: size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy
}
是的,就是这么简单,因为drawInRect
函数会考虑图像方向。
我已经创建了这个UIImage扩展来解决UIImagePNGRepresentation的这个问题,基于这个响应 。 所以我建议用这个类func UIImage.PNGRepresentation(img: UIImage)
代替UIKit func UIImagePNGRepresentation。
Swift 3代码:
// MyUIImage.swift
// MyEasyMovie-Public-App
//
// Created by Ahmed Zahraz on 19/12/2016.
// Copyright © 2016 AhmedZahraz. All rights reserved.
import Foundation
import UIKit
extension UIImage {
public class func PNGRepresentation(_ img: UIImage) -> Data? {
// No-op if the orientation is already correct
if (img.imageOrientation == UIImageOrientation.up) {
return UIImagePNGRepresentation(img);
}
// We need to calculate the proper transformation to make the image upright.
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
var transform:CGAffineTransform = CGAffineTransform.identity
if (img.imageOrientation == UIImageOrientation.down
|| img.imageOrientation == UIImageOrientation.downMirrored) {
transform = transform.translatedBy(x: img.size.width, y: img.size.height)
transform = transform.rotated(by: CGFloat(M_PI))
}
if (img.imageOrientation == UIImageOrientation.left
|| img.imageOrientation == UIImageOrientation.leftMirrored) {
transform = transform.translatedBy(x: img.size.width, y: 0)
transform = transform.rotated(by: CGFloat(M_PI_2))
}
if (img.imageOrientation == UIImageOrientation.right
|| img.imageOrientation == UIImageOrientation.rightMirrored) {
transform = transform.translatedBy(x: 0, y: img.size.height);
transform = transform.rotated(by: CGFloat(-M_PI_2));
}
if (img.imageOrientation == UIImageOrientation.upMirrored
|| img.imageOrientation == UIImageOrientation.downMirrored) {
transform = transform.translatedBy(x: img.size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
}
if (img.imageOrientation == UIImageOrientation.leftMirrored
|| img.imageOrientation == UIImageOrientation.rightMirrored) {
transform = transform.translatedBy(x: img.size.height, y: 0);
transform = transform.scaledBy(x: -1, y: 1);
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
let ctx:CGContext = CGContext(data: nil, width: Int(img.size.width), height: Int(img.size.height),
bitsPerComponent: img.cgImage!.bitsPerComponent, bytesPerRow: 0,
space: img.cgImage!.colorSpace!,
bitmapInfo: img.cgImage!.bitmapInfo.rawValue)!
ctx.concatenate(transform)
if (img.imageOrientation == UIImageOrientation.left
|| img.imageOrientation == UIImageOrientation.leftMirrored
|| img.imageOrientation == UIImageOrientation.right
|| img.imageOrientation == UIImageOrientation.rightMirrored
) {
ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.height,height:img.size.width))
} else {
ctx.draw(img.cgImage!, in: CGRect(x:0,y:0,width:img.size.width,height:img.size.height))
}
// And now we just create a new UIImage from the drawing context
let cgimg:CGImage = ctx.makeImage()!
let imgEnd:UIImage = UIImage(cgImage: cgimg)
return UIImagePNGRepresentation(imgEnd)
}
}
Stefan的答案更新为Swift 4:
func rotateImage(image: UIImage) -> UIImage {
if (image.imageOrientation == UIImage.Orientation.up) {
return image
}
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(origin: .zero, size: image.size))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy!
}
然后:
var originalImage = yourImage.image!
image = rotateImage(image: originalImage)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.