Vyvinul jsem je dokonalým řešením pro škálování obrazu v Swift.
Můžete ji použít pro změnu velikosti obrazu zaplnit, aspekt vyplnit nebo aspekt fit zadané velikosti.
Můžete zarovnat obraz na střed nebo některý ze čtyř rohů a koutů.
A také můžete zkrátit více prostoru, který se přidá, pokud poměry stran původního obrazu a velikost cíle nejsou stejné.
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
}
}
Existují příklady uplatnění tohoto řešení níže.
Šedý obdélník cílové místo obrázku bude změněna na. Modré kruhy světle modrým obdélníkem je obraz (použil jsem kruhy, protože to je snadné pochopit, když je zmenšen, aniž by zachování aspekt). Světle oranžová barva označuje oblasti, které budou ořezané pokud předat trim: true.
Aspekt fit před a po změně měřítka:

Dalším příkladem stran fit :

Aspekt fit s horní zarovnání:

Aspekt výplň :

Výplň :

Použil jsem upscaling ve svých příkladech, protože je to jednodušší prokázat, ale řešení funguje i pro zmenšování jako v otázce.
Pro kompresi JPEG byste měli používat toto:
let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
// ...
}
Můžete se podívat na mou podstatu s Xcode hřištěm.