Files
Disco/Disco.Services/Extensions/ImagingExtensions.cs
T
Gary Sharp 5ea9a814d6 Pdf Import Rewrite
Pdf Import rewritten to greatly improve QR Code detection, reduce
reliance on iTextSharp and improve thumbnails. Fixes #50
2016-09-01 18:31:35 +10:00

234 lines
9.1 KiB
C#

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
namespace Disco.Services
{
public static class ImagingExtensions
{
public static Bitmap RotateImage(this Image Source, float Angle, Brush BackgroundColor = null, bool ResizeIfOver45Deg = true)
{
var destWidth = Source.Width;
var destHeight = Source.Height;
var resizedDest = false;
if (ResizeIfOver45Deg && ((Angle > 45 && Angle < 135) || (Angle < -45 && Angle > -135)))
{
destWidth = Source.Height;
destHeight = Source.Width;
resizedDest = true;
}
var destination = new Bitmap(destWidth, destHeight);
destination.SetResolution(Source.HorizontalResolution, Source.VerticalResolution);
using (Graphics destinationGraphics = Graphics.FromImage(destination))
{
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
if (BackgroundColor != null)
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
float offsetWidth = destWidth / 2;
float offsetHeight = destHeight / 2;
destinationGraphics.TranslateTransform(offsetWidth, offsetHeight);
destinationGraphics.RotateTransform(Angle);
RectangleF destinationLocation;
if (resizedDest)
destinationLocation = new RectangleF(
offsetHeight * -1, offsetWidth * -1,
destHeight, destWidth);
else
destinationLocation = new RectangleF(
offsetWidth * -1, offsetHeight * -1,
destWidth, destHeight);
destinationGraphics.DrawImage(Source, destinationLocation, new RectangleF(0, 0, Source.Width, Source.Height), GraphicsUnit.Pixel);
}
return destination;
}
public static Bitmap ResizeImage(this Image Source, int TargetWidth, int TargetHeight, Brush BackgroundColor = null)
{
var destination = new Bitmap(TargetWidth, TargetHeight);
destination.SetResolution(72, 72);
using (Graphics destinationGraphics = Graphics.FromImage(destination))
{
destinationGraphics.CompositingQuality = CompositingQuality.HighQuality;
destinationGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
destinationGraphics.SmoothingMode = SmoothingMode.HighQuality;
if (BackgroundColor != null)
destinationGraphics.FillRectangle(BackgroundColor, destinationGraphics.VisibleClipBounds);
destinationGraphics.DrawImageResized(Source);
}
return destination;
}
public static RectangleF CalculateResize(int SourceWidth, int SourceHeight, int TargetWidth, int TargetHeight, out float scaleRatio)
{
scaleRatio = Math.Min((float)(TargetWidth) / SourceWidth, (float)(TargetHeight) / SourceHeight);
float width = SourceWidth * scaleRatio,
height = SourceHeight * scaleRatio,
x = 0,
y = 0;
if (width < TargetWidth)
x = (TargetWidth - width) / 2;
if (height < TargetHeight)
y = (TargetHeight - height) / 2;
return new RectangleF(x, y, width, height);
}
public static RectangleF CalculateResize(int SourceWidth, int SourceHeight, int TargetWidth, int TargetHeight)
{
float scaleRatio;
return CalculateResize(SourceWidth, SourceHeight, TargetHeight, TargetHeight, out scaleRatio);
}
public static RectangleF CalculateResize(this Image Source, int TargetWidth, int TargetHeight, out float scaleRatio)
{
return CalculateResize(Source.Width, Source.Height, TargetWidth, TargetHeight, out scaleRatio);
}
public static RectangleF CalculateResize(this Image Source, int TargetWidth, int TargetHeight)
{
return CalculateResize(Source.Width, Source.Height, TargetHeight, TargetHeight);
}
public static void DrawImageResized(this Graphics graphics, Image SourceImage)
{
RectangleF clipBounds = graphics.VisibleClipBounds;
var resizeBounds = SourceImage.CalculateResize((int)clipBounds.Width, (int)clipBounds.Height);
graphics.DrawImage(SourceImage, resizeBounds, new RectangleF(0, 0, SourceImage.Width, SourceImage.Height), GraphicsUnit.Pixel);
}
public static void DrawImageResized(this Graphics graphics, Image SourceImage, float Scale, float LocationX, float LocationY)
{
RectangleF clipBounds = graphics.VisibleClipBounds;
float width = SourceImage.Width * Scale,
height = SourceImage.Height * Scale,
x = LocationX,
y = LocationY;
x += clipBounds.Left;
y += clipBounds.Top;
graphics.DrawImage(SourceImage, new RectangleF(x, y, width, height), new RectangleF(0, 0, SourceImage.Width, SourceImage.Height), GraphicsUnit.Pixel);
}
public static void EmbedIconOverlay(this Image Source, Image Icon)
{
int top = Math.Max(0, Source.Height - Icon.Height);
int left = Math.Max(0, Source.Width - Icon.Width);
using (Graphics sourceGraphics = Graphics.FromImage(Source))
{
sourceGraphics.DrawImage(Icon, left, top);
}
}
public static void SavePng(this Image Source, string Filename)
{
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
{
SavePng(Source, outStream);
outStream.Flush();
outStream.Close();
}
}
public static void SavePng(this Image Source, Stream OutStream)
{
Source.Save(OutStream, ImageFormat.Png);
}
public static Stream SavePng(this Image Source)
{
MemoryStream outStream = new MemoryStream();
Source.SavePng(outStream);
outStream.Position = 0;
return outStream;
}
public static Stream SaveJpg(this Image Source, int Quality)
{
MemoryStream outStream = new MemoryStream();
Source.SaveJpg(Quality, outStream);
outStream.Position = 0;
return outStream;
}
public static void SaveJpg(this Image Source, int Quality, string Filename)
{
using (FileStream outStream = new FileStream(Filename, FileMode.Create, FileAccess.Write, FileShare.None))
{
SaveJpg(Source, Quality, outStream);
outStream.Flush();
outStream.Close();
}
}
public static void SaveJpg(this Image Source, int Quality, Stream OutStream)
{
ImageCodecInfo jpgCodec = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (jpgCodec != null)
{
if (Quality < 0 || Quality > 100)
throw new ArgumentOutOfRangeException("Quality", "Quality must be a positive integer <= 100");
using (EncoderParameters ep = new EncoderParameters(1))
{
ep.Param[0] = new EncoderParameter(Encoder.Quality, Quality);
Source.Save(OutStream, jpgCodec, ep);
}
}
else
{
// Fallback
Source.Save(OutStream, ImageFormat.Jpeg);
}
}
public static Color InterpolateColours(this Color Start, Color End, double Progress)
{
if (Progress > 1 || Progress < 0)
throw new ArgumentOutOfRangeException("Progress", "Progress must be >= 0 && <= 1");
return Color.FromArgb(
(byte)(Start.A * (1 - Progress) + (End.A * Progress)),
(byte)(Start.R * (1 - Progress) + (End.R * Progress)),
(byte)(Start.G * (1 - Progress) + (End.G * Progress)),
(byte)(Start.B * (1 - Progress) + (End.B * Progress))
);
}
public static RectangleF Multiply(this RectangleF Other, float Multiplier)
{
return new RectangleF(Other.X * Multiplier, Other.Y * Multiplier, Other.Width * Multiplier, Other.Height * Multiplier);
}
public static RectangleF Divide(this RectangleF Other, float Divisor)
{
return new RectangleF(Other.X / Divisor, Other.Y / Divisor, Other.Width / Divisor, Other.Height / Divisor);
}
}
}