Show a multipage tiff file (by libtiff.net) with ImageAnnotation

Oystein Bjorke 5 years ago 0
This discussion was imported from CodePlex

opensw wrote at 2014-05-08 12:53:

Hi,
I have a multipage tiff video (8 bit grayscale), I would like to show the frames in OxyPlot WPF plot control.

I am using libtfff.net to read the multipage tiff, all data are stored in a byte[] buf array; now the problem is that I do not know how to use this array with ImageAnnotation, sorry for the noob question, is there a way?

This is my code
            // open a tiff
            Tiff tiff = Tiff.Open("merged8bit.tif", "r");

            // read tiff image
            FieldValue[] value = tiff.GetField(TiffTag.IMAGELENGTH);
            int imageLength = value[0].ToInt();

            Bitmap bitmap = new Bitmap(tiff.ScanlineSize(), imageLength, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            byte[] buf = new byte[tiff.ScanlineSize()];

            for (int row = 0; row < imageLength; row++)
            {
                tiff.ReadScanline(buf, row);
                for (int col = 0; col < tiff.ScanlineSize(); col++)
                {
                    bitmap.SetPixel(col, row, System.Drawing.Color.FromArgb(0, buf[col], buf[col], buf[col]));
                }
            }

            // create a model
            PlotModel model = new PlotModel();
            Plot.Model = model;

            model.Title = "TIFF";

            LinearAxis 
                axisX = new LinearAxis(),
                axisY = new LinearAxis();
            axisX.Position = AxisPosition.Bottom;

            model.Axes.Add(axisX);
            model.Axes.Add(axisY);

            ImageAnnotation image = new ImageAnnotation();
            image.HorizontalAlignment = OxyPlot.HorizontalAlignment.Left;
            image.VerticalAlignment = OxyPlot.VerticalAlignment.Top;

            MemoryStream stream = new MemoryStream();
            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);

            // Exception: invalid format
            image.ImageSource = new OxyImage(stream);

            model.Annotations.Add(image);

            stream.Close();
            tiff.Close();
Thanks a lot for any help :)

opensw wrote at 2014-05-08 16:38:

I have found a solution: HeatMapSeries... but the rendering speed is bad and I have a problem in visualization (I need to 'transpose' the final plot). I hope there is another solution.
            // open a tiff
            Tiff tiff = Tiff.Open("merged8bit.tif", "r");

            // read tiff image
            FieldValue[] value = tiff.GetField(TiffTag.IMAGELENGTH);
            int imageLength = value[0].ToInt();

            // create a model
            PlotModel model = new PlotModel();

            LinearColorAxis colorAxis = new LinearColorAxis();
            colorAxis.Position = AxisPosition.Right;
            colorAxis.LowColor = OxyColors.White;
            colorAxis.HighColor = OxyColors.White;

            var palette = OxyPalette.Interpolate(255, OxyColors.Black, OxyColors.White);
            colorAxis.Palette = palette;

            model.Axes.Add(colorAxis);

            var heatMapSeries1 = new HeatMapSeries();
            heatMapSeries1.X0 = 0;
            heatMapSeries1.Y0 = tiff.ScanlineSize();
            heatMapSeries1.X1 = imageLength;
            heatMapSeries1.Y1 = 0;
            heatMapSeries1.Interpolate = false;
            heatMapSeries1.Data = new Double[imageLength, tiff.ScanlineSize()];

            byte[] buf = new byte[tiff.ScanlineSize()];

            for (int row = 0; row < imageLength; row++)
            {
                tiff.ReadScanline(buf, row);
                Parallel.For(0, tiff.ScanlineSize(), col =>
                {
                    heatMapSeries1.Data[row, col] = buf[col];
                });
            }

            model.Title = "TIFF";

            LinearAxis 
                axisX = new LinearAxis(),
                axisY = new LinearAxis();
            axisX.Position = AxisPosition.Bottom;

            model.Axes.Add(axisX);
            model.Axes.Add(axisY);

            model.Series.Add(heatMapSeries1);

            model.PlotType = PlotType.Cartesian;

            Plot.Model = model;

            tiff.Close();

objo wrote at 2014-05-10 23:28:

I think it is best to use the OxyImage solution. Can you try saving the image data to PNG instead? BMP may not be fully implemented.
And make sure the MemoryStream is positioned at the start when you pass the stream to the constructor. Consider using the OxyImage(byte[]) constructor instead.

opensw wrote at 2014-05-20 00:50:

Hi,
sorry for late reply, it is working :) the problem was about seek in MemoryStream (the fix is stream.Seek(0, SeekOrigin.Begin)) like you mentioned.

P.S.
Sometimes an exception occours at image.ImageSource = new OxyImage(stream);Is it a bug?

The exception is:
System.ArgumentOutOfRangeExcpetion
"Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: startIndex"}
CodePlex