Skip to content

Instantly share code, notes, and snippets.

@yhirano
Created August 2, 2019 07:15
Show Gist options
  • Select an option

  • Save yhirano/83c5f709b71559e37de0a051040245b9 to your computer and use it in GitHub Desktop.

Select an option

Save yhirano/83c5f709b71559e37de0a051040245b9 to your computer and use it in GitHub Desktop.
import UIKit
extension UIImage {
func fixedOrientation() -> UIImage? {
guard imageOrientation != UIImage.Orientation.up else {
return self
}
guard let cgImage = self.cgImage else {
return nil
}
guard let colorSpace = cgImage.colorSpace,
let ctx = CGContext(data: nil,
width: Int(size.width),
height: Int(size.height),
bitsPerComponent: cgImage.bitsPerComponent,
bytesPerRow: 0,
space: colorSpace,
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
return nil
}
var transform: CGAffineTransform = CGAffineTransform.identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2.0)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat.pi / -2.0)
case .up, .upMirrored:
break
}
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .up, .down, .left, .right:
break
}
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
guard let newCGImage = ctx.makeImage() else { return nil }
return UIImage.init(cgImage: newCGImage, scale: 1, orientation: .up)
}
func crop(to size: CGSize) -> UIImage? {
guard let image = fixedOrientation() else { return nil }
guard let cgImage = image.cgImage else { return nil }
let contextImage = UIImage(cgImage: cgImage)
let contextSize = contextImage.size
var positionX: CGFloat = 0.0
var positionY: CGFloat = 0.0
let cropAspect: CGFloat = size.width / size.height
var cropWidth: CGFloat = size.width
var cropHeight: CGFloat = size.height
if size.width > size.height { // Landscape
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
positionY = (contextSize.height - cropHeight) / 2
} else if size.width < size.height { // Portrait
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
positionX = (contextSize.width - cropWidth) / 2
} else { // Square
if contextSize.width >= contextSize.height { // Square on landscape (or square)
cropHeight = contextSize.height
cropWidth = contextSize.height * cropAspect
positionX = (contextSize.width - cropWidth) / 2
} else { // Square on portrait
cropWidth = contextSize.width
cropHeight = contextSize.width / cropAspect
positionY = (contextSize.height - cropHeight) / 2
}
}
let rect = CGRect(x: positionX, y: positionY, width: cropWidth, height: cropHeight)
// Create bitmap image from context using the rect
let imageRef = contextImage.cgImage!.cropping(to: rect)!
// Create a new image based on the imageRef and rotate back to the original orientation
let cropped = UIImage(cgImage: imageRef, scale: image.scale, orientation: image.imageOrientation)
cropped.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
return cropped
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment