Beispiel #1
0
        private static void ResizeImage(int width, int height, int quality, string options, IMagickImage magickImage)
        {
            magickImage.Quality = quality;
            magickImage.Strip();

            if (options.Contains("g")) //grayscale
            {
                magickImage.Grayscale(PixelIntensityMethod.Average);
            }
            if (width == magickImage.BaseWidth && height == magickImage.BaseHeight)
            {
                return;
            }
            else if (options.Contains("f") || options.Contains("t"))
            {
                magickImage.Resize(width, height);
            }
            else
            {
                var magickGeometry = new MagickGeometry(width, height)
                {
                    IgnoreAspectRatio = false, //保持长宽比
                    FillArea          = true
                };
                magickImage.Resize(magickGeometry);
                magickImage.Crop(magickGeometry, Gravity.Center);
            }
        }
        private void CropImage(IMagickImage image)
        {
            if (!CropOffset.IsSet)
            {
                return;
            }

            int width  = image.Width - (CropOffset.Left + CropOffset.Right);
            int height = image.Height - (CropOffset.Top + CropOffset.Bottom);

            image.Crop(new MagickGeometry(CropOffset.Left, CropOffset.Top, width, height));
        }
Beispiel #3
0
        public IMagickImage Execute(IMagickImage image, ValueItemCollection values)
        {
            Variables = values;

            if (!CropVisible)
            {
                return(image);
            }

            var dw = image.Width / 1000.0;
            var dh = image.Height / 1000.0;

            image.Crop((int)(CropX * dw), (int)(CropY * dh), (int)(CropWidth * dw),
                       (int)(CropHeight * dh));
            image.RePage();
            return(image);
        }
Beispiel #4
0
        private static void CropImage(CustomRatio ratio, IMagickImage image)
        {
            var cropWidth  = Math.Abs(ratio.X2 - ratio.X1);
            var cropHeight = Math.Abs(ratio.Y2 - ratio.Y1);

            if (image.BaseWidth == cropWidth && image.BaseHeight == cropHeight) //requested image is same size
            {
                return;
            }

            var cropSize = new MagickGeometry(cropWidth, cropHeight)
            {
                IgnoreAspectRatio = false, //keep aspect ratio!
                FillArea          = false,
                X = ratio.X1,
                Y = ratio.Y1
            };

            image.Crop(cropSize);
        }
Beispiel #5
0
        private static void ResizeImage(int requestWidth, int requestHeight, int quality, string options, IMagickImage image)
        {
            image.Quality = quality;

            image.Strip();

            if (options.Contains("g")) //grayscale
            {
                image.Grayscale(PixelIntensityMethod.Average);
            }

            if (image.BaseWidth == requestWidth && image.BaseHeight == requestHeight) //requested image is same size
            {
                return;
            }
            if (requestWidth == 0 && requestHeight == 0) //requested image is same size
            {
                return;
            }

            if (options.Contains("f") || options.Contains("t")) //scale with aspect of image
            {
                var size = new MagickGeometry(requestWidth, requestHeight);
                image.Resize(size);
            }
            else if (requestWidth == 0 || requestHeight == 0) //scale with aspect of image
            {
                var size = new MagickGeometry(requestWidth, requestHeight);
                image.Resize(size);
            }
            else // This will resize the image to a fixed size without maintaining the aspect ratio.
            {
                var size = new MagickGeometry(requestWidth, requestHeight)
                {
                    IgnoreAspectRatio = false, //keep aspect ratio!
                    FillArea          = true
                };
                image.Resize(size);
                image.Crop(size, Gravity.Center);
            }
        }
            private void AssertComponent(IMagickImage image, ConnectedComponent component, int id, int x, int y, int width, int height, int area, MagickColor color, int centroidX, int centroidY)
            {
                var delta = 2;

                Assert.AreEqual(id, component.Id);
                Assert.AreEqual(x, component.X, delta);
                Assert.AreEqual(y, component.Y, delta);
                Assert.AreEqual(width, component.Width, delta);
                Assert.AreEqual(height, component.Height, delta);
                Assert.AreEqual(area, component.Area, delta);
                ColorAssert.AreEqual(color, component.Color);
                Assert.AreEqual(centroidX, component.Centroid.X, delta);
                Assert.AreEqual(centroidY, component.Centroid.Y, delta);

                using (IMagickImage componentImage = image.Clone())
                {
                    componentImage.Crop(component.ToGeometry(10));
                    Assert.AreEqual(width + 20, componentImage.Width, delta);
                    Assert.AreEqual(height + 20, componentImage.Height, delta);
                }
            }
