LoginSignup
3
2

More than 3 years have passed since last update.

UIImageをnKB以下のJPEGに変換するExtension

Last updated at Posted at 2019-11-06

「UIImageを絶対にnKB以下のJPEGで送らないといけない!」ということがあり、作りました。

コード

import UIKit

extension UIImage {
    func compressedJpegData(toKB:Int) -> Data? {
        guard let resized = self.resized(withPercentage: 0.75) else { return nil }
        guard var data = resized.jpegData(compressionQuality: 0.9) else { return nil }

        let byte = [UInt8](data)
        if (byte.count / 1024) >= toKB {
            // toKBを超えてた時
            guard let againImage = UIImage(data: data) else { return nil }
            guard let rescalingData = againImage.compressedJpegData(toKB: toKB) else { return nil }
            data = rescalingData
        }
        return data
    }

    func resized(withPercentage percentage: CGFloat) -> UIImage? {
        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
        return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }
}

やっていること

func compressedJpetgData(toKB:Int) -> Data?

これは、指定したサイズ(容量的な)まで縮めるメソッドです。
toKBに指定したサイズに収まるまで再帰的に呼ばれます。

guard let resized = self.resized(withPercentage: 0.75) else { return nil }
guard var data = resized.jpegData(compressionQuality: 0.9) else { return nil }

まずサイズ(見た目的な)を縮小し、JPEGにエンコードします。
self.resized(withPercentage: 0.75)は以下のような処理になっています。

func resized(withPercentage percentage: CGFloat) -> UIImage? {
    let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
    return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
        _ in draw(in: CGRect(origin: .zero, size: canvas))
    }
}

↑で、縮小率を指定してUIImageを縮小することが出来ます。アスペクト比は保持されます。

let byte = [UInt8](data)
if (byte.count / 1024) >= toKB {
    // toKBを超えてた時
    guard let againImage = UIImage(data: data) else { return nil }
    guard let rescalingData = againImage.compressedJpegData(toKB: toKB) else { return nil }
    data = rescalingData
}
return data

JPEG化したDataをバイト配列に入れ、サイズを見ます。
byte.countはJPEGのバイト数を表しています。今回はKBで計算したいので1024で割ります。
割った結果がtoKBを下回っていればそのままdataを返し、超えていた場合は再度UIImageにして圧縮処理します。
以上の流れを、サイズがtoKBを下回るまで行います。


もしよかったら使っていただけるとありがたいです。いいねも押していただけると喜びます。
不明点、不足点、改善点など、何でもコメントしてください。
ありがとうございました。

3
2
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
3
2