開発メモ

開発関係のメモをいろいろと。たぶん。

最大容量/最大サイズを指定してUIImageをNSDataに変換する

せっかくUIImagePickerControllerで画像を選べるようになったので、ネット経由でいろいろしようかと思ったのですが、最近のiPhoneはカメラが良い事もあって、画像データがそこそこ大きかったりします。

そこで、データにした後の容量と長辺の最大サイズを制限した上で、NSDataにしてくれるような処理を書いてみました。

f:id:see_ku:20160306193032p:plain

ソースコードはこちら。(前回のデモの流用です)

See_Ku / ImagePickerDemo — Bitbucket
https://bitbucket.org/See_Ku/imagepickerdemo

ちなみに、UIImagePickerControllerの話はこちら。

UIImagePickerControllerを使ってみた - 開発メモ
http://seeku.hateblo.jp/entry/2016/02/29/210359

動作を確認した環境

環境 情報
Xcode 7.2.1 (7C1002)
iOS 9.2
Swift 2.1.1
Date 2016/3/6

ポイント解説

やってる事は単純です。

  1. 指定された範囲に収まるように画像をリサイズ
  2. JPEGの圧縮率を下げながら何度もデータ化

基本はこれだけです。簡単ですね。

指定された範囲に収まるように画像をリサイズ

画像のリサイズはこんな感じ。

/// イメージのサイズを変更
func resizeImage(src: UIImage) -> UIImage {

    // リサイズが必要か?
    let ss = src.size
    if maxLongSide == 0 || ( ss.width <= maxLongSide && ss.height <= maxLongSide ) {
        resizedSize = ss
        return src
    }

    // TODO: リサイズ回りの処理を切りだし

    // リサイズ後のサイズを計算
    let ax = ss.width / maxLongSide
    let ay = ss.height / maxLongSide
    let ar = ax > ay ? ax : ay
    let re = CGRect(x: 0, y: 0, width: ss.width / ar, height: ss.height / ar)

    // リサイズ
    UIGraphicsBeginImageContext(re.size)
    src.drawInRect(re)
    let dst = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    resizedSize = dst.size

    return dst
}

アスペクト比の計算から実際のリサイズまで、ほとんど、お約束の流れのままです。

JPEGの圧縮率を下げながら何度もデータ化

単純に、forでループを回してるだけです。

// JPEG形式でデータ化
for qualityUse = qualityMax; qualityUse >= qualityMin; qualityUse -= qualityDif {
    let data = UIImageJPEGRepresentation(resize, qualityUse)
    if checkDataSize(data) {
        return data
    }
}

こういう処理を書いてると、C言語風のforループもあって良い気がするんですけど・・・ 本当に無くすんでしょうかね?

SK4ShrinkRepresentationの使い方

実際にイメージをデータに変換する処理をまとめたのが、SK4ShrinkRepresentationクラスになります。最大容量/最大サイズを制限してデータにする場合、こんな感じになります。

// 単純に制限付きでデータにするだけならこんな感じ
let data = SK4ShrinkRepresentation.makeData(image, maxDataByte: 1024 * 1024 * 4, maxLongSide: 1024 * 2)

もっと面倒な使い方は・・・ たぶん、必要ないと思うんですけど、気になる方はソースコードを読んで下さい。