Article | 70002537 |
Type | HowTo |
Product | Engine |
Version | 11 |
Date Added | 6/12/2024 12:00:00 AM |
Fixed | 11.1.6.0 (6/14/2024 12:00:00 AM) |
Submitted by | Rafael de Freitas |
Summary
Open big size TIFF image files
Solution
In order to open tiff images with size larger than 2gb you need to convert the tiff image to an image (Bitmap) with smaller size using a third party library like the LibTiff.Net of "Bit Miracle" which is open source (see https://bitmiracle.com/libtiff/ ).
In .NET you cannot have an array bigger than 2GB, for example in C# a code like new byte(2200000000) Or new int(510000) then it crashes as it exceeds the 2GB of continues memory.
So see the example below that references the BitMiracle.LibTiff.NET nuget package
using BitMiracle.LibTiff.Classic; using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; namespace BitMiracle.LibTiff.Samples { public static class TiffToBitmap { ////// Convert the passed tiff file to a SyStem.Drawing.Bitmap object by decreasing its size. /// /// An existing .tif file name /// Maximum size in pixels of both height and width of the result Bitmap. ///If it is zero(0) then the maximagesize is auto set so the result image size to be smaller than 2 Gb of memory /// ///A new Bitmap object public static Bitmap ConvertTiffToBmp(string filename, int maximagesize) { using (Tiff tif = Tiff.Open(filename, "r")) { FieldValue[] value = tif.GetField(TiffTag.IMAGEWIDTH); int width = value[0].ToInt(); int BITSPERSAMPLE = tif.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); int SAMPLESPERPIXEL = tif.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt(); int bitsperpixel = BITSPERSAMPLE * SAMPLESPERPIXEL; PixelFormat pf = PixelFormat.Format24bppRgb; if (bitsperpixel == 24 ) pf = PixelFormat.Format24bppRgb; else if (bitsperpixel == 32) pf = PixelFormat.Format32bppArgb; value = tif.GetField(TiffTag.IMAGELENGTH); int height = value[0].ToInt(); if(maximagesize <= 0) { //asume 32bpp to calculate the scaling of the image to fit in 2gb memory double imscale =(double) width * height * 4 / 2000000000.0; if (imscale < 1) imscale = 1.0; maximagesize = (int)Math.Round(Math.Max(height / imscale, width / imscale)); } int imagesize = maximagesize; int nheights = (int)Math.Ceiling((double)height / imagesize); int nwidths = (int)Math.Ceiling((double)width / imagesize); nheights = Math.Max(nheights, nwidths); int sheight = height / nheights; int add = height % nheights; int rowsize = tif.ScanlineSize(); byte[] buffer = new byte[rowsize]; double aspect = (double)width / height; int nw = imagesize; int nh = (int)(nw / aspect); float scale = (float)nw / width; Bitmap image = new Bitmap(nw, nh, pf); Graphics g = Graphics.FromImage(image); for (int i = 0; i < nheights; i++) { int _h = sheight; if (i == nheights - 1) _h -= add; Bitmap bmp2 = new Bitmap(width, _h, pf); Rectangle rect = new Rectangle(0, 0, bmp2.Width, bmp2.Height); BitmapData bmpdata = bmp2.LockBits(rect, ImageLockMode.ReadWrite, bmp2.PixelFormat); try { for (int y = 0; y < bmp2.Height; y++) { int k = sheight * i + y; bool suc = tif.ReadScanline(buffer, 0, k, 0); System.Runtime.InteropServices.Marshal.Copy(buffer, 0, new IntPtr(bmpdata.Scan0.ToInt64() + bmpdata.Stride * y), buffer.Length); } bmp2.UnlockBits(bmpdata); g.DrawImage(bmp2, new Rectangle(0,(int)Math.Round( i * sheight * scale),(int)Math.Round( bmp2.Width * scale), (int)Math.Round(bmp2.Height * scale))); } catch (Exception ex) { return null; } } return image; } } [STAThread] public static void Main() { //select tiff images larger than 2gb size OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Tiff Files(*.tif)|*.tif||"; if (ofd.ShowDialog() != DialogResult.OK) return; string filename = ofd.FileName; // like @"c:\temp\someimage.tif"; //create a Bitmap with width and height smaller or equal to 10000 pixels Bitmap bmp = ConvertTiffToBmp(filename, 10000); //-or- //Bitmap bmp = ConvertTiffToBmp(filename, 0);//auto sizing to return a bitmap smaller than 2gb memory size // save it as BMP if (bmp != null) bmp.Save(filename + ".bmp", ImageFormat.Bmp); // or save it as JPG if (bmp != null) bmp.Save(filename + ".jpg", ImageFormat.Jpeg); //NOTE: If your VDF application is 32bit then the limit is lower and a much much smaller image should be used } } }