CGImage または UIImage を指定して、カスタム カラー ルックアップ テーブル (別名 LUT、CLUT、カラー マップ) を適用するにはどうすればよいですか? つまり、マッピングが与えられた場合、画像内の色を新しい色にマッピングするにはどうすればよいでしょうか?
1 に答える
あなたが取ることができる3つのアプローチについて説明します。
- 手動で行う
- CIFilterを使用する(iOS 5 で利用可能)
- シェーダー (GPU プログラム) を使用する
手動アプローチ
まず、UIImage から生の画像データを取得します。これを行うには、適切なサイズ (幅 * 高さ * コンポーネント) のバイト配列を作成し、CGBitmapContext で描画します。このようなもの:
using (var colorSpace = CGColorSpace.CreateDeviceRGB())
using (var context = new CGBitmapContext(
bytes, width, height, bitsPerComponent, bytesPerRow,
colorSpace, CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.PremultipliedLast))
{
var drawRect = new RectangleF(-rectangle.X, -rectangle.Y, image.CGImage.Width, image.CGImage.Height);
context.ClipToRect(new RectangleF(0, 0, width, height));
context.DrawImage(drawRect, image.CGImage);
}
次に、出力画像用のバイト配列を作成します (おそらく同じサイズ)。入力画像を反復処理して、ルックアップ テーブルで色の値を検索し、それらを出力画像に書き込みます。
出力バイトをイメージに変換するには、CGDataProvider
バイトから を作成し、次にCGImage
から を作成し、次にUIImage
から を作成しCGImage
ます。
CIFilterアプローチ
iOS 5 の時点で、Apple は多くの組み込みのイメージ操作を提供しています。一般に、これらは使いやすく、手動で行うよりも高速です。ただし、カラー ルックアップ テーブルの指定方法によっては、完全に適合しない場合があります。
CIFilter を指定すると、inputImage を設定し、OutputImage
プロパティから出力を取得できます。CICategoryColorAdjustment および CICategoryColorEffect カテゴリのフィルターのリストについては、ドキュメントを参照してください。これを書いている時点では、CIToneCurve、CIFalseColor、CIColorMap、および CIColorCube を見ることをお勧めします。残念ながら、執筆時点では、CIColorMap は iOS では利用できません。
科学的な画像処理を行っていて、2 つの色の間の線形グラデーションのみを使用している場合は、CIFalseColorを確認することをお勧めします。
これは、CIColorCubeにランダム カラー ルックアップ関数を設定する例です。CIFilters は、名前 (タイプ セーフではない) または厳密に型指定された方法で動的に作成される場合があることに注意してください。コード時に使用するフィルターがわかっている場合は、厳密に型指定されたフィルター (CIColorCube
ではなくCIFilter.FromName("CIColorCube")
) を使用することをお勧めします。次の例では、より紛らわしいため、動的アプローチを使用しています。
static void PopulateColorCubeFilter(CIFilter filter)
{
if (filter.Name != "CIColorCube")
return;
int dimension = 64; // Must be power of 2, max of 128 (max of 64 on ios)
int cubeDataSize = 4 * dimension * dimension * dimension;
filter[new NSString("inputCubeDimension")] = new NSNumber(dimension);
// 2 : 32 /4 = 8 = 2^3
// 4 : 256 /4 = 64 = 4^3
// 8 : 2048 /4 = 512 = 8^3
var cubeData = new byte[cubeDataSize];
var rnd = new Random();
rnd.NextBytes(cubeData);
for (int i = 3; i < cubeDataSize; i += 4)
cubeData[i] = 255;
filter[new NSString("inputCubeData")] = NSData.FromArray(cubeData);
}
GPU シェーダー アプローチ
最後に、拡大しても正しく維持される最も汎用的な高性能アプローチは、GPU でカラー マッピングを行うことです。これは最初の 2 つの方法よりも手間がかかるため、その価値があるかどうかを判断する必要があります。
- 入力画像で 1 つのテクスチャ マップ (別名 Sampler2D) を読み込みます
- カラー マップを使用して 2 番目のテクスチャ マップをロードします (実際には 1D テクスチャですが、OpenGL ES ではおそらく 2D テクスチャとしてロードする必要があります)。
- 2 つのテクスチャ マップとシェーダをクワッドに適用する
- シェーダーでは、テクスチャ座標を使用して最初のテクスチャの色を検索し、最初のテクスチャの値を使用して 2 番目のテクスチャを検索します。それが出力色です。