🦋
SwiftUI: 絵文字をモノクロ化してTintカラーで表示する
絵文字をモノクロ化したり、Tintカラーで表示したいことよくありますよね!
🏖️の絵文字をモノクロ化したりTintカラーで表示したり
それ、NSString
とUIGraphicsRendererContext
とCIFilter
でできます。
import SwiftUI
import CoreImage.CIFilterBuiltins
struct PlaygroundView: View {
var body: some View {
HStack(spacing: 20) {
Text("🏖️")
.font(.system(size: 100))
Image(systemName: "arrowshape.right.fill")
.font(.largeTitle)
convertToMonochrome(emoji: "🏖️")
.renderingMode(.template)
.foregroundColor(Color.blue)
}
}
func convertToMonochrome(emoji: String) -> Image {
let text = NSString(string: emoji)
let attributes = [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 100)
]
let textSize = text.size(withAttributes: attributes)
UIGraphicsBeginImageContext(textSize)
text.draw(at: .zero, withAttributes: attributes)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let dummy = Image(systemName: "questionmark.circle.fill")
guard let image else { return dummy }
let monoFilter = CIFilter.photoEffectMono()
monoFilter.inputImage = CIImage(image: image)
guard let output = monoFilter.outputImage else { return dummy }
let invertFilter = CIFilter.colorInvert()
invertFilter.inputImage = output
guard let output2 = invertFilter.outputImage else { return dummy }
let alphaFilter = CIFilter.maskToAlpha()
alphaFilter.inputImage = output2
guard let output3 = alphaFilter.outputImage else { return dummy }
guard let cgImage = CIContext().createCGImage(output3, from: output3.extent) else { return dummy }
return Image(cgImage, scale: 1.0, label: Text(emoji))
}
}
ポイント
- 絵文字を文字列として一度
UIImage
にする-
NSString.size(withAttributes:)
で画像にした時のサイズを取得 -
UIGraphicsBeginImageContext()
とUIGraphicsEndImageContext()
の間で画像への描画処理を行い、UIGraphicsGetImageFromCurrentImageContext()
で画像として出力
-
- 絵文字をモノクロAlpha画像化
-
CIFilter.photoEffectMono()
で絵文字を白黒に -
CIFilter.colorInvert()
で画像の白黒を反転 -
CIFilter.maskToAlpha()
で画像の黒いところをAlphaとして抜く
-
-
renderingMode(.template)
で画像に色をオーバーレイできるようにする
Discussion