0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

高画質画像を小さく表示すると波打つ件の対処【SwiftUI】【メモ帳アプリ】

Posted at

課題

画面の横幅いっぱいに画像を表示するには、普通こういう風に書く

if let uiImage = photoUIImage {
    Image(uiImage: uiImage)
    .resizable()
    .scaledToFit()
    .frame(width: screenWidth)
}

しかし横向きで撮影した写真を表示すると、ただの白い石膏ボードの壁が波打って表示されてしまった
IMG_0EB8A325AA9A-1.jpeg
図:開発中のメモ帳アプリのスクリーンショット

これは大きな画像を無理やり小さな箱(画面幅)に収めたためと考えられる。
このときの画面幅は750, 写真幅は 4032だったので、5分の1以下に無理やり収めたことになる。

解決策

画質を下げてから表示すれば良さそうだと考えて対策したら、うまくいった。
IMG_8C203C0E6EE4-1.jpeg

どれくらい画質を下げるかという問題だが、上記の場合は下記計算式で違和感のない表示になった。

倍率 = 画面幅 / 写真幅 * 2

最初はシンプルに画面幅 / 写真幅を試したが、画質が荒く見えてイマイチだったので2倍した。画面幅の2倍程度なら波打って見えることもないようである。このあたりの最適値は端末や、もしかしたら人によっても違うかもしれない。

コードはこちら:
画質を変更するためのextensionを定義しておいて、

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

表示するときに使う

if let uiImage = photoUIImage {
    let resizeRate: CGFloat = screenWidth / uiImage.size.width * 2
    Image(uiImage:
            uiImage.resized(rate: resizeRate)!
    )
    .resizable()
    .scaledToFit()
    .frame(width: screenWidth)
}

実装したアプリ

ちなみに、こちらは下記のメモ帳アプリ「Roamee」に実装しました。
よければ覗いてみてください。
https://apps.apple.com/jp/app/%E3%83%A9%E3%83%99%E3%83%AB%E3%83%8E%E3%83%BC%E3%83%88/id1644589126

参考にした記事

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?