Browse Source

Fixing rotate plus resolution errors.

Former-commit-id: fa8d70c55ba5bf778c557c190c89c2fcdf551a49
Former-commit-id: e7d3d40d11aae80bfe92f146287e22700871ebdd
af/merge-core
James South 11 years ago
parent
commit
f27eeb6be2
  1. 7
      src/ImageProcessor.Playground/Program.cs
  2. 3
      src/ImageProcessor.Playground/images/input/ce1a34f6-52bd-11e4-8164-54281a6247c9.jpg
  3. 17
      src/ImageProcessor.Web/Helpers/CommonParameterParserUtility.cs
  4. 11
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  5. 8
      src/ImageProcessor/ImageFactory.cs
  6. 21
      src/ImageProcessor/Imaging/Convolution.cs
  7. 1
      src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs
  8. 12
      src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs
  9. 10
      src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs
  10. 19
      src/ImageProcessor/Imaging/Helpers/Adjustments.cs
  11. 1
      src/ImageProcessor/Imaging/Helpers/Effects.cs
  12. 2
      src/ImageProcessor/Imaging/Quantizer.cs
  13. 3
      src/ImageProcessor/Imaging/Resizer.cs
  14. 3
      src/ImageProcessor/Processors/Alpha.cs
  15. 1
      src/ImageProcessor/Processors/BackgroundColor.cs
  16. 3
      src/ImageProcessor/Processors/Crop.cs
  17. 1
      src/ImageProcessor/Processors/EntropyCrop.cs
  18. 1
      src/ImageProcessor/Processors/Filter.cs
  19. 2
      src/ImageProcessor/Processors/Mask.cs
  20. 59
      src/ImageProcessor/Processors/Rotate.cs
  21. 3
      src/ImageProcessor/Processors/Saturation.cs
  22. 3
      src/ImageProcessor/Processors/Tint.cs

7
src/ImageProcessor.Playground/Program.cs

@ -78,17 +78,18 @@ namespace ImageProcessor.PlayGround
//.BackgroundColor(Color.White)
//.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer)
.Constrain(size)
//.Constrain(size)
.Rotate(66)
//.Mask(mask)
//.Format(new PngFormat())
//.BackgroundColor(Color.HotPink)
//.BackgroundColor(Color.Cyan)
//.ReplaceColor(Color.FromArgb(255, 1, 107, 165), Color.FromArgb(255, 1, 165, 13), 80)
//.Resize(layer)
//.DetectEdges(new SobelEdgeFilter(), false)
//.DetectEdges(new LaplacianOfGaussianEdgeFilter())
//.EntropyCrop()
//.Filter(MatrixFilters.Invert)
.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)
//.GaussianSharpen(10)

3
src/ImageProcessor.Playground/images/input/ce1a34f6-52bd-11e4-8164-54281a6247c9.jpg

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c296447b8ba5cc891c5668cfe5a977b6f94d6d8334bc8cfac1b9cf55cc00e343
size 18290

17
src/ImageProcessor.Web/Helpers/CommonParameterParserUtility.cs

@ -35,11 +35,12 @@ namespace ImageProcessor.Web.Helpers
/// The regular expression to search strings for colors.
/// </summary>
private static readonly Regex ColorRegex = BuildColorRegex();
/// <summary>
/// The regular expression to search strings for angles.
/// </summary>
private static readonly Regex AngleRegex = new Regex(@"(rotate|angle)(=|-)(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)", RegexOptions.Compiled);
//private static readonly Regex AngleRegex = new Regex(@"(rotate|angle)(=|-)(?:3[0-5][0-9]|[12][0-9]{2}|[1-9][0-9]?)", RegexOptions.Compiled);
private static readonly Regex AngleRegex = new Regex(@"(rotate|angle)(=|-)(-)?\d+(.?\d+)?", RegexOptions.Compiled);
/// <summary>
/// The regular expression to search strings for values between 1 and 100.
@ -70,14 +71,18 @@ namespace ImageProcessor.Web.Helpers
/// <returns>
/// The correct <see cref="T:System.Int32"/> containing the angle for the given string.
/// </returns>
public static int ParseAngle(string input)
public static float ParseAngle(string input)
{
foreach (Match match in AngleRegex.Matches(input))
{
// Split on angle
int angle;
string value = match.Value.Split(new[] { '=', '-' })[1];
int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out angle);
float angle;
string value = match.Value;
value = match.Value.ToUpperInvariant().Contains("ANGLE")
? value.Substring(value.IndexOf("-", System.StringComparison.Ordinal) + 1)
: match.Value.Split('=')[1];
float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out angle);
return angle;
}

11
src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

