public Image Apply(Image sourceImage, Matrix matrix) { using (WuQuantizer quantizer = new WuQuantizer((Bitmap)sourceImage)) { int colorCount = quantizer.GetColorCount(); if (colorCount > Colors) { try { return quantizer.GetQuantizedImage(Colors); } catch (Exception e) { LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } return null; }
/// <summary> /// Create an image from a surface with the settings from the output settings applied /// </summary> /// <param name="surface"></param> /// <param name="outputSettings"></param> /// <param name="imageToSave"></param> /// <returns>true if the image must be disposed</returns> public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) { bool disposeImage = false; ImageFormat imageFormat = null; switch (outputSettings.Format) { case OutputFormat.bmp: imageFormat = ImageFormat.Bmp; break; case OutputFormat.gif: imageFormat = ImageFormat.Gif; break; case OutputFormat.jpg: imageFormat = ImageFormat.Jpeg; break; case OutputFormat.tiff: imageFormat = ImageFormat.Tiff; break; case OutputFormat.greenshot: case OutputFormat.png: default: imageFormat = ImageFormat.Png; break; } if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) { // We save the image of the surface, this should not be disposed imageToSave = surface.Image; } else { // We create the export image of the surface to save imageToSave = surface.GetImageForExport(); disposeImage = true; } // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! if (outputSettings.Format != OutputFormat.greenshot) { Image tmpImage; if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) { // apply effects, if there are any Point ignoreOffset; tmpImage = ImageHelper.ApplyEffects((Bitmap)imageToSave, outputSettings.Effects, out ignoreOffset); if (tmpImage != null) { if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; disposeImage = true; } } // check for color reduction, forced or automatically, only when the DisableReduceColors is false if (!outputSettings.DisableReduceColors && (conf.OutputFileAutoReduceColors || outputSettings.ReduceColors)) { bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors)) { using (WuQuantizer quantizer = new WuQuantizer((Bitmap)imageToSave)) { int colorCount = quantizer.GetColorCount(); LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); if (outputSettings.ReduceColors || colorCount < 256) { try { LOG.Info("Reducing colors on bitmap to 256."); tmpImage = quantizer.GetQuantizedImage(256); if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; // Make sure the "new" image is disposed disposeImage = true; } catch (Exception e) { LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } } else if (isAlpha && !outputSettings.ReduceColors) { LOG.Info("Skipping 'optional' color reduction as the image has alpha"); } } } return(disposeImage); }
/// <summary> /// Create an image from a surface with the settings from the output settings applied /// </summary> /// <param name="surface"></param> /// <param name="outputSettings"></param> /// <param name="imageToSave"></param> /// <returns>true if the image must be disposed</returns> public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) { bool disposeImage = false; if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) { // We save the image of the surface, this should not be disposed imageToSave = surface.Image; } else { // We create the export image of the surface to save imageToSave = surface.GetImageForExport(); disposeImage = true; } // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! if (outputSettings.Format == OutputFormat.greenshot) { return(disposeImage); } Image tmpImage; if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) { // apply effects, if there are any using (Matrix matrix = new Matrix()) { tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix); } if (tmpImage != null) { if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; disposeImage = true; } } // check for color reduction, forced or automatically, only when the DisableReduceColors is false if (outputSettings.DisableReduceColors || (!CoreConfig.OutputFileAutoReduceColors && !outputSettings.ReduceColors)) { return(disposeImage); } bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); if (outputSettings.ReduceColors || (!isAlpha && CoreConfig.OutputFileAutoReduceColors)) { using (var quantizer = new WuQuantizer((Bitmap)imageToSave)) { int colorCount = quantizer.GetColorCount(); Log.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); if (!outputSettings.ReduceColors && colorCount >= 256) { return(disposeImage); } try { Log.Info("Reducing colors on bitmap to 256."); tmpImage = quantizer.GetQuantizedImage(CoreConfig.OutputFileReduceColorsTo); if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; // Make sure the "new" image is disposed disposeImage = true; } catch (Exception e) { Log.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } else if (isAlpha && !outputSettings.ReduceColors) { Log.Info("Skipping 'optional' color reduction as the image has alpha"); } return(disposeImage); }
/// <summary> /// Create an image from a surface with the settings from the output settings applied /// </summary> /// <param name="surface"></param> /// <param name="outputSettings"></param> /// <param name="imageToSave"></param> /// <returns>true if the image must be disposed</returns> public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave) { bool disposeImage = false; ImageFormat imageFormat = null; switch (outputSettings.Format) { case OutputFormat.bmp: imageFormat = ImageFormat.Bmp; break; case OutputFormat.gif: imageFormat = ImageFormat.Gif; break; case OutputFormat.jpg: imageFormat = ImageFormat.Jpeg; break; case OutputFormat.tiff: imageFormat = ImageFormat.Tiff; break; case OutputFormat.greenshot: case OutputFormat.png: default: imageFormat = ImageFormat.Png; break; } if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly) { // We save the image of the surface, this should not be disposed imageToSave = surface.Image; } else { // We create the export image of the surface to save imageToSave = surface.GetImageForExport(); disposeImage = true; } // The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise! if (outputSettings.Format != OutputFormat.greenshot) { Image tmpImage; if (outputSettings.Effects != null && outputSettings.Effects.Count > 0) { // apply effects, if there are any Point ignoreOffset; tmpImage = ImageHelper.ApplyEffects((Bitmap)imageToSave, outputSettings.Effects, out ignoreOffset); if (tmpImage != null) { if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; disposeImage = true; } } // check for color reduction, forced or automatically, only when the DisableReduceColors is false if (!outputSettings.DisableReduceColors && (conf.OutputFileAutoReduceColors || outputSettings.ReduceColors)) { bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat); if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors)) { using (WuQuantizer quantizer = new WuQuantizer((Bitmap)imageToSave)) { int colorCount = quantizer.GetColorCount(); LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); if (outputSettings.ReduceColors || colorCount < 256) { try { LOG.Info("Reducing colors on bitmap to 256."); tmpImage = quantizer.GetQuantizedImage(256); if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; // Make sure the "new" image is disposed disposeImage = true; } catch (Exception e) { LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } } else if (isAlpha && !outputSettings.ReduceColors) { LOG.Info("Skipping 'optional' color reduction as the image has alpha"); } } } return disposeImage; }
/// <summary> /// Saves image to stream with specified quality /// </summary> public static void SaveToStream(Image imageToSave, Stream stream, OutputFormat extension, int quality, bool reduceColors) { ImageFormat imageFormat = null; bool disposeImage = false; switch (extension) { case OutputFormat.bmp: imageFormat = ImageFormat.Bmp; break; case OutputFormat.gif: imageFormat = ImageFormat.Gif; break; case OutputFormat.jpg: imageFormat = ImageFormat.Jpeg; break; case OutputFormat.png: imageFormat = ImageFormat.Png; break; case OutputFormat.tiff: imageFormat = ImageFormat.Tiff; break; default: imageFormat = ImageFormat.Png; break; } // Fix for Bug #3468436, force quantizing when output format is gif as this has only 256 colors! if (ImageFormat.Gif.Equals(imageFormat)) { reduceColors = true; } // Removing transparency if it's not supported if (imageFormat != ImageFormat.Png) { imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb); disposeImage = true; } // check for color reduction, forced or automatically if (conf.OutputFileAutoReduceColors || reduceColors) { WuQuantizer quantizer = new WuQuantizer((Bitmap)imageToSave); int colorCount = quantizer.GetColorCount(); LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount); if (reduceColors || colorCount < 256) { try { LOG.Info("Reducing colors on bitmap to 255."); Image tmpImage = quantizer.GetQuantizedImage(255); if (disposeImage) { imageToSave.Dispose(); } imageToSave = tmpImage; // Make sure the "new" image is disposed disposeImage = true; } catch (Exception e) { LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e); } } } else { LOG.Info("Skipping color reduction test, OutputFileAutoReduceColors is set to false."); } try { // Create meta-data PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot"); if (softwareUsedPropertyItem != null) { try { imageToSave.SetPropertyItem(softwareUsedPropertyItem); } catch (ArgumentException) { LOG.WarnFormat("Image of type {0} do not support property {1}", imageFormat, softwareUsedPropertyItem.Id); } } LOG.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat); if (imageFormat == ImageFormat.Jpeg) { EncoderParameters parameters = new EncoderParameters(1); parameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(Encoder.Quality, quality); ImageCodecInfo[] ies = ImageCodecInfo.GetImageEncoders(); imageToSave.Save(stream, ies[1], parameters); } else if (imageFormat != ImageFormat.Png && Image.IsAlphaPixelFormat(imageToSave.PixelFormat)) { // No transparency in target format using (Bitmap tmpBitmap = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb)) { tmpBitmap.Save(stream, imageFormat); } } else { imageToSave.Save(stream, imageFormat); } } finally { // cleanup if needed if (disposeImage && imageToSave != null) { imageToSave.Dispose(); } } }