Beispiel #7
0
        private static void CropImage(ImageCustomization imageCustomization, IMagickImage magickImage)
        {
            var cropWidth  = Math.Abs(imageCustomization.X2 - imageCustomization.X1);
            var cropHeight = Math.Abs(imageCustomization.Y2 - imageCustomization.Y1);

            if ((cropWidth <= 0 || cropHeight <= 0) || cropWidth == magickImage.BaseWidth && cropHeight == magickImage.BaseHeight)
            {
                return;
            }
            else
            {
                var magickGeometry = new MagickGeometry(cropWidth, cropHeight)
                {
                    IgnoreAspectRatio = false, //保持长宽比
                    FillArea          = false,
                    X = imageCustomization.X1,
                    Y = imageCustomization.Y1
                };

                magickImage.Crop(magickGeometry);
            }
        }
Beispiel #8
0
        private static void Process(string png, string mesh)
        {
            var rebuildCoord = new List <Point>();
            var rebuildMeta  = new List <FragmentDataInfo>();
            var cropCoord    = new List <PointF>();

            string[] txtRaw     = File.ReadAllLines(mesh);
            int      nLine      = 0;
            int      widthLow   = 0;
            int      widthHigh  = 0;
            int      heightLow  = 0;
            int      heightHigh = 0;

            for (nLine = 0; nLine < txtRaw.Length; nLine++)
            {
                // Start of coord data
                if (txtRaw[nLine][0] == 'v')
                {
                    break;
                }
            }

            while (true)
            {
                int i = 0;

                string[] tmp = txtRaw[nLine + i + 0].Split(' ');

                Point  rd;
                PointF cd;

                if (tmp[0][0] == '#')
                {
                    break;
                }

                rd = new Point(Math.Abs(Convert.ToInt32(Convert.ToDouble(tmp[1]))), Convert.ToInt32(Convert.ToDouble(tmp[2])));
                rebuildCoord.Add(rd);

                if (widthLow > Convert.ToInt32(Convert.ToDouble(tmp[1])))
                {
                    widthLow = Convert.ToInt32(Convert.ToDouble(tmp[1]));
                }
                if (widthHigh < rd.X)
                {
                    widthHigh = rd.X;
                }
                if (heightLow > rd.Y)
                {
                    heightLow = rd.Y;
                }
                if (heightHigh < rd.Y)
                {
                    heightHigh = rd.Y;
                }

                tmp = txtRaw[nLine + i + 1].Split(' ');
                cd  = new PointF(float.Parse(tmp[1]), 1.0f - float.Parse(tmp[2]));
                cropCoord.Add(cd);

                nLine += 2;
            }

            for (; nLine < txtRaw.Length; nLine++)
            {
                // Start of meta data
                if (txtRaw[nLine][0] == 'f')
                {
                    break;
                }
            }

            while (true)
            {
                int i = 0;

                string[] tmp = txtRaw[nLine + i + 0].Split(' ', '/');

                FragmentDataInfo fdi = new FragmentDataInfo();

                if (tmp[0] == String.Empty || nLine > txtRaw.Length)
                {
                    break;
                }

                fdi.F1 = Math.Abs(Convert.ToInt32(Convert.ToDouble(tmp[1])));
                fdi.F2 = Math.Abs(Convert.ToInt32(Convert.ToDouble(tmp[3])));
                fdi.F3 = Math.Abs(Convert.ToInt32(Convert.ToDouble(tmp[5])));

                rebuildMeta.Add(fdi);

                nLine++;
            }

            MagickImage mi = new MagickImage(png);

            int baseWidth  = mi.Width;
            int baseHeight = mi.Height;
            int padding    = 1024;

            MagickImage ri = new MagickImage(MagickColor.FromRgb(255, 255, 255), 4096, 4096);

            ri.Resize(4096, 4096);
            ri.Transparent(MagickColors.White);

            for (int i = 0; i < rebuildMeta.Count; i++)
            {
                Point[] rebuildInfo =
                {
                    new Point(rebuildCoord[rebuildMeta[i].F1 - 1].X,
                              rebuildCoord[rebuildMeta[i].F1 - 1].Y),
                    new Point(rebuildCoord[rebuildMeta[i].F2 - 1].X,
                              rebuildCoord[rebuildMeta[i].F2 - 1].Y),
                    new Point(rebuildCoord[rebuildMeta[i].F3 - 1].X,
                              rebuildCoord[rebuildMeta[i].F3 - 1].Y)
                };

                PointF[] cropInfo =
                {
                    new PointF(baseWidth * cropCoord[rebuildMeta[i].F1 - 1].X, baseHeight * cropCoord[rebuildMeta[i].F1 - 1].Y),
                    new PointF(baseWidth * cropCoord[rebuildMeta[i].F2 - 1].X, baseHeight * cropCoord[rebuildMeta[i].F2 - 1].Y),
                    new PointF(baseWidth * cropCoord[rebuildMeta[i].F3 - 1].X, baseHeight * cropCoord[rebuildMeta[i].F3 - 1].Y)
                };

                int cropStartX = (int)Math.Round(Math.Min(Math.Min(cropInfo[0].X, cropInfo[1].X), cropInfo[2].X));
                int cropStartY = (int)Math.Round(Math.Min(Math.Min(cropInfo[0].Y, cropInfo[1].Y), cropInfo[2].Y));
                int cropEndX   = (int)Math.Round(Math.Max(Math.Max(cropInfo[0].X, cropInfo[1].X), cropInfo[2].X));
                int cropEndY   = (int)Math.Round(Math.Max(Math.Max(cropInfo[0].Y, cropInfo[1].Y), cropInfo[2].Y));

                int rebuildStartX = Math.Min(Math.Min(rebuildInfo[0].X, rebuildInfo[1].X), rebuildInfo[2].X);
                int rebuildStartY = baseWidth - Math.Min(Math.Min(rebuildInfo[0].Y, rebuildInfo[1].Y), rebuildInfo[2].Y)
                                    - (cropEndY - cropStartY);

                IMagickImage   clone = mi.Clone();
                MagickGeometry mg    = new MagickGeometry
                {
                    X      = cropStartX,
                    Y      = cropStartY,
                    Width  = cropEndX - cropStartX,
                    Height = cropEndY - cropStartY
                };

                clone.Crop(mg, Gravity.Northwest);
                ri.Composite(clone, rebuildStartX + padding, rebuildStartY + padding, CompositeOperator.Copy, Channels.All);

                Console.Write(((double)i / (double)rebuildMeta.Count * 100.0d).ToString("0.00"));
                Console.Write("\r");
            }

            //ri.Transparent(MagickColor.FromRgb(0, 0, 0));
            ri.BackgroundColor = MagickColors.Transparent;
            ri.Trim();
            ri.Write(Path.GetFileName(png) + "_d.png", MagickFormat.Png32);
            mi.Dispose();
            ri.Dispose();

            Console.Write("100.0");
            Console.WriteLine(Environment.NewLine +
                              "Output: " + Environment.NewLine +
                              "PNG=" + Path.GetFileName(png) + "_d.png" + Environment.NewLine);

            return;
        }
