如何加载图像并根据它的方向 exif 数据旋转它并使用 UIImageOrientationUp exif 数据保存它
How to load an image and rotate it according to it's orientation exif data and save it with UIImageOrientationUp exif data
如何加载图像并根据它的 orientation
exif
数据旋转它并使用 UIImageOrientationUp
exif 数据(或没有任何方向 exif 数据)保存它,以便软件不处理 exif 方向数据将正确显示图像?
加载图片就这么简单:
UIImage *image = [UIImage imageNamed:@"NameOfImageHere"];
或者如果您有图像数据:
NSData *imageData = [[NSData alloc] init];
UIImage *image = [UIImage imageWithData: imageData];
下面的方法将帮助您使用 UIImage
中的 exif 数据修复方向
- (UIImage *)imageByFixingOrientation {
UIImage *image = self;
if (image.imageOrientation == UIImageOrientationUp) return image;
CGAffineTransform transform = CGAffineTransformIdentity;
switch (image.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, image.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIImageOrientationUp:
case UIImageOrientationUpMirrored:
break;
}
switch (image.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, image.size.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationUp:
case UIImageOrientationDown:
case UIImageOrientationLeft:
case UIImageOrientationRight:
break;
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
CGImageGetBitsPerComponent(image.CGImage), 0,
CGImageGetColorSpace(image.CGImage),
CGImageGetBitmapInfo(image.CGImage));
CGContextConcatCTM(ctx, transform);
switch (image.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
break;
default:
CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage);
break;
}
// And now we just create a new UIImage from the drawing context
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *img = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return img;
}
Swift 4 等效于我以前的 objective-c 方法作为扩展:
extension UIImage {
func byFixingOrientation(andResizingImageToNewSize newSize: CGSize? = nil) -> UIImage {
guard let cgImage = self.cgImage else { return self }
let orientation = self.imageOrientation
guard orientation != .up else { return UIImage(cgImage: cgImage, scale: 1, orientation: .up) }
var transform = CGAffineTransform.identity
let size = newSize ?? self.size
if (orientation == .down || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: .pi)
}
else if (orientation == .left || orientation == .leftMirrored) {
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2)
}
else if (orientation == .right || orientation == .rightMirrored) {
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: -(CGFloat.pi / 2))
}
if (orientation == .upMirrored || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: 0);
transform = transform.scaledBy(x: -1, y: 1)
}
else if (orientation == .leftMirrored || orientation == .rightMirrored) {
transform = transform.translatedBy(x: 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.
guard let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0,
space: cgImage.colorSpace!, bitmapInfo: cgImage.bitmapInfo.rawValue)
else {
return UIImage(cgImage: cgImage, scale: 1, orientation: orientation)
}
ctx.concatenate(transform)
// Create a new UIImage from the drawing context
switch (orientation) {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
return UIImage(cgImage: ctx.makeImage() ?? cgImage, scale: 1, orientation: .up)
}
}
用法-1
let newImage = image.byFixingOrientation()
用法 2(固定方向并将图像调整为新大小)
let newImage = image.byFixingOrientation(andResizingImageToNewSize: CGSize(width: 200, height: 200))
如何加载图像并根据它的 orientation
exif
数据旋转它并使用 UIImageOrientationUp
exif 数据(或没有任何方向 exif 数据)保存它,以便软件不处理 exif 方向数据将正确显示图像?
加载图片就这么简单:
UIImage *image = [UIImage imageNamed:@"NameOfImageHere"];
或者如果您有图像数据:
NSData *imageData = [[NSData alloc] init];
UIImage *image = [UIImage imageWithData: imageData];
下面的方法将帮助您使用 UIImage
- (UIImage *)imageByFixingOrientation {
UIImage *image = self;
if (image.imageOrientation == UIImageOrientationUp) return image;
CGAffineTransform transform = CGAffineTransformIdentity;
switch (image.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, image.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIImageOrientationUp:
case UIImageOrientationUpMirrored:
break;
}
switch (image.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, image.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, image.size.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationUp:
case UIImageOrientationDown:
case UIImageOrientationLeft:
case UIImageOrientationRight:
break;
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
CGImageGetBitsPerComponent(image.CGImage), 0,
CGImageGetColorSpace(image.CGImage),
CGImageGetBitmapInfo(image.CGImage));
CGContextConcatCTM(ctx, transform);
switch (image.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
break;
default:
CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage);
break;
}
// And now we just create a new UIImage from the drawing context
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *img = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return img;
}
Swift 4 等效于我以前的 objective-c 方法作为扩展:
extension UIImage {
func byFixingOrientation(andResizingImageToNewSize newSize: CGSize? = nil) -> UIImage {
guard let cgImage = self.cgImage else { return self }
let orientation = self.imageOrientation
guard orientation != .up else { return UIImage(cgImage: cgImage, scale: 1, orientation: .up) }
var transform = CGAffineTransform.identity
let size = newSize ?? self.size
if (orientation == .down || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: .pi)
}
else if (orientation == .left || orientation == .leftMirrored) {
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2)
}
else if (orientation == .right || orientation == .rightMirrored) {
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: -(CGFloat.pi / 2))
}
if (orientation == .upMirrored || orientation == .downMirrored) {
transform = transform.translatedBy(x: size.width, y: 0);
transform = transform.scaledBy(x: -1, y: 1)
}
else if (orientation == .leftMirrored || orientation == .rightMirrored) {
transform = transform.translatedBy(x: 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.
guard let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0,
space: cgImage.colorSpace!, bitmapInfo: cgImage.bitmapInfo.rawValue)
else {
return UIImage(cgImage: cgImage, scale: 1, orientation: orientation)
}
ctx.concatenate(transform)
// Create a new UIImage from the drawing context
switch (orientation) {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
return UIImage(cgImage: ctx.makeImage() ?? cgImage, scale: 1, orientation: .up)
}
}
用法-1
let newImage = image.byFixingOrientation()
用法 2(固定方向并将图像调整为新大小)
let newImage = image.byFixingOrientation(andResizingImageToNewSize: CGSize(width: 200, height: 200))