2018年3月8日木曜日

画像の作り直しでJPEGがPNGになっちゃった

Retinaディスプレイの画面をキャプチャし、それをツイッターに投稿するアプリを作ってるが、画像容量がでかくなるので縮小したい。

画面キャプチャだけ

iPhoneだとRetina解像度でちょうどいいのだが、iPadだとファイルサイズが大きくなるためツイートをはねられることがしばしばある。5MB制限らしいので、それをオーバーしてしまうようだ。
うまく投稿できても15秒くらいかかって遅い。投稿できた画像は元と同じくJPEG。

UIGraphicsBeginImageContextWithOptions(realSize, false, 2.0) //Contextを作成(Retina対応で2.0)
let ctx = UIGraphicsGetCurrentContext() //現在のContextを得る
imageView.layer.render(in: UIGraphicsGetCurrentContext()!) //Context部分に表示されている画像その他をレンダリング(ここが画面キャプチャ)
var image = UIGraphicsGetImageFromCurrentImageContext() //UIImageを作る

UIGraphicsEndImageContext()

縦横ピクセルを制限

iPadのRetina解像度のまま投稿すると縦横の長さも大きすぎるので、はみ出してる画像は最大1000ピクセルに縮小させるようコードを書いた。
いっぺんに縮小するのでなく、一度キャプチャして出来た画像を再度GraphicContextを使ってリサイズしている。
Retina解像度でキャプチャしているので、image.sizeで得られるwidth、heightは1/2になっているので注意。最終的に得られる画像はその倍になるのでややこしい。
1000pxの画像を得たいときに500pxに縮小すると最終的に1000pxになるというもの。

//画像縦横サイズ制限
//maxPixelSizeは例えば500とか入ってる
//縦横の最大を1000pxに抑えたいが、2倍精細なRetina解像度なので、image.sizeで得られる解像度はその半分になるため
var newSize = image?.size
if image!.size.width > maxPixelSize || image!.size.height > maxPixelSize {
    if image!.size.width >= image!.size.height {
        let rate = maxPixelSize / image!.size.width //縦横比
        newSize = CGSize(width: maxPixelSize, height: image!.size.height * rate)
    } else {
        let rate = maxPixelSize / image!.size.height //縦横比
        newSize = CGSize(width: image!.size.width * rate, height: maxPixelSize)
    }
        //UIImage作り直し開始。なぜかPNGになってしまう
    UIGraphicsBeginImageContext(newSize!)
    image!.draw(in: CGRect(x: 0, y: 0, width: newSize!.width, height: newSize!.height))
    image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    ⭐️
}

そうしたらなぜか画像がPNGになってしまった。縮小してるから投稿できないことはないが、1MBオーバーで縮小したありがたみが薄い。

キャプチャ時の解像度を非Retinaにするとサイズ制限しなくてもJPEGになってくれるけど、今度はiPhoneでのキャプチャ解像度が低いため、画像が小さすぎてしまう。

しょうがないので、一度JPEGのData型に直し、さらにそれをUIImageに戻して解決した。

上記コードの⭐️に挿入
//0.7は圧縮率
let imageData = UIImageJPEGRepresentation(image!, 0.7)
image = UIImage(data: imageData!)

  1. Retina解像度でContextを作ってキャプチャ
  2. UIImageとして変数に
  3. 縦横を同比率で縮小するためにwidthとheightを計算
  4. 計算したwidth、heightでContextを作り、2.のUIImageをdrawすることで画像縮小(このままだとPNGになる)
  5. UIImageをJPEG化してDataに直す(UIImageのままフォーマット変換できないから)
  6. DataをUIImageに戻して終了

原因はわからないが、UIImageって内部的にJPEGとかPNGとかの情報も持ってるのね?

0 件のコメント:

コメントを投稿