using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
namespace FastReport.Utils
{
internal static class ImageHelper
{
public static Bitmap CloneBitmap(Image source)
{
if (source == null)
return null;
Bitmap image = new Bitmap(source.Width, source.Height);
image.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics g = Graphics.FromImage(image))
{
g.DrawImageUnscaled(source, 0, 0);
}
return image;
// this can throw OutOfMemory when creating a grayscale image from a cloned bitmap
// return source.Clone() as Bitmap;
}
public static void Save(Image image, Stream stream)
{
Save(image, stream, image.GetImageFormat());
}
public static void Save(Image image, string fileName, ImageFormat format)
{
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
Save(image, stream, format);
}
}
public static void Save(Image image, Stream stream, ImageFormat format)
{
if (image == null)
return;
if (image is Bitmap)
{
if (format == ImageFormat.Icon)
SaveAsIcon(image, stream, true);
else
image.Save(stream, format);
}
else if (image is Metafile)
{
Metafile emf = null;
using (Bitmap bmp = new Bitmap(1, 1))
using (Graphics g = Graphics.FromImage(bmp))
{
IntPtr hdc = g.GetHdc();
emf = new Metafile(stream, hdc);
g.ReleaseHdc(hdc);
}
using (Graphics g = Graphics.FromImage(emf))
{
g.DrawImage(image, 0, 0);
}
}
}
public static bool SaveAndConvert(Image image, Stream stream, ImageFormat format)
{
if (image == null)
return false;
if (format == ImageFormat.Jpeg || format == ImageFormat.Gif
|| format == ImageFormat.Tiff || format == ImageFormat.Bmp
|| format == ImageFormat.Png
|| format == ImageFormat.MemoryBmp)
{
if (image is Bitmap)
{
if (format == ImageFormat.MemoryBmp)
throw new Exception(Res.Get("Export,Image,ImageParceFormatException"));
image.Save(stream, format);
return true;
}
//from mf to bitmap
using (Metafile metafile = image as Metafile)
using (Bitmap bitmap = new Bitmap(image.Width, image.Height))
{
bitmap.SetResolution(96F, 96F);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawImage(metafile, 0, 0, (float)image.Width, (float)image.Height);
g.Dispose();
}
bitmap.Save(stream, format);
}
return true;
}
else if (format == ImageFormat.Icon)
{
return SaveAsIcon(image, stream, true);
}
else if (format == ImageFormat.Wmf || format == ImageFormat.Emf)
{
if (image is Metafile)
{
Metafile emf = null;
using (Bitmap bmp = new Bitmap(1, 1))
using (Graphics g = Graphics.FromImage(bmp))
{
IntPtr hdc = g.GetHdc();
emf = new Metafile(stream, hdc);
g.ReleaseHdc(hdc);
}
using (Graphics g = Graphics.FromImage(emf))
{
g.DrawImage(image, 0, 0);
}
return true;
}
}
//throw new Exception(Res.Get("Export,Image,ImageParceFormatException")); // we cant convert image to exif or from bitmap to mf
return false;
}
public static byte[] Load(string fileName)
{
if (!String.IsNullOrEmpty(fileName))
return File.ReadAllBytes(fileName);
return null;
}
public static Image Load(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
try
{
#if CROSSPLATFORM
// TODO memory leaks image converter
return Image.FromStream(new MemoryStream(bytes));
#else
return new ImageConverter().ConvertFrom(bytes) as Image;
#endif
}
catch
{
Bitmap errorBmp = new Bitmap(10, 10);
using (Graphics g = Graphics.FromImage(errorBmp))
{
g.DrawLine(Pens.Red, 0, 0, 10, 10);
g.DrawLine(Pens.Red, 0, 10, 10, 0);
}
return errorBmp;
}
}
return null;
}
public static byte[] LoadURL(string url)
{
if (!String.IsNullOrEmpty(url))
{
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc0 | 0x300 | 0xc00);
using (WebClient web = new WebClient())
{
return web.DownloadData(url);
}
}
return null;
}
public static Bitmap GetTransparentBitmap(Image source, float transparency)
{
if (source == null)
return null;
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.Matrix33 = 1 - transparency;
ImageAttributes imageAttributes = new ImageAttributes();
imageAttributes.SetColorMatrix(
colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
int width = source.Width;
int height = source.Height;
Bitmap image = new Bitmap(width, height);
image.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics g = Graphics.FromImage(image))
{
g.Clear(Color.Transparent);
g.DrawImage(
source,
new Rectangle(0, 0, width, height),
0, 0, width, height,
GraphicsUnit.Pixel,
imageAttributes);
}
return image;
}
public static Bitmap GetGrayscaleBitmap(Image source)
{
Bitmap grayscaleBitmap = new Bitmap(source.Width, source.Height, source.PixelFormat);
// Red should be converted to (R*.299)+(G*.587)+(B*.114)
// Green should be converted to (R*.299)+(G*.587)+(B*.114)
// Blue should be converted to (R*.299)+(G*.587)+(B*.114)
// Alpha should stay the same.
ColorMatrix grayscaleMatrix = new ColorMatrix(new float[][]{
new float[] {0.299f, 0.299f, 0.299f, 0, 0},
new float[] {0.587f, 0.587f, 0.587f, 0, 0},
new float[] {0.114f, 0.114f, 0.114f, 0, 0},
new float[] { 0, 0, 0, 1, 0},
new float[] { 0, 0, 0, 0, 1}});
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(grayscaleMatrix);
// Use a Graphics object from the new image
using (Graphics graphics = Graphics.FromImage(grayscaleBitmap))
{
// Draw the original image using the ImageAttributes we created
graphics.DrawImage(source,
new Rectangle(0, 0, grayscaleBitmap.Width, grayscaleBitmap.Height),
0, 0, grayscaleBitmap.Width, grayscaleBitmap.Height,
GraphicsUnit.Pixel, attributes);
}
return grayscaleBitmap;
}
///
/// Converts a PNG image to a icon (ico)
///
/// The input image
/// The output stream
/// Preserve the aspect ratio
/// Wether or not the icon was succesfully generated
public static bool SaveAsIcon(Image image, Stream output, bool preserveAspectRatio = false)
{
int size = 256;
float width = size, height = size;
if (preserveAspectRatio)
{
if (image.Width > image.Height)
height = ((float)image.Height / image.Width) * size;
else
width = ((float)image.Width / image.Height) * size;
}
var newBitmap = new Bitmap(image, new Size((int)width, (int)height));
if (newBitmap == null)
return false;
// save the resized png into a memory stream for future use
using (MemoryStream memoryStream = new MemoryStream())
{
newBitmap.Save(memoryStream, ImageFormat.Png);
var iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write((int)(6 + 16));
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
}
return true;
}
}
public static class ImageExtension
{
///
/// Returns an Image format.
///
public static ImageFormat GetImageFormat(this Image bitmap)
{
if (bitmap == null || bitmap.RawFormat == null)
return null;
ImageFormat format = null;
if (ImageFormat.Jpeg.Equals(bitmap.RawFormat))
{
format = ImageFormat.Jpeg;
}
else if (ImageFormat.Gif.Equals(bitmap.RawFormat))
{
format = ImageFormat.Gif;
}
else if (ImageFormat.Png.Equals(bitmap.RawFormat))
{
format = ImageFormat.Png;
}
else if (ImageFormat.Emf.Equals(bitmap.RawFormat))
{
format = ImageFormat.Emf;
}
else if (ImageFormat.Icon.Equals(bitmap.RawFormat))
{
format = ImageFormat.Icon;
}
else if (ImageFormat.Tiff.Equals(bitmap.RawFormat))
{
format = ImageFormat.Tiff;
}
else if (ImageFormat.Bmp.Equals(bitmap.RawFormat) || ImageFormat.MemoryBmp.Equals(bitmap.RawFormat)) // MemoryBmp format raises a GDI exception
{
format = ImageFormat.Bmp;
}
else if (ImageFormat.Wmf.Equals(bitmap.RawFormat))
{
format = ImageFormat.Wmf;
}
if (format != null)
return format;
return ImageFormat.Bmp;
}
}
}