private void pbPicture_Click(object sender, System.EventArgs e) { if (tiff == IntPtr.Zero) { return; } DateTime dtStart = DateTime.Now; Random rnd = new Random(); // these are the grayscale LUT limits of rescale on click int min = rnd.Next(0, 20); int max = rnd.Next(50, 100); // get actual bitmap data of the Bitmap object BitmapData bmpData = ((Bitmap)pbPicture.Image).LockBits( new Rectangle(0, 0, pbPicture.Image.Width, pbPicture.Image.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); tbLastScan0Ptr.Text = bmpData.Scan0.ToString(); // and free the previously allocated memory LibTIFF._free(bmpData.Scan0); ((Bitmap)pbPicture.Image).UnlockBits(bmpData); // dispose object and collect garbage (paranoia?... might be useful when dealing with huge files!) pbPicture.Image.Dispose(); GC.Collect(); // set new image: same file, differently contrasted pbPicture.Image = GetBitmapFromTIFFHandle(tiff, (ushort)min, (ushort)max); tbContrastingTime.Text = ((ulong)((TimeSpan)(DateTime.Now - dtStart)).TotalMilliseconds).ToString(); }
private void btnCloseTIFF_Click(object sender, System.EventArgs e) { if (tiff == IntPtr.Zero) { return; } // reset handle, text fields LibTIFF.Close(tiff); tiff = (IntPtr)0; tbTIFFPtr.Text = tiff.ToString(); tbRasterScanlineSize.Text = ""; tbScanlineSize.Text = ""; tbImageDimensions.Text = ""; tbTileDimensions.Text = ""; tbBitsPerSample.Text = ""; tbRowsPerStrip.Text = ""; tbSamplesPerPixel.Text = ""; tbInitialScan0Ptr.Text = ""; tbLastScan0Ptr.Text = ""; tbContrastingTime.Text = ""; // free bitmat data BitmapData bmpData = ((Bitmap)pbPicture.Image).LockBits( new Rectangle(0, 0, pbPicture.Image.Width, pbPicture.Image.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); LibTIFF._free(bmpData.Scan0); ((Bitmap)pbPicture.Image).UnlockBits(bmpData); // dispose and clear Bitmap object pbPicture.Image.Dispose(); pbPicture.Image = null; }
private void tbCreateTIFF_Click(object sender, System.EventArgs e) { if (sfdCreateTIFF.ShowDialog() != DialogResult.OK) { return; } DateTime startTime = DateTime.Now; // image size int width = 1024 * Convert.ToInt16(tbSizeFactorX.Text); int height = 1024 * Convert.ToInt16(tbSizeFactorY.Text); short rowsPerStrip = (short)height; // create file IntPtr newTiff = LibTIFF.Open(sfdCreateTIFF.FileName, "w"); IntPtr pBuffer; if (chkSaveStrips.Checked) { rowsPerStrip = Convert.ToInt16(tbSaveRowsPerStrip.Text); } // set required tag. WATCH THE TYPES!!! LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_IMAGEWIDTH, (short)width); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_IMAGELENGTH, (short)height); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_BITSPERSAMPLE, (int)16); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_SAMPLESPERPIXEL, (short)1); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_ROWSPERSTRIP, (short)rowsPerStrip); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_PHOTOMETRIC, (short)TIFFTags.PHOTOMETRIC_MINISBLACK); LibTIFF.SetField(newTiff, (int)TIFFTags.TIFFTAG_PLANARCONFIG, (short)TIFFTags.PLANARCONFIG_CONTIG); if (chkSaveStrips.Checked) { // write strips pBuffer = LibTIFF._malloc(width * 2 * rowsPerStrip); // assume raw data to be provided as short[] short[] shortbits = new short[width * rowsPerStrip]; // strips int strips = height / rowsPerStrip; for (int strip = 0; strip < strips; strip++) { for (int y = 0; y < rowsPerStrip; y++) { // pixels in line: set to specific gray value for (int x = 0; x < width; x++) { // short = -32,768 to 32,767 = signed 16-bit integer // ushort is not supported by Marshal.Copy shortbits[y * width + x] = (short)(10 * y); } } // copy data to unsafe context Marshal.Copy(shortbits, 0, pBuffer, width * rowsPerStrip); // ... and write to file int ret = LibTIFF.WriteRawStrip(newTiff, (uint)strip, pBuffer, width * 2 * rowsPerStrip); if (ret == -1) { Console.WriteLine("writing strip " + strip + " returned " + ret); } } } else { // write scanline by scanline pBuffer = LibTIFF._malloc(width * 2); // 16 bpp // assume raw data to be provided as short[] short[] shortbits = new short[width]; // lines for (int y = 0; y < height; y++) { // pixels in line: set to specific gray value for (int x = 0; x < width; x++) { // short = -32,768 to 32,767 = signed 16-bit integer // ushort is not supported by Marshal.Copy shortbits[x] = (short)(100 * y); } // copy data to unsafe context Marshal.Copy(shortbits, 0, pBuffer, width); // ... and write to file if (!LibTIFF.WriteScanline(newTiff, pBuffer, (uint)y)) { Console.WriteLine("writing line " + y + " failed."); } } } LibTIFF._free(pBuffer); LibTIFF.Close(newTiff); MessageBox.Show("Time: " + (DateTime.Now - startTime)); }
/// <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); }