課題
画面の横幅いっぱいに画像を表示するには、普通こういう風に書く
if let uiImage = photoUIImage {
Image(uiImage: uiImage)
.resizable()
.scaledToFit()
.frame(width: screenWidth)
}
しかし横向きで撮影した写真を表示すると、ただの白い石膏ボードの壁が波打って表示されてしまった。
図:開発中のメモ帳アプリのスクリーンショット
これは大きな画像を無理やり小さな箱(画面幅)に収めたためと考えられる。
このときの画面幅は750
, 写真幅は 4032
だったので、5分の1以下に無理やり収めたことになる。
解決策
画質を下げてから表示すれば良さそうだと考えて対策したら、うまくいった。
どれくらい画質を下げるかという問題だが、上記の場合は下記計算式で違和感のない表示になった。
倍率 = 画面幅 / 写真幅 * 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
参考にした記事