@ -268,6 +268,13 @@ namespace ImageProcessor.Web.HttpModules
private async Task ProcessImageAsync(HttpContext context)
{
HttpRequest request = context.Request;
// SHould we ignore this request?
if (request.RawUrl.ToUpperInvariant().Contains("IPIGNORE=TRUE"))
{
return;
}
IImageService currentService = this.GetImageServiceForRequest(request);
if (currentService != null)
@ -357,9 +364,7 @@ namespace ImageProcessor.Web.HttpModules
if (isNewOrUpdated)
{
// Process the image.
using (
ImageFactory imageFactory =
new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value))
using (ImageFactory imageFactory = new ImageFactory(preserveExifMetaData != null && preserveExifMetaData.Value))
{
using (await Locker.LockAsync(cachedPath))
{

8
src/ImageProcessor/ImageFactory.cs

@ -829,16 +829,10 @@ namespace ImageProcessor
/// <returns>
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
/// </returns>
public ImageFactory Rotate(int degrees)
public ImageFactory Rotate(float degrees)
{
if (this.ShouldProcess)
{
// Sanitize the input.
if (degrees > 360 || degrees < 0)
{
degrees = 0;
}
Rotate rotate = new Rotate { DynamicParameter = degrees };
this.CurrentImageFormat.ApplyProcessor(rotate.ProcessImage, this);
}

21
src/ImageProcessor/Imaging/Convolution.cs

@ -256,18 +256,19 @@ namespace ImageProcessor.Imaging
/// <summary>
/// Processes the given kernel to produce an array of pixels representing a bitmap.
/// </summary>
/// <param name="sourceBitmap">The image to process.</param>
/// <param name="source">The image to process.</param>
/// <param name="kernel">The Gaussian kernel to use when performing the method</param>
/// <returns>A processed bitmap.</returns>
public Bitmap ProcessKernel(Bitmap sourceBitmap, double[,] kernel)
public Bitmap ProcessKernel(Bitmap source, double[,] kernel)
{
int width = sourceBitmap.Width;
int height = sourceBitmap.Height;
Bitmap destinationBitmap = new Bitmap(width, height);
int width = source.Width;
int height = source.Height;
Bitmap destination = new Bitmap(width, height);
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (FastBitmap sourceFastBitmap = new FastBitmap(sourceBitmap))
using (FastBitmap sourceBitmap = new FastBitmap(source))
{
using (FastBitmap destinationFastBitmap = new FastBitmap(destinationBitmap))
using (FastBitmap destinationBitmap = new FastBitmap(destination))
{
int kernelLength = kernel.GetLength(0);
int radius = kernelLength >> 1;
@ -326,7 +327,7 @@ namespace ImageProcessor.Imaging
if (offsetX < width)
{
// ReSharper disable once AccessToDisposedClosure
Color color = sourceFastBitmap.GetPixel(offsetX, offsetY);
Color color = sourceBitmap.GetPixel(offsetX, offsetY);
double k = kernel[i, j];
divider += k;
@ -372,13 +373,13 @@ namespace ImageProcessor.Imaging
alpha += threshold;
// ReSharper disable once AccessToDisposedClosure
destinationFastBitmap.SetPixel(x, y, Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte()));
destinationBitmap.SetPixel(x, y, Color.FromArgb(alpha.ToByte(), red.ToByte(), green.ToByte(), blue.ToByte()));
}
});
}
}
return destinationBitmap;
return destination;
}
#region Private

1
src/ImageProcessor/Imaging/Filters/Artistic/OilPaintingFilter.cs

@ -101,6 +101,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
int radius = this.brushSize >> 1;
Bitmap destination = new Bitmap(width, height);
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (FastBitmap sourceBitmap = new FastBitmap(source))
{
using (FastBitmap destinationBitmap = new FastBitmap(destination))

12
src/ImageProcessor/Imaging/Filters/EdgeDetection/ConvolutionFilter.cs

@ -58,8 +58,10 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
int width = source.Width;
int height = source.Height;
Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Bitmap input = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Bitmap destination = new Bitmap(width, height);
Bitmap input = new Bitmap(width, height);
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
input.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(input))
{
@ -193,8 +195,10 @@ namespace ImageProcessor.Imaging.Filters.EdgeDetection
int width = source.Width;
int height = source.Height;
Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Bitmap input = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Bitmap destination = new Bitmap(width, height);
Bitmap input = new Bitmap(width, height);
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
input.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(input))
{

10
src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs

@ -59,13 +59,15 @@ namespace ImageProcessor.Imaging.Filters.Photo
attributes.SetColorMatrix(ColorMatrixes.ComicHigh);
// Draw the image with the high comic colormatrix.
highBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb);
highBitmap = new Bitmap(rectangle.Width, rectangle.Height);
highBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// Apply a oil painting filter to the image.
highBitmap = new OilPaintingFilter(3, 5).ApplyFilter((Bitmap)image);
// Draw the edges.
edgeBitmap = new Bitmap(width, height);
edgeBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
edgeBitmap = Trace(image, edgeBitmap, 120);
using (Graphics graphics = Graphics.FromImage(highBitmap))
@ -74,7 +76,8 @@ namespace ImageProcessor.Imaging.Filters.Photo
}
// Create a bitmap for overlaying.
lowBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb);
lowBitmap = new Bitmap(rectangle.Width, rectangle.Height);
lowBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// Set the color matrix
attributes.SetColorMatrix(this.Matrix);
@ -87,7 +90,8 @@ namespace ImageProcessor.Imaging.Filters.Photo
// We need to create a new image now with a pattern mask to paint it
// onto the other image with.
patternBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb);
patternBitmap = new Bitmap(rectangle.Width, rectangle.Height);
patternBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// Create the pattern mask.
using (Graphics graphics = Graphics.FromImage(patternBitmap))

19
src/ImageProcessor/Imaging/Helpers/Adjustments.cs

@ -101,15 +101,16 @@ namespace ImageProcessor.Imaging.Helpers
contrastFactor++;
float factorTransform = 0.5f * (1.0f - contrastFactor);
ColorMatrix colorMatrix = new ColorMatrix(
new[]
{
new[] { contrastFactor, 0, 0, 0, 0 },
new[] { 0, contrastFactor, 0, 0, 0 },
new[] { 0, 0, contrastFactor, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new[] { factorTransform, factorTransform, factorTransform, 0, 1 }
});
ColorMatrix colorMatrix =
new ColorMatrix(
new[]
{
new[] { contrastFactor, 0, 0, 0, 0 },
new[] { 0, contrastFactor, 0, 0, 0 },
new[] { 0, 0, contrastFactor, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new[] { factorTransform, factorTransform, factorTransform, 0, 1 }
});
using (Graphics graphics = Graphics.FromImage(source))
{

1
src/ImageProcessor/Imaging/Helpers/Effects.cs

@ -166,6 +166,7 @@ namespace ImageProcessor.Imaging.Helpers
// Ensure the background is cleared out on non alpha supporting formats.
Bitmap clear = new Bitmap(width, height);
clear.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(clear))
{
graphics.Clear(Color.Transparent);

2
src/ImageProcessor/Imaging/Quantizer.cs

@ -62,9 +62,11 @@ namespace ImageProcessor.Imaging
// First off take a 32bpp copy of the image
Bitmap copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
copy.SetResolution(source.HorizontalResolution, source.VerticalResolution);
// And construct an 8bpp version
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
output.SetResolution(source.HorizontalResolution, source.VerticalResolution);
// Now lock the bitmap into memory
using (Graphics g = Graphics.FromImage(copy))

3
src/ImageProcessor/Imaging/Resizer.cs

@ -312,7 +312,8 @@ namespace ImageProcessor.Imaging
return source;
}
newImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
newImage = new Bitmap(width, height);
newImage.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(newImage))
{

3
src/ImageProcessor/Processors/Alpha.cs

@ -67,7 +67,8 @@ namespace ImageProcessor.Processors
{
int alphaPercent = this.DynamicParameter;
newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb);
newImage = new Bitmap(image.Width, image.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.Matrix00 = colorMatrix.Matrix11 = colorMatrix.Matrix22 = colorMatrix.Matrix44 = 1;

1
src/ImageProcessor/Processors/BackgroundColor.cs

@ -60,6 +60,7 @@ namespace ImageProcessor.Processors
Color backgroundColor = this.DynamicParameter;
newImage = new Bitmap(width, height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// Make a graphics object from the empty bitmap.
using (Graphics graphics = Graphics.FromImage(newImage))

3
src/ImageProcessor/Processors/Crop.cs

@ -100,7 +100,8 @@ namespace ImageProcessor.Processors
rectangle.Height = sourceHeight - rectangle.Y;
}
newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb);
newImage = new Bitmap(rectangle.Width, rectangle.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(newImage))
{

1
src/ImageProcessor/Processors/EntropyCrop.cs

@ -66,6 +66,7 @@ namespace ImageProcessor.Processors
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(grey, 0);
newImage = new Bitmap(rectangle.Width, rectangle.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(newImage))
{
graphics.DrawImage(

1
src/ImageProcessor/Processors/Filter.cs

@ -66,6 +66,7 @@ namespace ImageProcessor.Processors
try
{
newImage = new Bitmap(image.Width, image.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
IMatrixFilter matrix = this.DynamicParameter;
newImage = matrix.TransformImage(image, newImage);

2
src/ImageProcessor/Processors/Mask.cs

@ -81,6 +81,7 @@ namespace ImageProcessor.Processors
Rectangle parent = new Rectangle(0, 0, width, height);
Rectangle child = ImageMaths.GetFilteredBoundingRectangle(mask, 0, RgbaComponent.A);
maskCropped = new Bitmap(child.Width, child.Height);
maskCropped.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// First crop any bounding transparency.
using (Graphics graphics = Graphics.FromImage(maskCropped))
@ -98,6 +99,7 @@ namespace ImageProcessor.Processors
// Now position the mask in an image of the same dimensions as the original.
maskPositioned = new Bitmap(width, height);
maskPositioned.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(maskPositioned))
{
graphics.Clear(Color.Transparent);

59
src/ImageProcessor/Processors/Rotate.cs

@ -65,7 +65,7 @@ namespace ImageProcessor.Processors
try
{
int angle = this.DynamicParameter;
float angle = this.DynamicParameter;
// Center of the image
float rotateAtX = Math.Abs(image.Width / 2);
@ -104,50 +104,27 @@ namespace ImageProcessor.Processors
/// </remarks>
private Bitmap RotateImage(Image image, float rotateAtX, float rotateAtY, float angle)
{
int width, height, x, y;
// Degrees to radians according to Google.
const double DegreeToRadian = 0.0174532925;
double widthAsDouble = image.Width;
double heightAsDouble = image.Height;
// Allow for angles over 180
if (angle > 180)
{
angle = angle - 360;
}
double radians = angle * Math.PI / 180d;
double radiansSin = Math.Sin(radians);
double radiansCos = Math.Cos(radians);
double width1 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
double height1 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
double degrees = Math.Abs(angle);
// Find dimensions in the other direction
radiansSin = Math.Sin(-radians);
radiansCos = Math.Cos(-radians);
double width2 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
double height2 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
if (degrees <= 90)
{
double radians = DegreeToRadian * degrees;
double radiansSin = Math.Sin(radians);
double radiansCos = Math.Cos(radians);
width = (int)((heightAsDouble * radiansSin) + (widthAsDouble * radiansCos));
height = (int)((widthAsDouble * radiansSin) + (heightAsDouble * radiansCos));
x = (width - image.Width) / 2;
y = (height - image.Height) / 2;
}
else
{
degrees -= 90;
double radians = DegreeToRadian * degrees;
double radiansSin = Math.Sin(radians);
double radiansCos = Math.Cos(radians);
// Get the external vertex for the rotation
int width = Convert.ToInt32(Math.Max(Math.Abs(width1), Math.Abs(width2)));
int height = Convert.ToInt32(Math.Max(Math.Abs(height1), Math.Abs(height2)));
// Fix the 270 error
if (Math.Abs(radiansCos - -1.0D) < 0.00001)
{
radiansCos = 1;
}
width = (int)((widthAsDouble * radiansSin) + (heightAsDouble * radiansCos));
height = (int)((heightAsDouble * radiansSin) + (widthAsDouble * radiansCos));
x = (width - image.Width) / 2;
y = (height - image.Height) / 2;
}
int x = (width - image.Width) / 2;
int y = (height - image.Height) / 2;
// Create a new empty bitmap to hold rotated image
Bitmap newImage = new Bitmap(width, height);
@ -157,7 +134,7 @@ namespace ImageProcessor.Processors
using (Graphics graphics = Graphics.FromImage(newImage))
{
// Reduce the jagged edge.
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.CompositingQuality = CompositingQuality.HighQuality;
@ -172,7 +149,7 @@ namespace ImageProcessor.Processors
graphics.TranslateTransform(-rotateAtX - x, -rotateAtY - y);
// Draw passed in image onto graphics object
graphics.DrawImage(image, new PointF(0 + x, 0 + y));
graphics.DrawImage(image, new PointF(x, y));
}
return newImage;

3
src/ImageProcessor/Processors/Saturation.cs

@ -81,7 +81,8 @@ namespace ImageProcessor.Processors
float saturationComplementG = 0.6094f * saturationComplement;
float saturationComplementB = 0.0820f * saturationComplement;
newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb);
newImage = new Bitmap(image.Width, image.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
ColorMatrix colorMatrix =
new ColorMatrix(

3
src/ImageProcessor/Processors/Tint.cs

@ -69,7 +69,8 @@ namespace ImageProcessor.Processors
};
ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb);
newImage = new Bitmap(image.Width, image.Height);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (Graphics graphics = Graphics.FromImage(newImage))
{

Loading…
Cancel
Save