/// <summary> /// Converts a FreeImage bitmap from one color depth to another. /// If the conversion fails the original FreeImage bitmap is returned. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="conversion">The desired output format.</param> /// <param name="ditherMethod">Dither algorithm when converting with /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param> /// <param name="unloadSource">When true the structure will be unloaded on success.</param> /// <returns>Handle to a FreeImage bitmap.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> is null.</exception> public static FIBITMAP ConvertColorDepth( FIBITMAP dib, FREE_IMAGE_COLOR_DEPTH conversion, FREE_IMAGE_DITHER ditherMethod, bool unloadSource) { return ConvertColorDepth( dib, conversion, 128, ditherMethod, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, unloadSource); }
/// <summary> /// Converts a FreeImage bitmap from one color depth to another. /// If the conversion fails the original FreeImage bitmap is returned. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="conversion">The desired output format.</param> /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param> /// <param name="unloadSource">When true the structure will be unloaded on success.</param> /// <returns>Handle to a FreeImage bitmap.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> is null.</exception> public static FIBITMAP ConvertColorDepth( FIBITMAP dib, FREE_IMAGE_COLOR_DEPTH conversion, FREE_IMAGE_QUANTIZE quantizationMethod, bool unloadSource) { return ConvertColorDepth( dib, conversion, 128, FREE_IMAGE_DITHER.FID_FS, quantizationMethod, unloadSource); }
/// <summary> /// Changes a bitmaps color depth. /// Used by SaveEx and SaveToStream /// </summary> private static FIBITMAP PrepareBitmapColorDepth(FIBITMAP dibToSave, FREE_IMAGE_FORMAT format, FREE_IMAGE_COLOR_DEPTH colorDepth) { int bpp = (int)GetBPP(dibToSave); int targetBpp = (int)(colorDepth & FREE_IMAGE_COLOR_DEPTH.FICD_COLOR_MASK); if (colorDepth != FREE_IMAGE_COLOR_DEPTH.FICD_AUTO) { // A fix colordepth was chosen if (FIFSupportsExportBPP(format, targetBpp)) { dibToSave = ConvertColorDepth(dibToSave, colorDepth, false); } else { throw new ArgumentException("FreeImage\n\nFreeImage Library plugin " + GetFormatFromFIF(format) + " is unable to write images with a color depth of " + targetBpp + " bpp."); } } else { // Auto selection was chosen if (!FIFSupportsExportBPP(format, bpp)) { // The color depth is not supported int bppUpper = bpp; int bppLower = bpp; // Check from the bitmaps current color depth in both directions do { bppUpper = GetNextColorDepth(bppUpper); if (FIFSupportsExportBPP(format, bppUpper)) { dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppUpper, false); break; } bppLower = GetPrevousColorDepth(bppLower); if (FIFSupportsExportBPP(format, bppLower)) { dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppLower, false); break; } } while (!((bppLower == 0) && (bppUpper == 0))); } } return dibToSave; }
/// <summary> /// Converts a FreeImage bitmap from one color depth to another. /// If the conversion fails the original FreeImage bitmap is returned. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="conversion">The desired output format.</param> /// <param name="threshold">Threshold value when converting with /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param> /// <param name="unloadSource">When true the structure will be unloaded on success.</param> /// <returns>Handle to a FreeImage bitmap.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> is null.</exception> public static FIBITMAP ConvertColorDepth( FIBITMAP dib, FREE_IMAGE_COLOR_DEPTH conversion, byte threshold, bool unloadSource) { return ConvertColorDepth( dib, conversion, threshold, FREE_IMAGE_DITHER.FID_FS, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, unloadSource); }
/// <summary> /// Converts a FreeImage bitmap from one color depth to another. /// If the conversion fails the original FreeImage bitmap is returned. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="conversion">The desired output format.</param> /// <returns>Handle to a FreeImage bitmap.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> is null.</exception> public static FIBITMAP ConvertColorDepth( FIBITMAP dib, FREE_IMAGE_COLOR_DEPTH conversion) { return ConvertColorDepth( dib, conversion, 128, FREE_IMAGE_DITHER.FID_FS, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, false); }
/// <summary> /// Converts a FreeImage bitmap from one color depth to another. /// If the conversion fails the original FreeImage bitmap is returned. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="conversion">The desired output format.</param> /// <param name="threshold">Threshold value when converting with /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param> /// <param name="ditherMethod">Dither algorithm when converting with /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param> /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param> /// <param name="unloadSource">When true the structure will be unloaded on success.</param> /// <returns>Handle to a FreeImage bitmap.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> is null.</exception> internal static FIBITMAP ConvertColorDepth( FIBITMAP dib, FREE_IMAGE_COLOR_DEPTH conversion, byte threshold, FREE_IMAGE_DITHER ditherMethod, FREE_IMAGE_QUANTIZE quantizationMethod, bool unloadSource) { if (dib.IsNull) { throw new ArgumentNullException("dib"); } FIBITMAP result = 0; FIBITMAP dibTemp = 0; uint bpp = GetBPP(dib); bool reorderPalette = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE) > 0); bool forceGreyscale = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) > 0); switch (conversion & (FREE_IMAGE_COLOR_DEPTH)0xFF) { case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD: if (bpp != 1) { result = Threshold(dib, threshold); } else { bool isGreyscale = IsGreyscaleImage(dib); if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale)) { result = Threshold(dib, threshold); } } break; case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER: if (bpp != 1) { result = Dither(dib, ditherMethod); } else { bool isGreyscale = IsGreyscaleImage(dib); if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale)) { result = Dither(dib, ditherMethod); } } break; case FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP: if (bpp != 4) { // Special case when 1bpp and FIC_PALETTE if (forceGreyscale && (bpp == 1) && (GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_PALETTE)) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo4Bits(dibTemp); Unload(dibTemp); } // All other cases are converted directly else { result = ConvertTo4Bits(dib); } } else { bool isGreyscale = IsGreyscaleImage(dib); if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale)) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo4Bits(dibTemp); Unload(dibTemp); } } break; case FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP: if (bpp != 8) { if (forceGreyscale) { result = ConvertToGreyscale(dib); } else { dibTemp = ConvertTo24Bits(dib); result = ColorQuantize(dibTemp, quantizationMethod); Unload(dibTemp); } } else { bool isGreyscale = IsGreyscaleImage(dib); if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale)) { result = ConvertToGreyscale(dib); } } break; case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP_555: if (forceGreyscale) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo16Bits555(dibTemp); Unload(dibTemp); } else if (bpp != 16 || GetRedMask(dib) != FI16_555_RED_MASK || GetGreenMask(dib) != FI16_555_GREEN_MASK || GetBlueMask(dib) != FI16_555_BLUE_MASK) { result = ConvertTo16Bits555(dib); } break; case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP: if (forceGreyscale) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo16Bits565(dibTemp); Unload(dibTemp); } else if (bpp != 16 || GetRedMask(dib) != FI16_565_RED_MASK || GetGreenMask(dib) != FI16_565_GREEN_MASK || GetBlueMask(dib) != FI16_565_BLUE_MASK) { result = ConvertTo16Bits565(dib); } break; case FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP: if (forceGreyscale) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo24Bits(dibTemp); Unload(dibTemp); } else if (bpp != 24) { result = ConvertTo24Bits(dib); } break; case FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP: if (forceGreyscale) { dibTemp = ConvertToGreyscale(dib); result = ConvertTo32Bits(dibTemp); Unload(dibTemp); } else if (bpp != 32) { result = ConvertTo32Bits(dib); } break; } if (result.IsNull) { return dib; } if (unloadSource) { Unload(dib); } return result; }
/// <summary> /// Saves a previously loaded FreeImage bitmap to a stream. /// The stream must be set to the correct position before calling SaveToStream. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="stream">The stream to write to.</param> /// <param name="format">Format of the image.</param> /// <param name="flags">Flags to enable or disable plugin-features.</param> /// <param name="colorDepth">The new color depth of the bitmap. /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should /// take the best suitable color depth. /// If a color depth is selected that the provided format cannot write an /// error-message will be thrown.</param> /// <param name="unloadSource">When true the structure will be unloaded on success.</param> /// <returns>Returns true on success, false on failure.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception> /// <exception cref="ArgumentException"> /// <paramref name="stream"/> cannot write.</exception> public static bool SaveToStream( ref FIBITMAP dib, Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags, FREE_IMAGE_COLOR_DEPTH colorDepth, bool unloadSource) { if (dib.IsNull) { throw new ArgumentNullException("dib"); } if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanWrite) { throw new ArgumentException("stream is not capable of writing."); } if ((!FIFSupportsWriting(format)) || (!FIFSupportsExportType(format, FREE_IMAGE_TYPE.FIT_BITMAP))) { return false; } FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth); bool result = false; try { // Create a 'FreeImageIO' structure for calling 'SaveToHandle' FreeImageIO io = FreeImageStreamIO.io; using (fi_handle handle = new fi_handle(stream)) { result = SaveToHandle(format, dibToSave, ref io, handle, flags); } } catch { // Always unload a temporary created bitmap. if (dibToSave != dib) { UnloadEx(ref dibToSave); } // On success unload the bitmap if (result && unloadSource) { UnloadEx(ref dib); } } return result; }
/// <summary> /// Saves a previously loaded FreeImage bitmap to a stream. /// The stream must be set to the correct position before calling SaveToStream. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="stream">The stream to write to.</param> /// <param name="format">Format of the image.</param> /// <param name="flags">Flags to enable or disable plugin-features.</param> /// <param name="colorDepth">The new color depth of the bitmap. /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should /// take the best suitable color depth. /// If a color depth is selected that the provided format cannot write an /// error-message will be thrown.</param> /// <returns>Returns true on success, false on failure.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception> /// <exception cref="ArgumentException"> /// <paramref name="stream"/> cannot write.</exception> public static bool SaveToStream( FIBITMAP dib, Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags, FREE_IMAGE_COLOR_DEPTH colorDepth) { return SaveToStream( ref dib, stream, format, flags, colorDepth, false); }
/// <summary> /// Saves a previously loaded FreeImage bitmap to a file. /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> /// the format is taken off the filename. /// If no suitable format was found false will be returned. /// Save flags can be provided by the flags parameter. /// The bitmaps color depth can be set by 'colorDepth'. /// If set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> a suitable color depth /// will be taken if available. /// </summary> /// <param name="dib">Handle to a FreeImage bitmap.</param> /// <param name="filename">The complete name of the file to save to. /// The extension will be corrected if it is no valid extension for the /// selected format or if no extension was specified.</param> /// <param name="format">Format of the image. If the format should be taken from the /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param> /// <param name="flags">Flags to enable or disable plugin-features.</param> /// <param name="colorDepth">The new color depth of the bitmap. /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if Save should take the /// best suitable color depth. /// If a color depth is selected that the provided format cannot write an /// error-message will be thrown.</param> /// <param name="unloadSource">When true the structure will be unloaded on success. /// If the function failed and returned false, the bitmap was not unloaded.</param> /// <returns>Returns true on success, false on failure.</returns> /// <exception cref="ArgumentException"> /// A direct color conversion failed.</exception> /// <exception cref="ArgumentNullException"> /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception> public static bool SaveEx( ref FIBITMAP dib, string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags, FREE_IMAGE_COLOR_DEPTH colorDepth, bool unloadSource) { if (dib.IsNull) { throw new ArgumentNullException("dib"); } if (filename == null) { throw new ArgumentNullException("filename"); } bool result = false; // Gets format from filename if the format is unknown if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN) { format = GetFIFFromFilename(filename); } if (format != FREE_IMAGE_FORMAT.FIF_UNKNOWN) { // Checks writing support if (FIFSupportsWriting(format) && FIFSupportsExportType(format, GetImageType(dib))) { // Check valid filename and correct it if needed if (!IsFilenameValidForFIF(format, filename)) { int index = filename.LastIndexOf('.'); string extension = GetPrimaryExtensionFromFIF(format); if (index == -1) { // We have no '.' (dot) so just add the extension filename += "." + extension; } else { // Overwrite the old extension filename = filename.Substring(0, filename.LastIndexOf('.')) + extension; } } FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth); result = Save(format, dibToSave, filename, flags); // Always unload a temporary created bitmap. if (dibToSave != dib) { UnloadEx(ref dibToSave); } // On success unload the bitmap if (result && unloadSource) { UnloadEx(ref dib); } } } return result; }