如何在IOS中将LUT(颜色查找表)应用于CGImage或UIImage?

时间:2012-06-29 08:16:22

标签: c# ios xamarin.ios

给定CGImage或UIImage,如何应用自定义颜色查找表(又称LUT,CLUT,Color Map)?也就是说,在给定映射的情况下,如何将图像中的颜色映射到新颜色?

1 个答案:

答案 0 :(得分:11)

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

  1. 手动执行
  2. 使用CIFilter(iOS 5中提供)
  3. 使用着色器(GPU程序)
  4. 手动方法

    首先,从UIImage获取原始图像数据。您可以通过创建适当大小的字节数组(width * height * components),然后使用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构建OutputImage,将输出字节转换为图像。

    CIFilter方法

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

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

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

    以下是使用随机颜色查找功能填充 CIColorCube 的示例。请注意,可以按名称(非类型安全)或强类型方式动态创建CIFilter。如果你知道在代码时想要使用哪种过滤器,我建议使用强类型过滤器(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); } )。我在下面的例子中使用动态方法,因为它更令人困惑。

    {{1}}

    GPU着色器方法

    最后,在放大率下保持正确的最通用的高性能方法是在GPU上进行颜色映射。这比前两种方法更省力,所以你需要决定它是否值得。

    1. 使用输入图像
    2. 加载一个纹理贴图(也称为Sampler2D)
    3. 使用颜色贴图加载第二个纹理贴图(实际上它是一维纹理,但OpenGL ES可能需要加载为2D纹理)
    4. 将两个纹理贴图和着色器应用于四边形
    5. 在着色器中使用纹理坐标查找第一个纹理中的颜色,然后使用第一个纹理中的值在第二个纹理中查找。那是你的输出颜色。