Skip to content

Instantly share code, notes, and snippets.

@laevandus
Last active November 28, 2020 05:45
Show Gist options
  • Save laevandus/f8c1f854d806c0ea066324e9bf567f8c to your computer and use it in GitHub Desktop.
Save laevandus/f8c1f854d806c0ea066324e9bf567f8c to your computer and use it in GitHub Desktop.
struct ImageScaler {
static func scaleToFill(_ image: UIImage, in targetSize: CGSize, from fromRect: CGRect = .zero) -> UIImage {
let rect = fromRect.isEmpty ? CGRect(origin: .zero, size: image.size) : fromRect
let scaledRect = rect.scaled(toFillSize: targetSize)
return scale(image, fromRect: scaledRect, targetSize: targetSize)
}
private static func scale(_ image: UIImage, fromRect: CGRect = .zero, targetSize: CGSize) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { context in
// UIImage and CGContext coordinates are flipped.
var transform = CGAffineTransform(translationX: 0.0, y: targetSize.height)
transform = transform.scaledBy(x: 1, y: -1)
context.cgContext.concatenate(transform)
// UIImage -> cropped CGImage
let makeCroppedCGImage: (UIImage) -> CGImage? = { image in
guard let cgImage = image.cgImage else { return nil }
guard !fromRect.isEmpty else { return cgImage }
return cgImage.cropping(to: fromRect)
}
if let cgImage = makeCroppedCGImage(image) {
context.cgContext.draw(cgImage, in: CGRect(origin: .zero, size: targetSize))
}
else if let ciImage = image.ciImage {
var transform = CGAffineTransform(translationX: 0.0, y: image.size.height)
transform = transform.scaledBy(x: 1, y: -1)
let adjustedFromRect = fromRect.applying(transform)
let ciContext = CIContext(cgContext: context.cgContext, options: nil)
ciContext.draw(ciImage, in: CGRect(origin: .zero, size: targetSize), from: adjustedFromRect)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment