pedrodotnet
pedrodotnet

Reputation: 818

C# - Automatic Image cropping

I have an App that sends emails. Most of the emails are 600px wide. When we create IPAD screenshots of those emails, they are created as 768px wide, therefore they have a grey frame like the following.

email We also have some wider templates, where the grey frame is just above and below the email.

Question: When generating screenshots, is it possible to identify the actual rectangle of the email, and crop the image to remove the grey frame around it?

Thanks

Upvotes: 0

Views: 770

Answers (2)

pedrodotnet
pedrodotnet

Reputation: 818

I'm sharing with you the solution I came up with. I hope that helps anybody. I created this helper that receives the image as a byte array and the color of the frame. Then it creates the frame limits and uses these values to create another image without the frame.

 public class ImageHelper
    {
        public static byte[] CropImage(byte[] sourceImage, Color grey)
        {
            using (var ms = new MemoryStream(sourceImage))
            {
                var Img = new Bitmap(ms);

                using (Bitmap bmp = new Bitmap(Img))
                {
                    var midX = bmp.Width / 2;
                    var midY = bmp.Height / 2;
                    var yTop = 0;
                    var yBottom = bmp.Height;
                    var xLeft = 0;
                    var xRight = bmp.Width;

                    for (int y = 0; y < bmp.Height; y++)
                    {
                        Color pxl = bmp.GetPixel(midX, y);
                        if (pxl != grey)
                        {
                            yTop = y;
                            break;
                        }
                    }

                    for (int x = 0; x < bmp.Width; x++)
                    {
                        Color pxl = bmp.GetPixel(x, midX);
                        if (pxl != grey)
                        {
                            xLeft = x;
                            break;
                        }
                    }

                    for (int x = bmp.Width - 1; x > midX; x--)
                    {
                        Color pxl = bmp.GetPixel(x, midX);
                        if (pxl != grey)
                        {
                            xRight = x;
                            break;
                        }
                    }

                    for (int y = bmp.Height - 1; y > midY; y--)
                    {
                        Color pxl = bmp.GetPixel(midX, y);
                        if (pxl != grey)
                        {
                            yBottom = y;
                            break;
                        }
                    }
                    Image redBmp = bmp.Clone(new Rectangle(xLeft, yTop, xRight - xLeft, yBottom - yTop), System.Drawing.Imaging.PixelFormat.DontCare);
                    byte[] byteImage = ImageToByteArray(redBmp);
                    return byteImage;
                }
            }
        }
        public static byte[] ImageToByteArray(Image imageIn)
        {
            MemoryStream ms = new MemoryStream();
            imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            return ms.ToArray();
        }
    }
}

Upvotes: 0

Trey
Trey

Reputation: 413

I do not have time to write a full solution, but here is how to traverse the bitmap, and check the colors.

System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(100, 100);

for (int x=0;x<= bmp.Width;x++)
{
    //just an example, you will have to use the actual color values
    System.Drawing.Color myBorderColor = System.Drawing.Color.Gray;
    for (int y = 0; y <= bmp.Width; y++)
    {
        var pixel = bmp.GetPixel(x, y);
        if (pixel!= myBorderColor)
        {
            //we have hit something that is not your border, record it.
            //so just mark down in a list or whatever where the grey is vs not
        }
    }
}

Upvotes: 1

Related Questions