LoginSignup
7
10

More than 5 years have passed since last update.

[Swift] iPhoneの写真をAPIにPOSTする際の、上下反転問題とファイルサイズ制限への対策

Last updated at Posted at 2017-09-14

概要

iPhoneで撮影した写真を画像解析のWeb APIにPOSTするケースで、以下のような課題に直面しました。

課題1
iPhoneで撮影した写真は、iPhoneやMac上で見ると正常に見えますが、他の環境で見ると上下反転していることがあります。
APIの解析処理が正常動作しないため、上下反転を補正してからPOSTする必要が生じました。

課題2
APIの仕様上、「POSTする画像は○MB以下」というようなファイルサイズ制限がありました。
ファイルサイズを判定し、制限以下に圧縮する必要が生じました。

以下のようなExtensionを作って、これらの課題をクリアしました。

環境

Item Version
Xcode 8.3
Swift 3.1

UIImage Extension

Swift

extension UIImage {

    /// 上下逆になった画像を反転する
    func fixedOrientation() -> UIImage? {
        if self.imageOrientation == UIImageOrientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        return newImage
    }

    /// イメージ縮小
    func resizeImage(maxSize: Int) -> UIImage? {

        guard let jpg = UIImageJPEGRepresentation(self, 1) as NSData? else {
            return nil
        }
        if isLessThanMaxByte(data: jpg, maxDataByte: maxSize) {
            return self
        }
        // 80%に圧縮
        let _size: CGSize = CGSize(width: (self.size.width * 0.8), height: (self.size.height * 0.8))
        UIGraphicsBeginImageContext(_size)
        self.draw(in: CGRect(x: 0, y: 0, width: _size.width, height: _size.height))
        guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        // 再帰処理
        return newImage.resizeImage(maxSize: maxSize)
    }

    /// 最大容量チェック
    func isLessThanMaxByte(data: NSData?, maxDataByte: Int) -> Bool {

        if maxDataByte <= 0 {
            // 最大容量の指定が無い場合はOK扱い
            return true
        }
        guard let data = data else {
            fatalError("Data unwrap error")
        }
        if data.length < maxDataByte {
            // 最大容量未満:OK ※以下でも良いがバッファを取ることにした
            return true
        }
        // 最大容量以上:NG
        return false
    }
}

Usage

Swift

let image = UIImage(named: "Donald_Trump.jpg")
// 上下反転を補正しつつ4MB未満にする
let arrangedImage = image?.fixedOrientation()?.resizeImage(maxSize: 4194304)

参考リンク

iPhoneで撮影した画像の上下左右バラバラ問題
最大容量/最大サイズを指定してUIImageをNSDataに変換する

7
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
7
10