If in future somebody would stumble upon same stuff, this is how i implemented it.
- I read image through default TiffBitmapDecoder with preserving pixel format.
- Retrieved image data into ushort[] array.
- 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]));
