イメージフィルター入門
イメージフィルター(image filter)の基本概念、複数フィルターの合成、BlurによるぼかしとShadowによるドロップシャドウの使い方を解説します。
カラーフィルターが各ピクセルの色だけを見て変換するのに対して、イメージフィルター(image filter)は周囲のピクセルも参照して計算する、より汎用的なエフェクトです。ぼかしのように隣接ピクセルの情報が必要な処理は、カラーフィルターではなくイメージフィルターとして実装されています。
フィルターを合成する
イメージフィルターもchildrenpropで別のフィルターと連結できます。さらに、カラーフィルターやシェーダーもイメージフィルターとして使えるため、異なる種類のエフェクトを1つのチェーンにまとめられます。
import { Canvas, Blur, Image, ColorMatrix, useImage } from "@shopify/react-native-skia";
const ComposeImageFilter = () => {
const image = useImage(require("./assets/photo.jpg"));
if (!image) {
return null;
}
return (
<Canvas style={{ flex: 1 }}>
<Image x={0} y={0} width={256} height={256} image={image} fit="cover">
<Blur blur={2} mode="clamp">
<ColorMatrix
matrix={[
-0.578, 0.99, 0.588, 0, 0, 0.469, 0.535, -0.003, 0, 0, 0.015,
1.69, -0.703, 0, 0, 0, 0, 0, 1, 0,
]}
/>
</Blur>
</Image>
</Canvas>
);
};
この例では、まずColorMatrixが色を変換し、その結果にBlurがかかります。カラーフィルターの章で説明した「childrenが先に適用される」というルールは、イメージフィルターでも同じです。
Blur: ぼかす
BlurはX・Y方向のシグマ値(ぼかしの強さ)を指定してガウスぼかしをかけるイメージフィルターです。ぼかしのカーネルが画像の端をはみ出す場合の扱いをmode(タイルモード)で指定します。
| Name | Type | Description |
|---|---|---|
| blur | number | Vector |
ガウスぼかしのシグマ値 |
| mode? | TileMode |
mirror・repeat・clamp・decalのいずれか(デフォルトはdecal) |
| children? | ImageFilter |
先に適用する別のイメージフィルター |
import { Canvas, Blur, Image, useImage } from "@shopify/react-native-skia";
const BlurImageFilter = () => {
const image = useImage(require("./assets/photo.jpg"));
if (!image) {
return null;
}
return (
<Canvas style={{ flex: 1 }}>
<Image x={0} y={0} width={256} height={256} image={image} fit="cover">
<Blur blur={4} />
</Image>
</Canvas>
);
};
mode="decal"(デフォルト)は画像の外側を透明として扱うため、端が少し暗く/薄くにじんだように見えます。mode="clamp"は端のピクセル色を外側に引き伸ばして使うため、端の色がにじみにくくなります。写真のような矩形いっぱいの画像にはclamp、切り抜かれた図形の縁を柔らかくしたい場合はdecalが向いています。
Shadow: ドロップシャドウ
Shadowイメージフィルターは、コンテンツの下にドロップシャドウを描画します。CSSのfilter: drop-shadow()に相当する機能です。innerpropを付けるとインナーシャドウになり、shadowOnlyを付けると影だけを描画してコンテンツ本体を除外できます。
| Name | Type | Description |
|---|---|---|
| dx | number |
影のX方向オフセット |
| dy | number |
影のY方向オフセット |
| blur | number |
影のぼかし半径 |
| color | Color |
影の色 |
| inner? | boolean |
trueの場合、コンテンツの内側に影を描く |
| shadowOnly? | boolean |
trueの場合、コンテンツ本体を含まず影だけを描画する |
| children? | ImageFilter |
先に適用する別のイメージフィルター |
import { Shadow, Fill, RoundedRect, Canvas } from "@shopify/react-native-skia";
const Neumorphism = () => {
return (
<Canvas style={{ width: 256, height: 256 }}>
<Fill color="lightblue" />
<RoundedRect x={32} y={32} width={192} height={192} r={32} color="lightblue">
<Shadow dx={12} dy={12} blur={25} color="#93b8c4" />
<Shadow dx={-12} dy={-12} blur={25} color="#c7f8ff" />
</RoundedRect>
</Canvas>
);
};
明るい方向と暗い方向、両方に影を1つずつ重ねるのがニューモーフィズム(neumorphism)風の定番テクニックです。同じ角丸矩形の色と背景色を揃えておくと、浮き出ているような・沈み込んでいるような質感が出ます。innerを付ければ後者の「沈み込み」だけを表現できます。
角丸矩形限定でよければ、第2部で扱ったBoxShadowの方が高速に動作します。任意の図形やテキストにも影を付けたい場合は、このShadowイメージフィルターを使ってください。
注意点
イメージフィルターは周辺ピクセルを参照するぶん、カラーフィルターより計算コストが高くなります。特にBlurは半径を大きくするほど処理コストが上がるので、アニメーションで毎フレーム変化させる場合は必要以上に大きな値を使わないようにしてください。
公式ドキュメントのImage Filters Overview・Blur・Shadowsも参照してください。