0

I have a picture containing text :

enter image description here

I made a method to detect text rows. This method return the 4 corners for the text zone (always sorted) :

enter image description here

I want to modify the bitmap to draw a rectangle (with transparence) from theses 4 corners. Something like this :

enter image description here

I have my image in gray scale. I created a function to draw a rectangle, but I only achieve to draw a right rectangle :

public static void SaveDrawRectangle(int width, int height, Byte[] matrix, int dpi, System.Drawing.Point[] corners, string path)
{
    System.Windows.Media.Imaging.WriteableBitmap wbm = new System.Windows.Media.Imaging.WriteableBitmap(width, height, dpi, dpi, System.Windows.Media.PixelFormats.Bgra32, null);

    uint[] pixels = new uint[width * height];
    for (int Y = 0; Y < height; Y++)
    {
        for (int X = 0; X < width; X++)
        {
            byte pixel = matrix[Y * width + X];
            int red = pixel;
            int green = pixel;
            int blue = pixel;
            int alpha = 255;
            if (X >= corners[0].X && X <= corners[1].X &&
                Y >= corners[0].Y && Y <= corners[3].Y)
            {
                red = 255;
                alpha = 255;
            }

            pixels[Y * width + X] = (uint)((alpha << 24) + (red << 16) + (green << 8) + blue);
        }
    }

    wbm.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), pixels, width * 4, 0);
    using (FileStream stream5 = new FileStream(path, FileMode.Create))
    {
        PngBitmapEncoder encoder5 = new PngBitmapEncoder();
        encoder5.Frames.Add(BitmapFrame.Create(wbm));
        encoder5.Save(stream5);
    }
}

enter image description here

How can I draw a rectangle from 4 corners ?

A.Pissicat
  • 3,023
  • 4
  • 38
  • 93
  • What are you targetting: Winforms, WPF, ASP..? YOU should __always__ TAG your questions correctly so one can see it on the questions page! – TaW Aug 29 '18 at 08:50
  • @TaW i'm actually targeting a windows application. – A.Pissicat Aug 29 '18 at 09:08
  • Yes, but which platform was the question. You have now tagged ASP. Ina n comment you wrote you use SetPixel. Or do you meane UWP? – TaW Aug 29 '18 at 09:30
  • @TaW I'm not really sure (I don't know all the platform differences). I actually crated a project : "Windows Service (.NET framework) Visual C#" – A.Pissicat Aug 29 '18 at 09:41
  • But you really __need__ to understand this!! If you create a Service it is a program that is meant to run either on a Server machine or as a Service on a Desktop machine. Do not continue before clearing this up!! ASP will always run on a internet server with IIE; normal windows applications can be good old Winforms, WPF (Presentation Foundation) or UWP (Universal Windows Program). All different targets... – TaW Aug 29 '18 at 10:14

1 Answers1

0

I modify my condition by replacing with that code:

public static void SaveDrawRectangle(int width, int height, Byte[] matrix, int dpi, List<Point> corners, string path)
{
    System.Windows.Media.Imaging.WriteableBitmap wbm = new System.Windows.Media.Imaging.WriteableBitmap(width, height, dpi, dpi, System.Windows.Media.PixelFormats.Bgra32, null);

    uint[] pixels = new uint[width * height];
    for (int Y = 0; Y < height; Y++)
    {
        for (int X = 0; X < width; X++)
        {
            byte pixel = matrix[Y * width + X];
            int red = pixel;
            int green = pixel;
            int blue = pixel;
            int alpha = 255;
            if (IsInRectangle(X, Y, corners))
            {
                red = 255;
            }

            pixels[Y * width + X] = (uint)((alpha << 24) + (red << 16) + (green << 8) + blue);
        }
    }

    wbm.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), pixels, width * 4, 0);
    using (FileStream stream5 = new FileStream(path, FileMode.Create))
    {
        PngBitmapEncoder encoder5 = new PngBitmapEncoder();
        encoder5.Frames.Add(BitmapFrame.Create(wbm));
        encoder5.Save(stream5);
    }
}

public static bool IsInRectangle(int X, int Y, List<Point> corners)
{
    Point p1, p2;
    bool inside = false;

    if (corners.Count < 3)
    {
        return inside;
    }

    var oldPoint = new Point(
        corners[corners.Count - 1].X, corners[corners.Count - 1].Y);

    for (int i = 0; i < corners.Count; i++)
    {
        var newPoint = new Point(corners[i].X, corners[i].Y);

        if (newPoint.X > oldPoint.X)
        {
            p1 = oldPoint;
            p2 = newPoint;
        }
        else
        {
            p1 = newPoint;
            p2 = oldPoint;
        }

        if ((newPoint.X < X) == (X <= oldPoint.X)
            && (Y - (long)p1.Y) * (p2.X - p1.X)
            < (p2.Y - (long)p1.Y) * (X - p1.X))
        {
            inside = !inside;
        }

        oldPoint = newPoint;
    }

    return inside;
}

It works but have 2 failings :

  • generated images are very big (base image take 6 Mo and after drawing 25 Mo)
  • generation take several time (my images are 5000x7000 pixels, process take 10 seconds)

There is probably a better way, but this way is working good.

A.Pissicat
  • 3,023
  • 4
  • 38
  • 93