LoginSignup
10
10

More than 5 years have passed since last update.

UIImageの加工について

Last updated at Posted at 2016-12-01

iOS その3 Advent Calendar

2日目を書かせていただきます!

今年は何記事書けるのかな...。

iOSということでSwiftのことではなくUIKit周りのことを書ければと思います。

といことで早速本題です。

UIImageの加工

先日作成したアプリで(S3とかにある)画像をたくさん並べる処理をして、案の定スクロールがカクツク問題にぶち当たりました。

その際に色々試したUIImageの加工について紹介します。

紹介する処理

  • リサイズ
    • 比率を保たない
    • 比率を保つ
  • 角丸
  • ボーダー

あたりを紹介できればと思います。

リサイズ

UIImage+resize.swift
extension UIImage {

    // 比率保つ版
    func resize(_ size: CGSize) -> UIImage? {
        let widthRatio = size.width / self.size.width
        let heightRatio = size.height / self.size.height
        let ratio = (widthRatio < heightRatio) ? widthRatio : heightRatio
        let resizedWidth = round(self.size.width * ratio)
        let resizedHeight = round(self.size.height * ratio)
        let resizedSize = CGSize(width: resizedWidth, height: resizedHeight)
        UIGraphicsBeginImageContextWithOptions(resizedSize, false, UIScreen.mainScreen().scale)
        let drawRect = CGRect(origin: CGPointZero, size: resizedSize)
        drawInRect(drawRect)
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resizedImage
    }

    // 比率保たない版
    func resize(_ size: CGSize) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)
        let drawRect = CGRect(origin: CGPointZero, size: resizedSize)
        drawInRect(drawRect)
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resizedImage
    }
}

注意点は特にありません...。

角丸

UIImage+maskCorner.swift
extension UIImage {
    func maskCorner(radius r: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.mainScreen().scale)

        let rect = CGRect(origin: CGPointZero, size: self.size)
        UIBezierPath(roundedRect: rect, cornerRadius: r).addClip()
        drawInRect(rect)
        let clippedImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()
        return clippedImage
    }
}

注意点は特にありません...。

ボーダー

UIImage+drawBorder.swift
extension UIImage {

    func drawBorder(width borderWidth: CGFloat, color: UIColor) -> UIImage? {

        UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)

        // clip corner
        let rect = CGRect(origin: CGPointZero, size: self.size)

        let context = UIGraphicsGetCurrentContext()
        CGContextSaveGState(context!)

        drawInRect(rect)
        CGContextRestoreGState(context!)

        let insetRect = CGRectInset(rect, borderWidth / 2.0, borderWidth / 2.0)
        let path = UIBezierPath(rect: insetRect)
        color.setStroke()
        path.lineWidth = borderWidth

        path.stroke()

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

}

補足

ちなみにこのUIImageの加工の処理メインスレッド以外でも実行できます。

なのでUICollectionViewCellなどでSDWebImageと一緒に使う場合はダウンロード処理が終わった後Cellのサイズに合わせてリサイズした後に表示処理をするとスクロールの邪魔もしづらくなります。(個人の体感ですが...)

終わりに

UICollectionViewCelllayerをいじるよりだいぶ邪魔しないで済む方法になるかと思います。

ただ、もしできることならS3などの画像をリクエストでリサイズできるようお願いするともっと幸せになれるかもしれないです。

以上になります。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10