Pdf Import Rewrite
Pdf Import rewritten to greatly improve QR Code detection, reduce reliance on iTextSharp and improve thumbnails. Fixes #50
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user