6

给定 CGImage 或 UIImage,我如何应用自定义颜色查找表(又名 LUT、CLUT、颜色图)?也就是说,给定映射,我如何将图像中的颜色映射到新颜色?

4

1 回答 1

11

我将描述您可以采取的三种方法。

  1. 手动执行
  2. 使用CIFilter(在 iOS 5 中可用)
  3. 使用着色器(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从字节构造 a ,然后CGImage从中构造 a ,然后UIImageCGImage.

CIFilter方法

从 iOS 5 开始,Apple 提供了许多内置的图像操作。通常,这些比手动操作更易于使用且速度更快。但是,根据指定颜色查找表的方式,您可能找不到完美的匹配。

给定一个 CIFilter,您可以设置 inputImage,然后从OutputImage属性中检索输出。有关CICategoryColorAdjustment 和 CICategoryColorEffect 类别中的过滤器列表,请参阅文档。在撰写本文时,我建议查看 CIToneCurve、CIFalseColor、CIColorMap 和 CIColorCube。遗憾的是,在撰写本文时,CIColorMap 在 iOS 上不可用。

如果您正在做科学成像,并且只使用两种颜色之间的线性渐变,我建议您查看CIFalseColor

这是一个使用随机颜色查找函数填充CIColorCube的示例。请注意,CIFilter 可以通过名称(非类型安全)或以强类型方式动态创建。如果您知道要在代码时使用什么过滤器,我建议使用强类型过滤器(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 上进行颜色映射。这比前两种方法更费力,因此您需要确定是否值得。

  1. 使用输入图像加载一个纹理贴图(又名 Sampler2D)
  2. 使用您的颜色贴图加载第二个纹理贴图(实际上它是 1D 纹理,但使用 OpenGL ES 可能需要作为 2D 纹理加载)
  3. 将两个纹理贴图和一个着色器应用于四边形
  4. 在着色器中使用纹理坐标在第一个纹理中查找颜色,然后使用第一个纹理中的值在第二个纹理中查找。那是你的输出颜色。
于 2012-06-29T18:31:58.990 回答