static void Main(string[] args) { // load image, this can by your 16-bit tif FIBITMAP dib = FreeImage.LoadEx("myfile.tif"); // convert to 8-bits dib = FreeImage.ConvertToGreyscale(dib); // rotate image by 90 degrees dib = FreeImage.Rotate(dib, 90); // save image FreeImage.SaveEx(dib, "newfile.png"); // unload bitmap FreeImage.UnloadEx(ref dib); }
public RenderTexture LoadImage(string path, bool isLinear = false, bool isGrayscale = false, bool doMipMaps = false, bool forceGC = false, bool premultiplyAlpha = false) { // default bits per channel //uint origBPP = outBPP = 0; bool successfullyLoadedRaw = false; int width = 0, height = 0; TextureFormat formatToLoad = TextureFormat.ARGB32; RenderTextureFormat rtFormat = RenderTextureFormat.ARGB32; bool forceGrayscaleAfterTexture2D = false; //System.Threading.Thread newThread = new System.Threading.Thread(() => { var loadType = System.IO.Path.GetExtension(path); FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT; switch (loadType) { case ".png": loadFlags = FREE_IMAGE_LOAD_FLAGS.PNG_IGNOREGAMMA; break; case ".jpg": case ".jpeg": loadFlags = FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE; break; } // Format is stored in 'format' on successfull load. FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN; FIBITMAP dib; bool isModifiedEXR = false; char yChar = 'Y'; byte yByte = Convert.ToByte(yChar); char rChar = 'R'; byte rByte = Convert.ToByte(rChar); //byte[] byteArray = File.ReadAllBytes(path); FileStream stream = null; if (Path.GetExtension(path).ToLower() == ".exr") { stream = new FileStream(path, FileMode.Open); stream.Position = 66; isModifiedEXR = (stream.ReadByte() == rByte); if (isModifiedEXR) { Debug.Log("<color=blue>*** This is a modified EXR </color>"); //byteArray[66] = yByte; stream.Position = 66; stream.WriteByte(yByte); stream.Position = 0; } } #if UNITY_STANDALONE_OSX if (stream == null) { stream = new FileStream(path, FileMode.Open); } dib = FreeImage.LoadFromStream(stream, loadFlags, ref format); #else dib = FreeImage.LoadEx(path, loadFlags, ref format); Debug.Log("Used Heap Size After FreeImage.LoadEx: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); #endif if (stream != null) { stream.Dispose(); GC.Collect(); Debug.Log("Used Heap Size After stream.Dispose: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); } if (isModifiedEXR) { using (FileStream fs = new FileStream(path, FileMode.Open)) { fs.Position = 66; fs.WriteByte(rByte); fs.Position = 0; } } rtFormat = RenderTextureFormat.ARGB32; try { // Error handling if (dib.IsNull) { return(null); } FREE_IMAGE_TYPE origInputType = FreeImage.GetImageType(dib); //Debug.Log("DIB for :" + path); // read bits per channel of loaded image uint origBPP = FreeImage.GetBPP(dib); var header = FreeImage.GetInfoHeaderEx(dib); //Debug.Log("original BPP:" + origBPP); //Debug.Log("origInputType:" + origInputType); // check here if we need to convert single channel textures to RGB or vice versa based on source input texture type and destination type expected FREE_IMAGE_TYPE destType = FREE_IMAGE_TYPE.FIT_UNKNOWN; switch (origInputType) { case FREE_IMAGE_TYPE.FIT_UINT16: if (!isGrayscale) { destType = FREE_IMAGE_TYPE.FIT_RGBAF; } else { destType = FREE_IMAGE_TYPE.FIT_FLOAT; } break; case FREE_IMAGE_TYPE.FIT_RGBF: case FREE_IMAGE_TYPE.FIT_RGBAF: destType = isGrayscale ? FREE_IMAGE_TYPE.FIT_FLOAT : FREE_IMAGE_TYPE.FIT_RGBAF; break; case FREE_IMAGE_TYPE.FIT_RGB16: case FREE_IMAGE_TYPE.FIT_RGBA16: destType = isGrayscale ? FREE_IMAGE_TYPE.FIT_FLOAT : FREE_IMAGE_TYPE.FIT_RGBAF; break; case FREE_IMAGE_TYPE.FIT_BITMAP: if (isGrayscale) { if (Mathf.IsPowerOfTwo(header.biWidth) && Mathf.IsPowerOfTwo(header.biHeight)) { if (!premultiplyAlpha) { dib = FreeImage.ConvertToGreyscale(dib); } } else { //int w = Mathf.NextPowerOfTwo(header.biWidth); //int h = Mathf.NextPowerOfTwo(header.biHeight); //FIBITMAP bitmap2 = FreeImage.Allocate(w, h, 8); //FreeImage.Paste(bitmap2, dib, 0, 0, 255); //FreeImage.UnloadEx(ref dib); //dib = bitmap2; forceGrayscaleAfterTexture2D = true; dib = FreeImage.ConvertTo32Bits(dib); } } else { dib = FreeImage.ConvertTo32Bits(dib); } destType = FREE_IMAGE_TYPE.FIT_BITMAP; break; } //// premultiply if need be //if (premultiplyAlpha) // FreeImage.PreMultiplyWithAlpha(dib); // convert to destination expected type if (destType != FREE_IMAGE_TYPE.FIT_UNKNOWN && origInputType != destType) { Debug.Log("Trying to convert from:" + origInputType + ", to:" + destType); dib = FreeImage.ConvertToType(dib, destType, false); } //GC.Collect(); Debug.Log("Used Heap Size After FreeImage.ConvertToType: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); //if (isModifiedEXR && origInputType == FREE_IMAGE_TYPE.FIT_FLOAT) width = (int)FreeImageAPI.FreeImage.GetWidth(dib); height = (int)FreeImageAPI.FreeImage.GetHeight(dib); uint bpp = FreeImage.GetBPP(dib); int pitch = (int)FreeImage.GetPitch(dib); long byteSize = pitch * height; Debug.Log("byteSize: " + byteSize); FREE_IMAGE_TYPE inputType = FreeImage.GetImageType(dib); if (doMipMaps) { byteSize = (long)(byteSize * 1.6666f); } //bytes = new byte[byteSize]; FreeImage.ConvertToRawBits(bytes, dib, pitch, bpp, 0, 0, 0, false); Debug.Log("Used Heap Size After FreeImage.ConvertToRawBits: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); FreeImage.UnloadEx(ref dib); //GC.Collect(); //Debug.Log("Used Heap Size After FreeImage.UnloadEx: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); // choose texture format formatToLoad = TextureFormat.ARGB32; Debug.Log("inputType:" + inputType); switch (inputType) { case FREE_IMAGE_TYPE.FIT_FLOAT: formatToLoad = TextureFormat.RFloat; if (origInputType == FREE_IMAGE_TYPE.FIT_UINT16) { rtFormat = RenderTextureFormat.RHalf; } else { rtFormat = RenderTextureFormat.RFloat; } break; case FREE_IMAGE_TYPE.FIT_UINT16: formatToLoad = TextureFormat.RHalf; rtFormat = RenderTextureFormat.RHalf; break; case FREE_IMAGE_TYPE.FIT_RGBA16: formatToLoad = TextureFormat.RGBAHalf; rtFormat = RenderTextureFormat.ARGBHalf; isLinear = true; break; case FREE_IMAGE_TYPE.FIT_RGBAF: formatToLoad = TextureFormat.RGBAFloat; if (origInputType == FREE_IMAGE_TYPE.FIT_RGBA16 || origInputType == FREE_IMAGE_TYPE.FIT_RGB16) { rtFormat = RenderTextureFormat.ARGBHalf; } else { rtFormat = RenderTextureFormat.ARGBFloat; } isLinear = true; break; case FREE_IMAGE_TYPE.FIT_BITMAP: //Iterate over all scanlines switch (bpp) { case 8: { formatToLoad = TextureFormat.Alpha8; rtFormat = RenderTextureFormat.R8; } break; case 16: formatToLoad = TextureFormat.RGBA4444; rtFormat = RenderTextureFormat.ARGB4444; break; case 24: if (FreeImage.IsLittleEndian()) { int length = bytes.Length; // make sure it's a multiple of 3 int factor = length / 3; int adjustedLength = factor * 3; // convert back to RGB for (int i = 0; i < adjustedLength; i += 3) { // convert BGR to RGB var r = bytes[i]; bytes[i] = bytes[i + 2]; bytes[i + 2] = r; } } formatToLoad = TextureFormat.RGB24; rtFormat = RenderTextureFormat.ARGB32; break; case 32: if (forceGrayscaleAfterTexture2D) { formatToLoad = TextureFormat.ARGB32; rtFormat = RenderTextureFormat.R8; } else { if (FreeImage.IsLittleEndian()) { int length = bytes.Length; // make sure it's a multiple of 4 int factor = length / 4; int adjustedLength = factor * 4; for (int j = 0; j < adjustedLength; j += 4) { // convert BGRA to ARGB var a = bytes[j]; var r = bytes[j + 1]; bytes[j] = bytes[j + 3]; bytes[j + 1] = bytes[j + 2]; bytes[j + 2] = r; bytes[j + 3] = a; } } formatToLoad = TextureFormat.ARGB32; rtFormat = RenderTextureFormat.ARGB32; } break; } break; } successfullyLoadedRaw = true; } catch (System.Exception ex) { Debug.LogError("Exception: " + ex.Message); } } //); //newThread.IsBackground = true; //newThread.Start(); //newThread.Join(); //outBPP = origBPP; if (successfullyLoadedRaw) { RenderTexture temp = LoadRawToTexture2D(bytes, width, height, formatToLoad, rtFormat, doMipMaps, isLinear, forceGC, premultiplyAlpha); //GC.Collect(); Debug.Log("Used Heap Size After LoadRawToTexture2D: " + Profiler.GetMonoUsedSizeLong() / 1024 / 1024); return(temp); } return(null); }
// Сохраняет выделенные файлы в TIFF private void btnTIFF_Click(object sender, EventArgs e) { if (0 == listView1.SelectedItems.Count) { return; } bool deleteFiles = chkDeleteFiles.Checked; // Удалять jpeg'и после создания tiff savePDFDialog.Filter = "Файлы TIFF|*.tif;*.tiff"; savePDFDialog.InitialDirectory = PDFInitialDir; if (DialogResult.OK != savePDFDialog.ShowDialog()) { return; } Cursor.Current = Cursors.WaitCursor; // Вариант с FreeImage - быстро, но сложнее и иногда инвертирует цвета // Сохранить первую страницу FIBITMAP dib_color = FreeImage.LoadEx(scanFileNames[listView1.SelectedItems[0].Index]); FIBITMAP dib = FreeImage.ConvertToGreyscale(dib_color); FreeImage.UnloadEx(ref dib_color); if (FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK == FreeImage.GetColorType(dib)) { FreeImage.Invert(dib); } deleteFiles = FreeImage.SaveEx(ref dib, savePDFDialog.FileName, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_CCITTFAX4, FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP, true); FreeImage.UnloadEx(ref dib); if (listView1.SelectedItems.Count > 1) { string tmpFile = Path.GetTempFileName() + ".tif"; FIBITMAP fib; FIBITMAP fib_color; FIMULTIBITMAP fmb = FreeImage.OpenMultiBitmapEx(savePDFDialog.FileName); // Добавить остальные страницы for (int i = 1; i < listView1.SelectedItems.Count; i++) { fib_color = FreeImage.LoadEx(scanFileNames[listView1.SelectedItems[i].Index]); fib = FreeImage.ConvertToGreyscale(fib_color); FreeImage.UnloadEx(ref fib_color); if (FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK == FreeImage.GetColorType(fib)) { FreeImage.Invert(fib); } FreeImage.SaveEx(ref fib, tmpFile, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_CCITTFAX4, FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP, true); fib = FreeImageAPI.FreeImage.LoadEx(tmpFile); FreeImage.AppendPage(fmb, fib); FreeImage.UnloadEx(ref fib); File.Delete(tmpFile); } deleteFiles = FreeImage.CloseMultiBitmapEx(ref fmb); } /* * // Вариант с ImageMagick - проще, но очень медленно * int s = 0; * * MagickImageCollection images = new MagickImageCollection(); * foreach (ListViewItem item in listView1.SelectedItems) * { * images.Add(scanFileNames[item.Index]); * images[s].Strip(); // По аналогии с PDF на всякий случай * images[s].Format = MagickFormat.Tif; * images[s].Settings.Compression = CompressionMethod.Group4; * images[s].Depth = 1; * s++; * } * try * { * images.Write(savePDFDialog.FileName, MagickFormat.Tif); * } * catch (MagickException me) * { * toolStripStatus.Text = me.Message; * deleteFiles = false; * } * images.Dispose(); */ if (deleteFiles) { btnDelete_Click(btnPDF, null); } Cursor.Current = Cursors.Default; }