-
Star
(102)
You must be signed in to star a gist -
Fork
(17)
You must be signed in to fork a gist
-
-
Save schickling/b5d86cb070130f80bb40 to your computer and use it in GitHub Desktop.
extension UIImage { | |
func fixedOrientation() -> UIImage { | |
if imageOrientation == UIImageOrientation.Up { | |
return self | |
} | |
var transform: CGAffineTransform = CGAffineTransformIdentity | |
switch imageOrientation { | |
case UIImageOrientation.Down, UIImageOrientation.DownMirrored: | |
transform = CGAffineTransformTranslate(transform, size.width, size.height) | |
transform = CGAffineTransformRotate(transform, CGFloat(M_PI)) | |
break | |
case UIImageOrientation.Left, UIImageOrientation.LeftMirrored: | |
transform = CGAffineTransformTranslate(transform, size.width, 0) | |
transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2)) | |
break | |
case UIImageOrientation.Right, UIImageOrientation.RightMirrored: | |
transform = CGAffineTransformTranslate(transform, 0, size.height) | |
transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2)) | |
break | |
case UIImageOrientation.Up, UIImageOrientation.UpMirrored: | |
break | |
} | |
switch imageOrientation { | |
case UIImageOrientation.UpMirrored, UIImageOrientation.DownMirrored: | |
CGAffineTransformTranslate(transform, size.width, 0) | |
CGAffineTransformScale(transform, -1, 1) | |
break | |
case UIImageOrientation.LeftMirrored, UIImageOrientation.RightMirrored: | |
CGAffineTransformTranslate(transform, size.height, 0) | |
CGAffineTransformScale(transform, -1, 1) | |
case UIImageOrientation.Up, UIImageOrientation.Down, UIImageOrientation.Left, UIImageOrientation.Right: | |
break | |
} | |
let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(size.width), Int(size.height), CGImageGetBitsPerComponent(CGImage), 0, CGImageGetColorSpace(CGImage), CGImageAlphaInfo.PremultipliedLast.rawValue)! | |
CGContextConcatCTM(ctx, transform) | |
switch imageOrientation { | |
case UIImageOrientation.Left, UIImageOrientation.LeftMirrored, UIImageOrientation.Right, UIImageOrientation.RightMirrored: | |
CGContextDrawImage(ctx, CGRectMake(0, 0, size.height, size.width), CGImage) | |
break | |
default: | |
CGContextDrawImage(ctx, CGRectMake(0, 0, size.width, size.height), CGImage) | |
break | |
} | |
let cgImage: CGImageRef = CGBitmapContextCreateImage(ctx)! | |
return UIImage(CGImage: cgImage) | |
} | |
} |
I believe those transform around the origin (0, 0) and would thus flip/rotate your image to be outside the box. if you try it with an angle of around 45° you’ll see how it would break.
I believe those transform around the origin (0, 0) and would thus flip/rotate your image to be outside the box. if you try it with an angle of around 45° you’ll see how it would break.
Thanks!
Hi, here's my solution. It relies on iOS's
UIImage
handing of the orientation. So an "xyz" orientated image is rendered (using it's orientation info) onto anup
orientated canvas.
⚠️ self.draw
ofUIImage
, notCGImage
.extension UIImage { /// `Re-orientate` the image to `up`. /// func normalizedImage() -> UIImage? { if self.imageOrientation == .up { return self } else { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) defer { UIGraphicsEndImageContext() } self.draw(in: CGRect(origin: .zero, size: self.size)) return UIGraphicsGetImageFromCurrentImageContext() } } }
UIGraphicsBeginImageContextWithOptions
was deprecated, use UIGraphicsImageRenderer
instead.
extension UIImage {
func normalizedImage() -> UIImage {
guard imageOrientation != .up else {
return self
}
return UIGraphicsImageRenderer(size: size, format: .preferred())
.image {
draw(in: $0.format.bounds)
}
}
}
@ChrisXu thank you :)
What should i pass for this label?)

@Sam-Spencer thank you, it helped. I used your version eve though there was newer which was reported to have no memory leak, because it's the most recent which works as is. The last one requires me to pass something for the for
labels.
In my case, your solution was not enough. I was having cropped image saved in some broken cropping.
Here how I used it:
func cropImage(_ image: UIImage, x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> UIImage? {
let rectToCrop = CGRect(x: x, y: y, width: width, height: height)
let rect = CGRect(x: rectToCrop.origin.x, y: rectToCrop.origin.y, width: rectToCrop.width, height: rectToCrop.height)
guard let cropped = image.fixedOrientation()?.cgImage?.cropping(to: rect) else {
return nil
}
return UIImage(cgImage: cropped, scale: image.scale, orientation: .up)
}
And saving like
UIImageWriteToSavedPhotosAlbum(imageCropped, nil, nil, nil)
My problem was that i forgot to change image.imageOrientation
to .up
in the last line of the cropping function
UIImage(cgImage: cropped, scale: image.scale, orientation: .up)
Could someone explain me why we need
transform.translatedBy
?Wouldn't only
.rotated(by...
and.scaledBy(...
(for flipped images) do it? 🤔