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();
        //}
    }