J'ai développé une solution ultime pour la mise à l'échelle d'image dans Swift.
Vous pouvez l'utiliser pour redimensionner l'image pour remplir, remplir d'aspect ou ajuster l'aspect à la taille spécifiée.
Vous pouvez aligner l'image au centre ou à l'un des quatre bords et quatre coins.
Et vous pouvez également réduire l'espace supplémentaire qui est ajouté si les rapports hauteur / largeur de l'image d'origine et de la taille cible ne sont pas égaux.
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
}
}
Vous trouverez ci-dessous des exemples d'application de cette solution.
Le rectangle gris est l'image du site cible sera redimensionnée. Les cercles bleus dans un rectangle bleu clair sont l'image (j'ai utilisé des cercles car il est facile de voir quand ils sont mis à l'échelle sans préserver l'aspect). La couleur orange clair marque les zones qui seront coupées si vous passez trim: true
.
Ajustement de l'aspect avant et après la mise à l'échelle:
Un autre exemple d' ajustement d'aspect :
Ajustement d'aspect avec alignement supérieur:
Remplissage d'aspect :
Remplir :
J'ai utilisé la mise à l'échelle dans mes exemples parce que c'est plus simple à démontrer, mais la solution fonctionne également pour la réduction d'échelle comme en question.
Pour la compression JPEG, vous devez utiliser ceci:
let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
// ...
}
Vous pouvez consulter mon essentiel avec le terrain de jeu Xcode.