/// <summary> /// crop /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { byte[] imageBytes = File.ReadAllBytes("balloon.jpg"); Rectangle rec = new Rectangle(100, 100, 300, 300); using (MemoryStream ms = new MemoryStream(imageBytes)) { using (MemoryStream outStream = new MemoryStream()) { using (ImageFactory factory = new ImageFactory()) { factory.Load(ms).Crop(rec).Save(outStream); Image.FromStream(outStream).Save("imageProcessor\\Crop.jpg"); } } } CropLayer crop = new CropLayer(100, 100, 300, 300, CropMode.Pixels); using (MemoryStream ms = new MemoryStream(imageBytes)) { using (MemoryStream outStream = new MemoryStream()) { using (ImageFactory factory = new ImageFactory()) { factory.Load(ms).Crop(crop).Save(outStream); Image.FromStream(outStream).Save("imageProcessor\\crop2.jpg"); } } } }
public void ThenResultingImageSizeShouldBeLikeCropLayer(float left, float top, float right, float bottom, CropMode mode) { // When crop mode is percentage. The right and bottom values should represent // the percentage amount to remove from those sides. const int SizeX = 200; const int SizeY = 200; int expectedWidth = 160; int expectedHeight = 144; CropLayer cl = new CropLayer(left, top, right, bottom, mode); // Arrange using (Bitmap bitmap = new Bitmap(SizeX, SizeY)) using (MemoryStream memoryStream = new MemoryStream()) { bitmap.Save(memoryStream, ImageFormat.Bmp); memoryStream.Position = 0; using (ImageFactory imageFactory = new ImageFactory()) using (ImageFactory resultImage = imageFactory.Load(memoryStream).Crop(cl)) { // Act // Assert Assert.AreEqual(expectedWidth, resultImage.Image.Width); Assert.AreEqual(expectedHeight, resultImage.Image.Height); } } }
public void FullscreenScreenshot_MouseUp(object sender, MouseButtonEventArgs e) { if (leftButtonIsPressed == true) { leftButtonIsPressed = false; } // (left, top, right, bottom, cropmode) CropLayer cropLayer = new CropLayer( Math.Min((float)cropStart[0], (float)cropEnd[0]), Math.Min((float)cropStart[1], (float)cropEnd[1]), (float)Math.Abs(cropEnd[0] - cropStart[0]), (float)Math.Abs(cropEnd[1] - cropStart[1]), CropMode.Pixels ); CropLayer = cropLayer; CroppedImage = BitmapHelper.CropImage(screenshotBytes, cropLayer); this.Close(); //if (ImageCropped != null) //{ // ImageCropped(result); // this.Close(); //} }
public static BitmapImage CropImage(byte[] photoBytes, CropLayer cropLayer) { BitmapImage bitmap = new BitmapImage(); using (MemoryStream inStream = new MemoryStream(photoBytes)) { using (MemoryStream outStream = new MemoryStream()) { // Initialize the ImageFactory using the overload to preserve EXIF metadata. using (ImageFactory imageFactory = new ImageFactory(preserveExifData: true)) { // Load, resize, set the format and quality and save an image. imageFactory.Load(inStream); imageFactory.Crop(cropLayer); imageFactory.Save(outStream); } // Do something with the stream. bitmap.BeginInit(); bitmap.StreamSource = outStream; bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.EndInit(); bitmap.Freeze(); } } return(bitmap); }
public void ConstructorSavesData(float left, float top, float right, float bottom, CropMode mode) { CropLayer cl = new CropLayer(left, top, right, bottom, mode); cl.Left.Should().Be(left); cl.Top.Should().Be(top); cl.Right.Should().Be(right); cl.Bottom.Should().Be(bottom); cl.CropMode.Should().Be(mode); }
/// <summary> /// Crops the current image to the given location and size. /// </summary> /// <param name="rectangle"> /// The <see cref="T:System.Drawing.Rectangle"/> containing the coordinates to crop the image to. /// </param> /// <returns> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public ImageFactory Crop(Rectangle rectangle) { if (this.ShouldProcess) { CropLayer cropLayer = new CropLayer(rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height, CropMode.Pixels); return(this.Crop(cropLayer)); } return(this); }
/// <summary> /// Crops the current image to the given location and size. /// </summary> /// <param name="cropLayer"> /// The <see cref="Imaging.CropLayer"/> containing the coordinates and mode to crop the image with. /// </param> /// <returns> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public ImageFactory Crop(CropLayer cropLayer) { if (this.ShouldProcess) { Crop crop = new Crop { DynamicParameter = cropLayer }; this.CurrentImageFormat.ApplyProcessor(crop.ProcessImage, this); } return(this); }
public void TestCropRegex() { const string Querystring = "crop=0,0,150,300"; CropLayer expected = new CropLayer(0, 0, 150, 300, CropMode.Pixels); Processors.Crop crop = new Processors.Crop(); crop.MatchRegexIndex(Querystring); CropLayer actual = crop.Processor.DynamicParameter; Assert.AreEqual(expected, actual); }
public bool CanExecute(object parameter) { CropLayer cropLayer = parameter as CropLayer; if (cropLayer != null) { return(true); } else { return(false); } }
/// <summary> /// The position in the original string where the first character of the captured substring was found. /// </summary> /// <param name="queryString"> /// The query string to search. /// </param> /// <returns> /// The zero-based starting position in the original string where the captured substring was found. /// </returns> public int MatchRegexIndex(string queryString) { this.SortOrder = int.MaxValue; Match match = this.RegexPattern.Match(queryString); if (match.Success) { this.SortOrder = match.Index; NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); float[] coordinates = QueryParamParser.Instance.ParseValue <float[]>(queryCollection["cropper"]); // Default CropMode.Pixels will be returned. CropMode cropMode = QueryParamParser.Instance.ParseValue <CropMode>(queryCollection["cropmode"]); CropLayer cropLayer = new CropLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], cropMode); this.Processor.DynamicParameter = cropLayer; } return(this.SortOrder); }
public static string ProcessScreenshot(string filePath) { Console.WriteLine("Processing " + Path.GetFileName(filePath) + "..."); var imgBytes = File.ReadAllBytes(filePath); CropLayer fifaCrop = new CropLayer(11.5f, 34.8f, 32.5f, 17.5f, CropMode.Percentage); CropLayer tempCrop = new CropLayer(0, 0, 0, 92f, CropMode.Percentage); Image originalImage = Image.FromFile(filePath); string savePath = (Path.GetDirectoryName(filePath) + @"\Processed\" + Path.GetFileName(filePath)); using (var tempStream1 = new MemoryStream()) using (var tempStream2 = new MemoryStream()) using (var imageFactory = new ImageFactory(false)) { imageFactory.Load(originalImage) .Saturation(-100) .Crop(fifaCrop) .Contrast(100) .Save(tempStream1) .Crop(tempCrop) .Filter(MatrixFilters.Invert) .Save(tempStream2); Image goalsImage = Image.FromStream(tempStream2); ImageLayer goals = new ImageLayer() { Image = goalsImage, Size = goalsImage.Size, Opacity = 100, Position = new Point(originalImage.Size.Height) }; imageFactory.Load(tempStream1) .Overlay(goals) .Save(savePath); tempStream1.Dispose(); tempStream2.Dispose(); imageFactory.Dispose(); } Console.WriteLine("Image processed and saved to " + savePath); return(savePath); }
/// <summary> /// The position in the original string where the first character of the captured substring was found. /// </summary> /// <param name="queryString">The query string to search.</param> /// <returns> /// The zero-based starting position in the original string where the captured substring was found. /// </returns> public int MatchRegexIndex(string queryString) { int index = 0; // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; // First merge the matches so we can parse . StringBuilder stringBuilder = new StringBuilder(); foreach (Match match in this.RegexPattern.Matches(queryString)) { // Match but ignore entropy if (match.Success && !queryString.ToUpperInvariant().Contains("ENTROPYCROP=")) { if (index == 0) { // Set the index on the first instance only. this.SortOrder = match.Index; } stringBuilder.Append(match.Value); index += 1; } } if (this.SortOrder < int.MaxValue) { // Match syntax string toParse = stringBuilder.ToString(); float[] coordinates = this.ParseCoordinates(toParse); CropMode cropMode = this.ParseMode(toParse); CropLayer cropLayer = new CropLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], cropMode); this.Processor.DynamicParameter = cropLayer; } return(this.SortOrder); }
public void TestCropRegex() { Dictionary <string, CropLayer> data = new Dictionary <string, CropLayer> { { "crop=0,0,150,300", new CropLayer(0, 0, 150, 300, CropMode.Pixels) }, { "crop=0.1,0.1,.2,.2&cropmode=percentage", new CropLayer(0.1f, 0.1f, 0.2f, 0.2f, CropMode.Percentage) } }; Processors.Crop crop = new Processors.Crop(); foreach (KeyValuePair <string, CropLayer> item in data) { crop.MatchRegexIndex(item.Key); CropLayer result = crop.Processor.DynamicParameter; Assert.AreEqual(item.Value, result); } }
/// <summary> /// Processes the image. /// </summary> /// <param name="factory"> /// The the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing /// the image to process. /// </param> /// <returns> /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { int sourceWidth = image.Width; int sourceHeight = image.Height; RectangleF rectangleF; CropLayer cropLayer = this.DynamicParameter; if (cropLayer.CropMode == CropMode.Percentage) { // Work out the percentages. float left = cropLayer.Left * sourceWidth; float top = cropLayer.Top * sourceHeight; float width = (1 - cropLayer.Left - cropLayer.Right) * sourceWidth; float height = (1 - cropLayer.Top - cropLayer.Bottom) * sourceHeight; rectangleF = new RectangleF(left, top, width, height); } else { rectangleF = new RectangleF(cropLayer.Left, cropLayer.Top, cropLayer.Right, cropLayer.Bottom); } Rectangle rectangle = Rectangle.Round(rectangleF); if (rectangle.X < sourceWidth && rectangle.Y < sourceHeight) { if (rectangle.Width > (sourceWidth - rectangle.X)) { rectangle.Width = sourceWidth - rectangle.X; } if (rectangle.Height > (sourceHeight - rectangle.Y)) { rectangle.Height = sourceHeight - rectangle.Y; } newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); using (Graphics graphics = Graphics.FromImage(newImage)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality; // An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image // as the algorithm appears to be pulling averaging detail from surrounding pixels beyond the edge // of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror // images of the pixels within solves this problem. using (ImageAttributes wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage( image, new Rectangle(0, 0, rectangle.Width, rectangle.Height), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, GraphicsUnit.Pixel, wrapMode); } // Reassign the image. image.Dispose(); image = newImage; } } } catch { if (newImage != null) { newImage.Dispose(); } } return(image); }
/// <summary> /// The main routine. /// </summary> /// <param name="args"> /// The args. /// </param> public static void Main(string[] args) { string path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath; // ReSharper disable once AssignNullToNotNullAttribute string resolvedPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\input")); DirectoryInfo di = new DirectoryInfo(resolvedPath); if (!di.Exists) { di.Create(); } // Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask.png")); // Image overlay = Image.FromFile(Path.Combine(resolvedPath, "imageprocessor.128.png")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "2008.jpg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "stretched.jpg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "mountain.jpg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "Arc-de-Triomphe-France.jpg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "Martin-Schoeller-Jack-Nicholson-Portrait.jpeg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "crop-base-300x200.jpg")); //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "cmyk.png")); //IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif"); IEnumerable <FileInfo> files = GetFilesByExtensions(di, ".jpg", ".jpeg", ".jfif"); //IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif"); foreach (FileInfo fileInfo in files) { if (fileInfo.Name == "test5.jpg") { continue; } byte[] photoBytes = File.ReadAllBytes(fileInfo.FullName); Console.WriteLine("Processing: " + fileInfo.Name); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // ImageProcessor using (MemoryStream inStream = new MemoryStream(photoBytes)) { using (ImageFactory imageFactory = new ImageFactory(true)) { Size size = new Size(1024, 0); CropLayer cropLayer = new CropLayer(20, 20, 20, 20, ImageProcessor.Imaging.CropMode.Percentage); //ResizeLayer layer = new ResizeLayer(size, ResizeMode.Max, AnchorPosition.Center, false); //ContentAwareResizeLayer layer = new ContentAwareResizeLayer(size) //{ // ConvolutionType = ConvolutionType.Sobel //}; // Load, resize, set the format and quality and save an image. imageFactory.Load(inStream) //.Overlay(new ImageLayer // { // Image = overlay, // Opacity = 50 // }) //.Alpha(50) //.BackgroundColor(Color.White) //.Resize(new Size((int)(size.Width * 1.1), 0)) //.ContentAwareResize(layer) //.Constrain(size) //.Mask(mask) //.Format(new PngFormat()) //.BackgroundColor(Color.Cyan) //.ReplaceColor(Color.FromArgb(255, 223, 224), Color.FromArgb(121, 188, 255), 128) //.Resize(size) //.Resize(new ResizeLayer(size, ResizeMode.Max)) // .Resize(new ResizeLayer(size, ResizeMode.Stretch)) //.DetectEdges(new Laplacian3X3EdgeFilter(), true) //.DetectEdges(new LaplacianOfGaussianEdgeFilter()) //.EntropyCrop() //.Halftone(true) //.RotateBounded(150, false) .Crop(cropLayer) //.Rotate(140) //.Filter(MatrixFilters.Invert) //.Contrast(50) //.Filter(MatrixFilters.Comic) //.Flip() //.Filter(MatrixFilters.HiSatch) //.Pixelate(8) //.GaussianSharpen(10) //.Format(new PngFormat() { IsIndexed = true }) //.Format(new PngFormat() ) .Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name))); //.Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", Path.GetFileNameWithoutExtension(fileInfo.Name) + ".png"))); stopwatch.Stop(); } } long peakWorkingSet64 = Process.GetCurrentProcess().PeakWorkingSet64; float mB = peakWorkingSet64 / (float)1024 / 1024; Console.WriteLine(@"Completed {0} in {1:s\.fff} secs {2}Peak memory usage was {3} bytes or {4} Mb.", fileInfo.Name, stopwatch.Elapsed, Environment.NewLine, peakWorkingSet64.ToString("#,#"), mB); //Console.WriteLine("Processed: " + fileInfo.Name + " in " + stopwatch.ElapsedMilliseconds + "ms"); } Console.ReadLine(); }
/// <summary> /// Processes the image. /// </summary> /// <param name="factory"> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing /// the image to process. /// </param> /// <returns> /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { int sourceWidth = image.Width; int sourceHeight = image.Height; RectangleF rectangleF; CropLayer cropLayer = this.DynamicParameter; if (cropLayer.CropMode == CropMode.Percentage) { // Fix for whole numbers. float percentageLeft = cropLayer.Left > 1 ? cropLayer.Left / 100 : cropLayer.Left; float percentageRight = cropLayer.Right > 1 ? cropLayer.Right / 100 : cropLayer.Right; float percentageTop = cropLayer.Top > 1 ? cropLayer.Top / 100 : cropLayer.Top; float percentageBottom = cropLayer.Bottom > 1 ? cropLayer.Bottom / 100 : cropLayer.Bottom; // Work out the percentages. float left = percentageLeft * sourceWidth; float top = percentageTop * sourceHeight; float width = percentageRight < 1 ? (1 - percentageLeft - percentageRight) * sourceWidth : sourceWidth; float height = percentageBottom < 1 ? (1 - percentageTop - percentageBottom) * sourceHeight : sourceHeight; rectangleF = new RectangleF(left, top, width, height); } else { rectangleF = new RectangleF(cropLayer.Left, cropLayer.Top, cropLayer.Right, cropLayer.Bottom); } Rectangle rectangle = Rectangle.Round(rectangleF); if (rectangle.X < sourceWidth && rectangle.Y < sourceHeight) { if (rectangle.Width > (sourceWidth - rectangle.X)) { rectangle.Width = sourceWidth - rectangle.X; } if (rectangle.Height > (sourceHeight - rectangle.Y)) { rectangle.Height = sourceHeight - rectangle.Y; } newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); using (Graphics graphics = Graphics.FromImage(newImage)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality; // An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image // as the algorithm appears to be pulling averaging detail from surrounding pixels beyond the edge // of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror // images of the pixels within solves this problem. using (ImageAttributes wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage( image, new Rectangle(0, 0, rectangle.Width, rectangle.Height), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, GraphicsUnit.Pixel, wrapMode); } } // Reassign the image. image.Dispose(); image = newImage; if (factory.PreserveExifData && factory.ExifPropertyItems.Any()) { // Set the width EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageWidth, (ushort)image.Width); // Set the height EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageHeight, (ushort)image.Height); } } } catch (Exception ex) { newImage?.Dispose(); throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return(image); }
public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { CropLayer cropLayer = this.DynamicParameter; int iw = image.Width; int ih = image.Height; double ir = iw / (double)ih; double tw = cropLayer.Right; double th = cropLayer.Right / cropLayer.Bottom; double tr = tw / th; double sw, sh, sx, sy; if (ir > tr) { sh = ih; sw = ih * tr; } else { sw = iw; sh = iw / tr; } sx = (iw - sw) / 2 + iw * (cropLayer.Left - 0.5); sy = (ih - sh) / 2 + ih * (cropLayer.Top - 0.5); sx = Math.Max(0, sx); sy = Math.Max(0, sy); sx = Math.Min(iw - sw, sx); sy = Math.Min(ih - sh, sy); RectangleF rectangleF = new RectangleF(Convert.ToSingle(sx), Convert.ToSingle(sy), Convert.ToSingle(sw), Convert.ToSingle(sh)); Rectangle rectangle = Rectangle.Round(rectangleF); if (rectangle.X < iw && rectangle.Y < ih) { if (rectangle.Width > (iw - rectangle.X)) { rectangle.Width = iw - rectangle.X; } if (rectangle.Height > (ih - rectangle.Y)) { rectangle.Height = ih - rectangle.Y; } newImage = new Bitmap(rectangle.Width, rectangle.Height); newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); using (Graphics graphics = Graphics.FromImage(newImage)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality; // An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image // as the algorithm appears to be pulling averaging detail from surrounding pixels beyond the edge // of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror // images of the pixels within solves this problem. using (ImageAttributes wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage( image, new Rectangle(0, 0, (int)tw, (int)(tw / tr)), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, GraphicsUnit.Pixel, wrapMode); } } // Reassign the image. image.Dispose(); image = newImage; } } catch (Exception ex) { if (newImage != null) { newImage.Dispose(); } throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return(image); }
/// <summary> /// Processes the image. /// </summary> /// <param name="factory"> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing /// the image to process. /// </param> /// <returns> /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; var image = factory.Image; try { var sourceWidth = image.Width; var sourceHeight = image.Height; RectangleF rectangleF; CropLayer cropLayer = DynamicParameter; if (cropLayer.CropMode == CropMode.Percentage) { // Fix for whole numbers. var percentageLeft = cropLayer.Left > 1 ? cropLayer.Left / 100 : cropLayer.Left; var percentageRight = cropLayer.Right > 1 ? cropLayer.Right / 100 : cropLayer.Right; var percentageTop = cropLayer.Top > 1 ? cropLayer.Top / 100 : cropLayer.Top; var percentageBottom = cropLayer.Bottom > 1 ? cropLayer.Bottom / 100 : cropLayer.Bottom; // Work out the percentages. var left = percentageLeft * sourceWidth; var top = percentageTop * sourceHeight; var width = percentageRight < 1 ? (1 - percentageLeft - percentageRight) * sourceWidth : sourceWidth; var height = percentageBottom < 1 ? (1 - percentageTop - percentageBottom) * sourceHeight : sourceHeight; rectangleF = new RectangleF(left, top, width, height); } else { rectangleF = new RectangleF(cropLayer.Left, cropLayer.Top, cropLayer.Right, cropLayer.Bottom); } var rectangle = Rectangle.Round(rectangleF); if (rectangle.X < sourceWidth && rectangle.Y < sourceHeight) { if (rectangle.Width > (sourceWidth - rectangle.X)) { rectangle.Width = sourceWidth - rectangle.X; } if (rectangle.Height > (sourceHeight - rectangle.Y)) { rectangle.Height = sourceHeight - rectangle.Y; } newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); var rotationValue = 0; const int orientation = (int)ExifPropertyTag.Orientation; var rotate = factory.PreserveExifData && factory.ExifPropertyItems.ContainsKey(orientation); if (rotate) { rotationValue = factory.ExifPropertyItems[orientation].Value[0]; ForwardRotateFlip(rotationValue, ref image); } using (var graphics = Graphics.FromImage(newImage)) { GraphicsHelper.SetGraphicsOptions(graphics); // An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image // as the algorithm appears to be pulling averaging detail from surrounding pixels beyond the edge // of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror // images of the pixels within solves this problem. using (var wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage( image, new Rectangle(0, 0, rectangle.Width, rectangle.Height), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, GraphicsUnit.Pixel, wrapMode); } } // Reassign the image. image.Dispose(); image = newImage; if (rotate) { ReverseRotateFlip(rotationValue, ref image); } if (factory.PreserveExifData && factory.ExifPropertyItems.Any()) { // Set the width EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageWidth, (ushort)image.Width); // Set the height EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageHeight, (ushort)image.Height); } } } catch (Exception ex) { newImage?.Dispose(); throw new ImageProcessingException("Error processing image with " + GetType().Name, ex); } return(image); }
/// <summary> /// Processes the image. /// </summary> /// <param name="factory"> /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing /// the image to process. /// </param> /// <returns> /// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// </returns> public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { int sourceWidth = image.Width; int sourceHeight = image.Height; RectangleF rectangleF; CropLayer cropLayer = this.DynamicParameter; Rectangle rectangle = new Rectangle(cropLayer.X, cropLayer.Y, cropLayer.Width, cropLayer.Height); if (!rectangle.IntersectsWith(new Rectangle(0, 0, sourceWidth, sourceHeight))) { throw new ImageProcessingException("Invalid coordinates"); } if (rectangle.X < sourceWidth && rectangle.Y < sourceHeight) { if (rectangle.Width > (sourceWidth - rectangle.X)) { rectangle.Width = sourceWidth - rectangle.X; } if (rectangle.Height > (sourceHeight - rectangle.Y)) { rectangle.Height = sourceHeight - rectangle.Y; } newImage = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); int rotationValue = 0; const int orientation = (int)ExifPropertyTag.Orientation; bool rotate = factory.PreserveExifData && factory.ExifPropertyItems.ContainsKey(orientation); if (rotate) { rotationValue = factory.ExifPropertyItems[orientation].Value[0]; this.ForwardRotateFlip(rotationValue, ref image); } using (Graphics graphics = Graphics.FromImage(newImage)) { GraphicsHelper.SetGraphicsOptions(graphics); // An unwanted border appears when using InterpolationMode.HighQualityBicubic to resize the image // as the algorithm appears to be pulling averaging detail from surrounding pixels beyond the edge // of the image. Using the ImageAttributes class to specify that the pixels beyond are simply mirror // images of the pixels within solves this problem. using (ImageAttributes wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage( image, new Rectangle(0, 0, rectangle.Width, rectangle.Height), rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, GraphicsUnit.Pixel, wrapMode); } } // Reassign the image. image.Dispose(); image = newImage; if (rotate) { this.ReverseRotateFlip(rotationValue, ref image); } if (factory.PreserveExifData && factory.ExifPropertyItems.Any()) { // Set the width EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageWidth, (ushort)image.Width); // Set the height EXIF data. factory.SetPropertyItem(ExifPropertyTag.ImageHeight, (ushort)image.Height); } } } catch (Exception ex) { newImage?.Dispose(); throw new ImageProcessingException("Error processing image with " + this.GetType().Name, ex); } return(image); }