photo credit: crunklygill swifts up high via photopin (license)

画像から正方形のサムネイルを作る方法を紹介する。

手順は次の通り。

  1. 画像をリサイズする
    1-1. リサイズの目標サイズを計算する
    1-2. 目標サイズへリサイズした画像を生成する
  2. リサイズ画像をクロッピングする
    2-1. サムネイルの目標サイズに合わせて、クロッピングする形を計算する
    2-2. リサイズ画像をクロッピングしてサムネイルを作成する

最終的なコード全体は最下部

GitHub で見るにはこちら。


 
 

1. 画像をリサイズする

1-1. リサイズの目標サイズを計算する

func calculateResizedWidth(sourceImage: UIImage, objectiveLengthOfShortSide: CGFloat) -> CGFloat {
        let width: CGFloat = sourceImage.size.width
        let height: CGFloat = sourceImage.size.height
        let resizedWidth: CGFloat = width <= height ? objectiveLengthOfShortSide : objectiveLengthOfShortSide * width / height
        return resizedWidth
}

上記のcalculateResizedWidth関数を用いて、リサイズ後画像の幅をいくらにすべきかを計算する。

次の変数があるとして、

let sourceImage: UIImage = もともとのUIImage
let objectiveEdgeLength: CGFloat = サムネイルの一辺の長さとしたい値(サムネイルは正方形と仮定しています)

次のコードでリサイズ後画像の幅resizedWidthが得られる。

let resizedWidth: CGFloat = calculateResizedWidth(sourceImage: sourceImage, objectiveLengthOfShortSide: objectiveEdgeLength)

1-2. 目標サイズへリサイズした画像を生成する

func resizeImage(sourceImage: UIImage, objectiveWidth: CGFloat) -> UIImage {
        let aspectScale: CGFloat = sourceImage.size.height / sourceImage.size.width
        let resizedSize: CGSize = CGSize(width: objectiveWidth, height: objectiveWidth * aspectScale)

        // リサイズ後のUIImageを生成して返却
        UIGraphicsBeginImageContext(resizedSize)
        sourceImage.draw(in: CGRect(x: 0, y: 0, width: resizedSize.width, height: resizedSize.height))
        let resizedImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return resizedImage!
}

上記のresizeImage関数に、1-1 で得たresizedWidthを引数として渡してやることでリサイズされた画像が得られる。

 let resizedImage: UIImage = resizeImage(sourceImage: sourceImage, objectiveWidth: resizedWidth)
        let thumbnailSize: CGSize = CGSize(width: objectiveEdgeLength, height: objectiveEdgeLength)


 
 

2. リサイズ画像をクロッピングする

2-1. サムネイルの目標サイズに合わせて、クロッピングする形を計算する

func calulateCroppingRect(imgae: UIImage, objectiveSize: CGSize) -> CGRect {
        let croppingRect: CGRect = CGRect.init(x: (imgae.size.width - objectiveSize.width) / 2, y: (imgae.size.height - objectiveSize.height) / 2, width: objectiveSize.width, height: objectiveSize.height)
        return croppingRect
}

1-2 で得たresizedImageと上記のcalulateCroppingRectを用いて、クロッピングする形を計算する。

let thumbnailSize: CGSize = CGSize(width: objectiveEdgeLength, height: objectiveEdgeLength)
let croppingRect: CGRect = calulateCroppingRect(imgae: resizedImage, objectiveSize: thumbnailSize)

2-2. リサイズ画像をクロッピングしてサムネイルを作成する

func cropImage(image: UIImage, croppingRect: CGRect) -> UIImage {
        let croppingRef: CGImage? = image.cgImage!.cropping(to: croppingRect)
        let croppedImage: UIImage = UIImage(cgImage: croppingRef!)
        return croppedImage
}

1-2 で得たresizedImageと 2-1 で得たcroppingRectを上記のcropImage関数に渡してやることで、サムネイルを得る。

let croppedImage: UIImage = cropImage(image: resizedImage, croppingRect: croppingRect)

コード全体

generateThumbnail関数を呼び出してやれば、サムネイルが返ってくる。

func generateThumbnail(sourceImage: UIImage, objectiveEdgeLength: CGFloat) -> UIImage {
        let resizedWidth: CGFloat = calculateResizedWidth(sourceImage: sourceImage, objectiveLengthOfShortSide: objectiveEdgeLength)
        let resizedImage: UIImage = resizeImage(sourceImage: sourceImage, objectiveWidth: resizedWidth)
        let thumbnailSize: CGSize = CGSize(width: objectiveEdgeLength, height: objectiveEdgeLength)
        let croppingRect: CGRect = calulateCroppingRect(imgae: resizedImage, objectiveSize: thumbnailSize)
        let croppedImage: UIImage = cropImage(image: resizedImage, croppingRect: croppingRect)
        return croppedImage
}

func calculateResizedWidth(sourceImage: UIImage, objectiveLengthOfShortSide: CGFloat) -> CGFloat {
        let width: CGFloat = sourceImage.size.width
        let height: CGFloat = sourceImage.size.height
        let resizedWidth: CGFloat = width <= height ? objectiveLengthOfShortSide : objectiveLengthOfShortSide * width / height
        return resizedWidth
}

func resizeImage(sourceImage: UIImage, objectiveWidth: CGFloat) -> UIImage {
        let aspectScale: CGFloat = sourceImage.size.height / sourceImage.size.width
        let resizedSize: CGSize = CGSize(width: objectiveWidth, height: objectiveWidth * aspectScale)

        // リサイズ後のUIImageを生成して返却
        UIGraphicsBeginImageContext(resizedSize)
        sourceImage.draw(in: CGRect(x: 0, y: 0, width: resizedSize.width, height: resizedSize.height))
        let resizedImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return resizedImage!
}

func calulateCroppingRect(imgae: UIImage, objectiveSize: CGSize) -> CGRect {
        let croppingRect: CGRect = CGRect.init(x: (imgae.size.width - objectiveSize.width) / 2, y: (imgae.size.height - objectiveSize.height) / 2, width: objectiveSize.width, height: objectiveSize.height)
        return croppingRect
}

func cropImage(image: UIImage, croppingRect: CGRect) -> UIImage {
        let croppingRef: CGImage? = image.cgImage!.cropping(to: croppingRect)
        let croppedImage: UIImage = UIImage(cgImage: croppingRef!)
        return croppedImage
}

GitHub はこちら。

カテゴリー: Tips

hahnah

はーな Webエンジニア。モバイルアプリも少々。Elmが好き。

0件のコメント

コメントを残す

メールアドレスが公開されることはありません。