He desarrollado una solución definitiva para el escalado de imágenes en Swift.
Se puede utilizar para cambiar el tamaño de la imagen para llenar, llenar aspecto o aspecto encaja tamaño especificado.
Puede alinear la imagen en el centro o cualquiera de los cuatro bordes y cuatro esquinas.
Y también se puede recortar el espacio adicional que se añade si las relaciones de aspecto de la imagen original y tamaño de destino no son iguales.
enum UIImageAlignment {
case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
}
enum UIImageScaleMode {
case Fill,
AspectFill,
AspectFit(UIImageAlignment)
}
extension UIImage {
func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
let preWidthScale = width.map { $0 / size.width }
let preHeightScale = height.map { $0 / size.height }
var widthScale = preWidthScale ?? preHeightScale ?? 1
var heightScale = preHeightScale ?? widthScale
switch scaleMode {
case .AspectFit(_):
let scale = min(widthScale, heightScale)
widthScale = scale
heightScale = scale
case .AspectFill:
let scale = max(widthScale, heightScale)
widthScale = scale
heightScale = scale
default:
break
}
let newWidth = size.width * widthScale
let newHeight = size.height * heightScale
let canvasWidth = trim ? newWidth : (width ?? newWidth)
let canvasHeight = trim ? newHeight : (height ?? newHeight)
UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)
var originX: CGFloat = 0
var originY: CGFloat = 0
switch scaleMode {
case .AspectFit(let alignment):
switch alignment {
case .Center:
originX = (canvasWidth - newWidth) / 2
originY = (canvasHeight - newHeight) / 2
case .Top:
originX = (canvasWidth - newWidth) / 2
case .Left:
originY = (canvasHeight - newHeight) / 2
case .Bottom:
originX = (canvasWidth - newWidth) / 2
originY = canvasHeight - newHeight
case .Right:
originX = canvasWidth - newWidth
originY = (canvasHeight - newHeight) / 2
case .TopLeft:
break
case .TopRight:
originX = canvasWidth - newWidth
case .BottomLeft:
originY = canvasHeight - newHeight
case .BottomRight:
originX = canvasWidth - newWidth
originY = canvasHeight - newHeight
}
default:
break
}
self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Hay ejemplos de la aplicación de esta solución a continuación.
Rectángulo gris es la imagen lugar objetivo será redimensionada a. Círculos azules en rectángulo de color azul claro es la imagen (utilicé círculos porque es fácil de ver cuando se escala sin conservar de aspecto). De color naranja claro marca áreas que serán recortadas si pasa trim: true.
Aspecto encaja antes y después de la escala:

Otro ejemplo de ajuste aspecto :

Aspecto encaja con la parte superior de alineación:

Aspecto de relleno :

llenar :

Solía escalado en mis ejemplos porque es más fácil de demostrar, pero la solución también funciona para la reducción de escala que en la pregunta.
Para la compresión JPEG se debe utilizar la siguiente:
let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
// ...
}
Se puede extraer de mi GIST con Xcode parque infantil.