From 3048c46dc77b4caab2e2dfed4186bcd6e22966cd Mon Sep 17 00:00:00 2001 From: "Enrico A. Franzelli" Date: Wed, 13 Sep 2017 11:18:53 +0200 Subject: [PATCH] Choose image interpolation based on size change --- Sources/SwiftGD.swift | 68 ++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/Sources/SwiftGD.swift b/Sources/SwiftGD.swift index 2b9ba72..73653fb 100644 --- a/Sources/SwiftGD.swift +++ b/Sources/SwiftGD.swift @@ -18,8 +18,8 @@ public class Image { private var internalImage: gdImagePtr - public var size: (width: Int, height: Int) { - return (width: Int(internalImage.pointee.sx), height: Int(internalImage.pointee.sy)) + public var size: Size { + return Size(width: internalImage.pointee.sx, height: internalImage.pointee.sy) } public init?(width: Int, height: Int) { @@ -87,46 +87,49 @@ public class Image { } public func resizedTo(width: Int, height: Int, applySmoothing: Bool = true) -> Image? { - if applySmoothing { - gdImageSetInterpolationMethod(internalImage, GD_BILINEAR_FIXED) - } else { - gdImageSetInterpolationMethod(internalImage, GD_NEAREST_NEIGHBOUR) - } + applyInterpolation(enabled: applySmoothing, currentSize: size, newSize: Size(width: width, height: height)) guard let output = gdImageScale(internalImage, UInt32(width), UInt32(height)) else { return nil } return Image(gdImage: output) } public func resizedTo(width: Int, applySmoothing: Bool = true) -> Image? { - if applySmoothing { - gdImageSetInterpolationMethod(internalImage, GD_BILINEAR_FIXED) - } else { - gdImageSetInterpolationMethod(internalImage, GD_NEAREST_NEIGHBOUR) - } - let currentSize = size let heightAdjustment = Double(width) / Double(currentSize.width) - let newHeight = Double(currentSize.height) * Double(heightAdjustment) + let newSize = Size(width: Int32(width), height: Int32(Double(currentSize.height) * Double(heightAdjustment))) - guard let output = gdImageScale(internalImage, UInt32(width), UInt32(newHeight)) else { return nil } + applyInterpolation(enabled: applySmoothing, currentSize: currentSize, newSize: newSize) + + guard let output = gdImageScale(internalImage, UInt32(newSize.width), UInt32(newSize.height)) else { return nil } return Image(gdImage: output) } public func resizedTo(height: Int, applySmoothing: Bool = true) -> Image? { - if applySmoothing { - gdImageSetInterpolationMethod(internalImage, GD_BILINEAR_FIXED) - } else { - gdImageSetInterpolationMethod(internalImage, GD_NEAREST_NEIGHBOUR) - } - let currentSize = size let widthAdjustment = Double(height) / Double(currentSize.height) - let newWidth = Double(currentSize.width) * Double(widthAdjustment) + let newSize = Size(width: Int32(Double(currentSize.width) * Double(widthAdjustment)), height: Int32(height)) + + applyInterpolation(enabled: applySmoothing, currentSize: currentSize, newSize: newSize) - guard let output = gdImageScale(internalImage, UInt32(newWidth), UInt32(height)) else { return nil } + guard let output = gdImageScale(internalImage, UInt32(newSize.width), UInt32(height)) else { return nil } return Image(gdImage: output) } + public func applyInterpolation(enabled: Bool, currentSize: Size, newSize: Size) { + guard enabled else { + gdImageSetInterpolationMethod(internalImage, GD_NEAREST_NEIGHBOUR) + return + } + + if currentSize > newSize { + gdImageSetInterpolationMethod(internalImage, GD_SINC) + } else if currentSize < newSize { + gdImageSetInterpolationMethod(internalImage, GD_MITCHELL) + } else { + gdImageSetInterpolationMethod(internalImage, GD_NEAREST_NEIGHBOUR) + } + } + public func fill(from: Point, color: Color) { let internalColor = gdImageColorAllocateAlpha(internalImage, Int32(color.redComponent * 255.0), Int32(color.greenComponent * 255.0), Int32(color.blueComponent * 255.0), 127 - Int32(color.alphaComponent * 127.0)) defer { gdImageColorDeallocate(internalImage, internalColor) } @@ -234,14 +237,27 @@ public struct Point { } } -public struct Size { - var width: Int - var height: Int +public struct Size: Comparable { + public var width: Int + public var height: Int public init(width: Int, height: Int) { self.width = width self.height = height } + + public init(width: Int32, height: Int32) { + self.width = Int(width) + self.height = Int(height) + } +} + +public func <(lhs: Size, rhs: Size) -> Bool { + return lhs.width < rhs.width && lhs.height < rhs.height +} + +public func ==(lhs: Size, rhs: Size) -> Bool { + return lhs.width == rhs.width && lhs.height == rhs.height } public class Color {