1

I'm trying to create a colormap (not sure about the right term) of the TIFF image - from this kind of image to such, and as i understand i need to modify all RGB values accordingly.

I'm having trouble with modifying existing image with Libtiff.net and there are example of how to read the RGBA values from the image (link), but no examples on how to write them into the image. (single one is missing actual writing the values into the raster). Maybe somebody had done something similiar or have experience with processing of RGB in TIFF images with this library.

2 Answers2

0

The library does not provide means to alter existing image pixels.

The recommended workflow is: read pixels/samples -> edit them as needed -> create a new image with edited samples. Please note that it is not required to convert samples to RGB.

You can find relevant sample code in the Samples folder of the library code repository. You might want to start from these ones:

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
0

If in future somebody would stumble upon same stuff, this is how i implemented it.

  1. I read image through default TiffBitmapDecoder with preserving pixel format.
  2. Retrieved image data into ushort[] array.
  3. Calculated new RGB based on values that are in ushort array and created a new image, not in original 48bit, but in 16bit, which is fine for my purposes.

Code looks like this:

    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);

In RetrieveDataAccordingToChannel i read each Nth value - depends on the color channel that is chosen.

/// <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();
}

After that i create a new Bitmap where i write processed pixels.

Processing of values into new colormap looks like this (I took Colormap from 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]));

Source image Final image after processing