private void SaveHelper(TextureFormat format, byte[] rawBytes, int texwidth, int texheight, bool convertTo16, ChannelsPerMap exportChannels, string imagePath, FREE_IMAGE_FORMAT destFormat, FREE_IMAGE_SAVE_FLAGS saveFlags) { int bytesPerPixel = 4; FREE_IMAGE_TYPE imageType = FREE_IMAGE_TYPE.FIT_BITMAP; switch (format) { case TextureFormat.RGBAHalf: imageType = FREE_IMAGE_TYPE.FIT_RGBA16; bytesPerPixel = 8; break; case TextureFormat.RGBAFloat: imageType = FREE_IMAGE_TYPE.FIT_RGBAF; bytesPerPixel = 16; break; case TextureFormat.ARGB32: imageType = FREE_IMAGE_TYPE.FIT_BITMAP; bytesPerPixel = 4; //tex.GetPixels32(); //ConvertBGRAtoARGBScanline(dib); // convert back to ARGB if (FreeImage.IsLittleEndian()) { for (int j = 0; j < rawBytes.Length; j += 4) { // convert BGRA to ARGB var a = rawBytes[j]; var r = rawBytes[j + 1]; rawBytes[j] = rawBytes[j + 3]; rawBytes[j + 1] = rawBytes[j + 2]; rawBytes[j + 2] = r; rawBytes[j + 3] = a; } } break; case TextureFormat.RGB24: imageType = FREE_IMAGE_TYPE.FIT_BITMAP; bytesPerPixel = 3; if (FreeImage.IsLittleEndian()) { // convert back to RGB for (int i = 0; i < rawBytes.Length; i += 3) { // convert BGR to RGB var r = rawBytes[i]; rawBytes[i] = rawBytes[i + 2]; rawBytes[i + 2] = r; } } break; } FIBITMAP dib = FreeImage.ConvertFromRawBits(rawBytes, imageType, texwidth, texheight, texwidth * bytesPerPixel, (uint)bytesPerPixel * 8, 0, 0, 0, false); if (dib.IsNull) { Debug.LogError("Dib is NULL!!!"); } rawBytes = null; GC.Collect(); if (convertTo16) { dib = FreeImage.ConvertToType(dib, FREE_IMAGE_TYPE.FIT_RGBA16, false); format = TextureFormat.RGBAHalf; } switch (exportChannels) { case ChannelsPerMap.RGB: // remove alpha channel switch (format) { case TextureFormat.RGBAFloat: dib = FreeImage.ConvertToRGBF(dib); break; case TextureFormat.RGBAHalf: dib = FreeImage.ConvertToType(dib, FREE_IMAGE_TYPE.FIT_RGB16, false); break; case TextureFormat.ARGB32: dib = FreeImage.ConvertTo24Bits(dib); break; } break; case ChannelsPerMap.R: dib = FreeImage.GetChannel(dib, FREE_IMAGE_COLOR_CHANNEL.FICC_RED); break; // if already RGBA don't need to do any conversion default: break; } try { using (FileStream saveStream = new FileStream(imagePath, FileMode.OpenOrCreate, FileAccess.Write)) { Debug.Log("FreeImage::FileSaveSuccess: " + imagePath + " :" + FreeImage.SaveToStream(ref dib, saveStream, destFormat, saveFlags, true)); } } catch (Exception e) { Debug.LogException(e); //progressBar.DoneProgress(); FreeImage.UnloadEx(ref dib); throw; } //if (progressBar != null) //{ // UnityThreadHelper.Dispatcher.Dispatch(() => // { // progressBar.Increment(); // }); //} }
// public Texture2D testTexture; public void SaveImage(Texture2D texture, string imagePath, ChannelsPerMap exportChannels, bool convertTo16 = false, bool waitForThread = false) { // testTexture = texture; var format = texture.format; FREE_IMAGE_SAVE_FLAGS saveFlags = FREE_IMAGE_SAVE_FLAGS.DEFAULT; FREE_IMAGE_FORMAT destFormat = FREE_IMAGE_FORMAT.FIF_BMP; var saveType = System.IO.Path.GetExtension(imagePath); switch (saveType) { case ".png": destFormat = FREE_IMAGE_FORMAT.FIF_PNG; saveFlags = FREE_IMAGE_SAVE_FLAGS.PNG_Z_BEST_SPEED; if (format == TextureFormat.RGBAFloat && !convertTo16) { Debug.LogError("Can't save HDR image as PNG"); return; //dib = FreeImage.TmoDrago03(dib, 1, 1); } break; case ".exr": destFormat = FREE_IMAGE_FORMAT.FIF_EXR; saveFlags = FREE_IMAGE_SAVE_FLAGS.EXR_FLOAT | FREE_IMAGE_SAVE_FLAGS.EXR_PIZ; break; case ".tif": case ".tiff": destFormat = FREE_IMAGE_FORMAT.FIF_TIFF; saveFlags = FREE_IMAGE_SAVE_FLAGS.TIFF_LZW; break; case ".tga": destFormat = FREE_IMAGE_FORMAT.FIF_TARGA; saveFlags = FREE_IMAGE_SAVE_FLAGS.EXR_NONE; // same value as TARGA_SAVE_RLE (not present in FreeImage.NET for some reason) if (format == TextureFormat.RGBAFloat) { Debug.LogError("Can't save HDR image as TGA"); return; } break; case ".psd": destFormat = FREE_IMAGE_FORMAT.FIF_PSD; break; case ".jpg": case ".jpeg": destFormat = FREE_IMAGE_FORMAT.FIF_JPEG; saveFlags = FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYSUPERB | FREE_IMAGE_SAVE_FLAGS.JPEG_SUBSAMPLING_420 | FREE_IMAGE_SAVE_FLAGS.JPEG_OPTIMIZE; break; } Debug.Log("destFormat: " + destFormat); //int bppDest = 0; //int bppSource = 0; var rawBytes = texture.GetRawTextureData(); Debug.Log("texture2d.width, texture2d.height, format:" + texture.width + ", " + texture.height + " , " + format); int texwidth = texture.width; int texheight = texture.height; Destroy(texture); Resources.UnloadUnusedAssets(); //Create new thread then save image to file if (waitForThread || texwidth >= 8096) { Debug.Log("Saving image synchronously."); SaveHelper(format, rawBytes, texwidth, texheight, convertTo16, exportChannels, imagePath, destFormat, saveFlags); } else { new System.Threading.Thread(() => { Debug.Log("Saving image asynchronously with threads."); SaveHelper(format, rawBytes, texwidth, texheight, convertTo16, exportChannels, imagePath, destFormat, saveFlags); }).Start(); } //if (waitForThread) //{ // newThread.Join(); //} }