LoginSignup
2
1

【Swift】画像がギザギザに表示されてしまう問題のTips【画像 粗い】【ジャギー 除去】

Last updated at Posted at 2024-04-02

■ 概要

本記事では、

Swiftでの開発中において、画像が粗く表示されてしまう

→ 画像が「ジャギる」場合の簡単な対処法

について紹介したいと思います。

■ 環境

Xcodeバージョン : 15.3

■ 実装

まずは今回のサンプル実装から。

CIFilter「CINoiseReduction」フィルターを使用した実装です。

名前の通りでノイズを軽減し、画像がジャギるのを改善するフィルターで、
通常使用の範囲であれば、実装が簡単でとても便利なフィルターです。

(より高度な「ノイズ除去」やカスタマイズ性の高い「ぼかし処理」としてMetalなどのシェーディング言語を使った実装もありますが、実装がかなり大変です…。)

import UIKit

class ExternalViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        
        let w = CGFloat(view.bounds.size.width)
        let h = CGFloat(view.bounds.size.height)
        
        let imageSize = CGSize(width: w * 0.5, height: w * 0.5)

        // inputのCIImageを生成
        let ciImage = CIImage(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: "logo", ofType: "png") ?? ""))
        // ジャギー除去のフィルターをかける
        let filteredCiImage = applyNoiseReductionBlurToImage(inputImage: ciImage ?? CIImage())
        // CIImage → UIImageに変換
        let filteredUiImage = convertCIImageToUIImage(ciImage: filteredCiImage ?? CIImage())

        // 画面中央に画像を配置
        let imageView = UIImageView(frame: CGRect(x: (w - imageSize.width) * 0.5,
                                                  y: (h - imageSize.height) * 0.5,
                                                  width: imageSize.width,
                                                  height: imageSize.height))
        imageView.contentMode = .scaleAspectFit
        
        imageView.image = filteredUiImage
        view.addSubview(imageView)
    }

    // ジャギー除去のCIFilterをかける関数
    func applyNoiseReductionBlurToImage(inputImage: CIImage) -> CIImage? {
    
        guard let noiseReductionFilter = CIFilter(name: "CINoiseReduction") else {
            fatalError("Specified filter does not exist")
        }

        noiseReductionFilter.setValue(inputImage, forKey: kCIInputImageKey)
        
        // これらの値(1.0)は必要に応じて調整する
        noiseReductionFilter.setValue(1.0, forKey: "inputNoiseLevel")
        noiseReductionFilter.setValue(1.0, forKey: "inputSharpness")

        guard let outputImage = noiseReductionFilter.outputImage else {
            fatalError("Failed to get output image from filter")
        }
        
        return outputImage
    }

    // CIImage → UIImageに変換する関数
    func convertCIImageToUIImage(ciImage: CIImage) -> UIImage? {
    
        let context = CIContext()
        
        guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else {
            fatalError("Failed to create CGImage from CIImage")
        }
        
        return UIImage(cgImage: cgImage)
    }
}

■ 「ジャギる」って?

「ジャギる」というのは「ジャギー」を動詞化した言い方をしているだけ
なのですが、具体的にどんな状態を指すかというと

例えば、こんな感じの画像データがあるとして
(ロゴとかを画像データとして表示する機会は多いと思います。)

その画像をシンプルにそのまま表示させます。


モバイル端末など、比較的小さな画面で表示させる分には目立ちづらかったり
しますが、大きな外部モニターなどに出力すると

こんな感じに輪郭部分がギザギザになってしまうことがあります。
(外部モニターに出力したものを、普通に写真で撮ったので
分かりづらいと思いますが、画像を拡大表示してもらうと
文字の輪郭がジャギっていることが確認できると思います。)

■ 解決法

このジャギーの原因はいくつか考えられ、

・画像を高解像度で書き出す
・画像サイズを「2の乗数」で書き出す
・モニター表示設定を適切なものに変更する

これらの対処法でジャギーが改善されるケースもあります。

しかし、どうしても原因や対処法の見当がつかない場合は
「アンチエイリアス」によって、画像に「ぼかし」をかけて
ジャギー除去をするのが効果的です。


CIFilterの「CINoiseReduction」フィルターで
アンチエイリアスをかけた結果…

【Before( 画像 : 左 )】 【After ( 画像 : 右 )】

(色味が若干異なるのは写真撮影時のライトの影響で、
フィルターによるものではありません。こちらも画像を拡大して
比較してもらうと違いが分かりやすいと思います。)

■ 最後に (感想)

今回はCIFilterによる簡単な画像処理について紹介しました。
特に初学者の方とかは、画像を綺麗に表示させるために「ぼかし」をかける、
という発想自体なかなか思い浮かばなかったりするかと思うので
今回の記事が手助けになれば幸いです。

最後まで読んでいただきありがとうございました。

2
1
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
2
1