Beispiel #9
0
 private void Crop(IMagickImage image, MagickGeometry area)
 {
     ShiftGeometry(area);
     image.Crop(area.X, area.Y, area.Width, area.Height);
     image.RePage();
 }
        public static void Run([BlobTrigger("inbox/{inputFilename}", Connection = "StorageAccountConnString")] Stream inputStream, string inputFilename,
                               [Blob("outbox/out-{inputFilename}", FileAccess.Write, Connection = "StorageAccountConnString")] Stream outputStream, ILogger log)
        {
            log.LogInformation($"STEP: trigger fired for file:{inputFilename}, Size: {inputStream.Length} Bytes");

            using (MagickImage image = new MagickImage(inputStream))
            {
                log.LogInformation($"STEP: Read image {inputFilename} with {image.BaseWidth} x {image.BaseHeight} in {image.Format.ToString()}");

                // Step 0 - does nothing in the sample images I used
                image.AutoOrient();

                // Step 1 - Deskew
                image.BackgroundColor = MagickColor.FromRgb(0, 0, 0);
                image.Deskew(new Percentage(1)); // documentation suggests "A threshold of 40% works for most images" but 1% seems to work well
                IMagickImage rotatedImage = image.Clone();
                log.LogInformation($"STEP: Deskewed {inputFilename}");

                // Step 2 - Apply threshold to transform in black and white image
                image.AutoThreshold(AutoThresholdMethod.OTSU);
                log.LogInformation($"STEP: Applied OTSU to {inputFilename}");

                // Step 3 - find the regions (blocs) in the image and group them if large enough
                IEnumerable <ConnectedComponent> components = null;
                ConnectedComponentsSettings      ccs        = new ConnectedComponentsSettings();
                ccs.AreaThreshold = 500 * 500.0; // 500x500 -- seems to be pointless, many more regions are returned
                ccs.Connectivity  = 8;
                components        = image.ConnectedComponents(ccs);

                // if there are multiple blocs, consolidate them in a larger block
                if (components != null && components.Count() > 0)
                {
                    log.LogInformation($"STEP: Looked for regions in {inputFilename}, there are {components.Count()}");

                    // filter out the smaller rectangles, as the AreaThreshold parameter seems not to be working
                    List <ConnectedComponent> biggerComponents = components.Where(cc => cc.Height * cc.Width >= 250000 && cc.Height * cc.Width != image.Width * image.Height) /*.OrderByDescending(i => i.Height * i.Width)*/.ToList();
                    int topLeftX = biggerComponents[0].X, topLeftY = biggerComponents[0].Y, bottomRightX = biggerComponents[0].Width + topLeftX, bottomRightY = biggerComponents[0].Height + topLeftY;

                    foreach (ConnectedComponent cc in biggerComponents)
                    {
                        #region Debug -- draw the regions on the image
                        //DrawableStrokeColor strokeColor = new DrawableStrokeColor(new MagickColor("yellow"));
                        //DrawableStrokeWidth stokeWidth = new DrawableStrokeWidth(3);
                        //DrawableFillColor fillColor = new DrawableFillColor(new MagickColor(50, 50, 50, 128));
                        //DrawableRectangle dr = new DrawableRectangle(cc.X, cc.Y, cc.X + cc.Width, cc.Y + cc.Height);
                        //rotatedImage.Draw(dr, strokeColor, stokeWidth, fillColor);
                        #endregion

                        if (cc.X < topLeftX)
                        {
                            topLeftX = cc.X;
                        }

                        if (cc.Y < topLeftY)
                        {
                            topLeftY = cc.Y;
                        }

                        if (cc.X + cc.Width > bottomRightX)
                        {
                            bottomRightX = cc.X + cc.Width;
                        }

                        if (cc.Y + cc.Height > bottomRightY)
                        {
                            bottomRightY = cc.Y + cc.Height;
                        }
                    }

                    #region Debug -- draw the bounding box on the image
                    //DrawableStrokeColor strokeColor2 = new DrawableStrokeColor(new MagickColor("purple"));
                    //DrawableStrokeWidth stokeWidth2 = new DrawableStrokeWidth(3);
                    //DrawableFillColor fillColor2 = new DrawableFillColor(new MagickColor(50, 50, 50, 128));
                    //DrawableRectangle dr2 = new DrawableRectangle(topLeftX, topLeftY, bottomRightX, bottomRightY);
                    //rotatedImage.Draw(dr2, strokeColor2, stokeWidth2, fillColor2);
                    #endregion

                    // Step 4 - Crop the image
                    MagickGeometry mg = new MagickGeometry(topLeftX, topLeftY, bottomRightX - topLeftX, bottomRightY - topLeftY);
                    rotatedImage.RePage();  // this is needed because otherwise the crop is relative to the page information and sometimes this leads to an incorrect crop
                    rotatedImage.Crop(mg);

                    log.LogInformation($"STEP: Cropped {inputFilename} to fit existing large regions");
                }
                else
                {
                    log.LogInformation($"STEP: Looked for large regions in {inputFilename}, none were found, skipping crop");
                }

                // Step 5 - Resize the image to 1200px width (todo: move to configuration)
                int originalWidth  = rotatedImage.BaseWidth;
                int originalHeight = rotatedImage.BaseHeight;
                rotatedImage.Resize(1200, 0); // make width 1200, height proportional
                log.LogInformation($"STEP: Resized {inputFilename} from {originalWidth}x{originalHeight} to {image.BaseWidth}x{image.BaseHeight}");

                // Step 6 - write out as Jpeg with 70% quality
                rotatedImage.Format  = MagickFormat.Jpeg;
                rotatedImage.Quality = 70;
                rotatedImage.Write(outputStream);
                log.LogInformation($"STEP: Wrote out {inputFilename} as JPEG");
            }

            log.LogInformation($"STEP: Processing of {inputFilename} done");
        }