/// <summary>Creates a Bitmap object from a libtiff handle.</summary> /// <param name="tiff">Source image handle, 16 bit grayscale</param> /// <param name="min">Min source histogram value => mapped to 0</param> /// <param name="max">Max source histogram value => mapped to 255</param> /// <returns>The Bitmap object. Remember to dispose the bitmap data /// before abandoning the object!</returns> private Bitmap GetBitmapFromTIFFHandle(IntPtr tiff, ushort min, ushort max) { UInt32 imageWidth, imageLength; UInt16 bitsPerSample, samplesPerPixel; int scanlineSize = LibTIFF.ScanlineSize(tiff); Bitmap bmp; // get image parameters LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_IMAGEWIDTH, out imageWidth); LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_IMAGELENGTH, out imageLength); LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_BITSPERSAMPLE, out bitsPerSample); LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_SAMPLESPERPIXEL, out samplesPerPixel); if (bitsPerSample != 16 || samplesPerPixel != 1) { // this is not a 16bit grayscale TIFF file -- return return(null); } // allocate memory for bitmap IntPtr bmpData = LibTIFF._malloc((int)(scanlineSize / 2 * imageLength)); tbInitialScan0Ptr.Text = bmpData.ToString(); // read scanline by scanline IntPtr pScanline = LibTIFF._malloc(scanlineSize); for (UInt32 row = 0; row < imageLength; row++) { LibTIFF.ReadScanline(tiff, pScanline, row); unsafe { ushort *srcBits16bit = (ushort *)pScanline; // source: 16bit grayscale bitmap byte * dstBitsPalette = (byte *)bmpData; // dest.: 8bit palette bitmap for (int i = 0; i < imageWidth; i++) { // scale each pixel's color according to given limits if (srcBits16bit[i] <= min) { dstBitsPalette[i + row * imageWidth] = 0; } else if (srcBits16bit[i] >= max) { dstBitsPalette[i + row * imageWidth] = 255; } else { dstBitsPalette[i + row * imageWidth] = (byte)(((long)srcBits16bit[i] - (long)min) * (long)255 / ((long)max - min)); } } } } LibTIFF._free(pScanline); // create the Bitmap object using the read bitmap data bmp = new Bitmap((int)imageWidth, (int)imageLength, scanlineSize / 2, PixelFormat.Format8bppIndexed, bmpData); // setup grayscale palette ColorPalette palette = bmp.Palette; for (int i = 0; i < 256; i++) { Color c = Color.FromArgb(i, i, i); palette.Entries[i] = c; } bmp.Palette = palette; return(bmp); }
private void btnOpenTIFF_Click(object sender, System.EventArgs e) { if (ofdOpenTIFF.ShowDialog() != DialogResult.OK) { return; } // open TIFF file string filename = ofdOpenTIFF.FileName; tiff = LibTIFF.Open(filename, "r"); if (tiff == IntPtr.Zero) { MessageBox.Show("Failed to open " + filename); return; } // report some file info tbTIFFPtr.Text = tiff.ToString(); tbRasterScanlineSize.Text = LibTIFF.RasterScanlineSize(tiff).ToString(); tbScanlineSize.Text = LibTIFF.ScanlineSize(tiff).ToString(); UInt32 width, length; if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_IMAGEWIDTH, out width) && LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_IMAGELENGTH, out length)) { tbImageDimensions.Text = width.ToString() + "x" + length.ToString(); } if (LibTIFF.IsTiled(tiff)) { if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_TILEWIDTH, out width) && LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_TILELENGTH, out length)) { tbTileDimensions.Text = width.ToString() + "x" + length.ToString(); } } else { tbTileDimensions.Text = "not tiled"; UInt32 rows; if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_ROWSPERSTRIP, out rows)) { tbRowsPerStrip.Text = rows.ToString(); } } UInt16 bps; if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_BITSPERSAMPLE, out bps)) { tbBitsPerSample.Text = bps.ToString(); } UInt16 spp; if (LibTIFF.GetField(tiff, (int)TIFFTags.TIFFTAG_SAMPLESPERPIXEL, out spp)) { tbSamplesPerPixel.Text = spp.ToString(); } // place TIFF content in the picture box pbPicture.SizeMode = PictureBoxSizeMode.StretchImage; pbPicture.Image = GetBitmapFromTIFFHandle(tiff, 0, 65535); System.Console.WriteLine("System.GC.GetTotalMemory: " + System.GC.GetTotalMemory(true)); }