概要
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)