使用 LibTiff 写入 TIFF 图像的 RGB 值

Writing RGB values of the TIFF image with LibTiff

我正在尝试创建 TIFF 图像的颜色图(不确定正确的术语)- 来自 this kind of image to such,据我所知,我需要相应地修改所有 RGB 值。

我在使用 Libtiff.net 修改现有图像时遇到问题,并且有示例说明如何 读取 图像中的 RGBA 值 (link), but no examples on how to write them into the image. (single one缺少实际将值写入栅格)。 也许有人做过类似的事情或者有使用这个库处理 TIFF 图像中的 RGB 的经验。

库不提供改变现有图像像素的方法。

推荐的工作流程是:阅读 pixels/samples -> 根据需要编辑它们 -> 使用编辑后的样本创建新图像。请注意,不需要将样本转换为 RGB。

您可以在库代码库的Samples文件夹中找到相关示例代码。您可能想从这些开始:

如果将来有人偶然发现同样的东西,我就是这样实现的。

  1. 我通过保留像素格式的默认 TiffBitmapDecoder 读取图像。
  2. 已将图像数据检索到 ushort[] 数组中。
  3. 根据 ushort 数组中的值计算了新的 RGB 并创建了一个新图像,不是原始的 48 位,而是 16 位,这对我的目的来说很好。

代码如下所示:

    using var inputImageStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
    var decoder = new TiffBitmapDecoder(inputImageStream, BitmapCreateOptions.PreservePixelFormat,
        BitmapCacheOption.Default);
    BitmapSource bitmapSource = decoder.Frames[0];

    int bytesPerPixel = (bitmapSource.Format.BitsPerPixel + 7) / 8;
    int ushortStride = bitmapSource.PixelWidth * bytesPerPixel;
    ushort[] pixelData = new ushort[(bitmapSource.PixelHeight * ushortStride) / 2];

    bitmapSource.CopyPixels(pixelData, ushortStride, 0);
    var writeableBitmap = new WriteableBitmap(
        bitmapSource.PixelWidth,
        bitmapSource.PixelHeight,
        bitmapSource.DpiX, bitmapSource.DpiY,
        bitmapSource.Format,
        bitmapSource.Palette);

    var channelValues = RetrieveDataAccordingToChannel(pixelData, selectedChannel);

在 RetrieveDataAccordingToChannel 中,我读取了每个第 N 个值 - 取决于所选的颜色通道。

/// <summary>
/// This method retrieves every 3rd element starting with specific index. Index depends on color channel.
/// Pixel data looks like a 1D array, where every 3 elements is a pixel color data - 
/// e.g. [1, 2, 3, 4, 5, 6...] - 1 and 4 are red channels of first and second pixel, 
/// 2 and 5 is green values of first and second pixel, and 3 and 6 is blue values 
/// of first and second pixels respectively.
/// </summary>
public ushort[] RetrieveDataAccordingToChannel(ushort[] pixelData, ColorChannel colorChannel)
{
    int startElement = 0;

    switch (colorChannel)
    {
        case ColorChannel.Red:
            startElement = 0;
            break;
        case ColorChannel.Green:
            startElement = 1;
            break;
        case ColorChannel.Blue:
            startElement = 2;
            break;
    }

    var outputArray = new List<ushort>();

    for (int i = startElement; i < pixelData.Length; i += 3)
    {
        var element = pixelData[i];
        outputArray.Add(element);
    }

    return outputArray.ToArray();
}

之后我创建了一个新的位图,我在其中写入处理过的像素。

将值处理成新的颜色图如下所示(我从 https://github.com/ar1st0crat/SciColorMaps 获取颜色图):

var colormap = new ColorMap("Jet",
        min, // Mininimum value in the channel data
        max); // Maximum value in the channel data.
...
byte[] color = colormap[channelDataValue];
bitmap.SetPixel(x, y, Color.FromArgb(color[0], color[1], color[2]));