How to to shrink(scale) an entire graphics structure? - c#

I’m trying to fit a lot of rectangles into a Bitmap, which will be displayed in a picturebox. In my real code, I figure out the total width and height of a rectangle that can encompass all them, and then I divide that by the size of the Bitmap, to get my scaling factor. The problem is I can’t figure out how to perform the scaling. The code below is a simple version of what I need to do.
Please keep in mind that I cannot rely on the picturebox’s scaling abilities (stretch), and I don’t want to simply apply the scale to the width and height of all the rectangles, because in my real code it wouldn’t work very well. I need a way to shrink it down in Graphics. It is important the Bitmap stays the same size that it is (300 X 300). Thanks. The below code is what I've gotten so far, but nothing changes with the size.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication22
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap BM = new System.Drawing.Bitmap(300, 300);
Pen PenTest = new System.Drawing.Pen(Brushes.Red);
private void Form1_Load(object sender, EventArgs e)
{
using (Graphics GR = Graphics.FromImage(BM))
{
GR.DrawRectangle(PenTest, new Rectangle(0,0,500,500));
// I need a scale of 0.60 in this example, because 300/500 = .6
GR.ScaleTransform(.6F, .6F);//Doesn't Work. No Change at all in the size of the rectangle.
}
pictureBox1.Image = BM;
}
}
}

Graphics.ScaleTransform performs the transformation but it does not draw anything.
You would need to then draw a rectangle after performing the transform on the graphics object:
using (Graphics GR = Graphics.FromImage(BM))
{
// ....
GR.ScaleTransform(.6F, .6F);
GR.DrawRectangle(PenTest, new Rectangle(0,0,500,500));
}

Related

Drawing a circle on a pictureBox from another winform

I have two winforms in my application. One of the forms has a picturebox with a jpg loaded of our building plan. The main form has code that does facial recognition identifying people coming into certain areas. I have been asked to modify this program to show an identified individual's location on the building plan. I have a database that has all the X,Y coordinates of the locations that should map to the building plan image. I have looked around and tried to find some code that will draw a circle on the map at the X,Y coordinates as the person progresses through areas of the building by erasing all the existing circles and updating this new one. So on the map form I put in the following code:
public void DrawCircle(int x, int y)
{
Graphics gf = pictureBox1.CreateGraphics();
gf.DrawEllipse(new Pen(Color.Red), new Rectangle(x, y, 400, 400));
pictureBox1.Refresh();
}
Then from the update method (right now a button click for testing) on the main form I call this method on the map form. The method gets called, but the circle doesn't show up on the form. I have tried both Refresh and Invalidate and neither method seems to draw the circle on the image.
I haven't done winforms development for years, so I'm sure I am missing some plumbing somewhere. Here is the code on the mainform:
LocationMap map = new LocationMap();
public Form1()
{
InitializeComponent();
//set up signalR
UserName = "MovementHub1";
ConnectAsync();
//show the map screen
map.Show();
map.WindowState = FormWindowState.Maximized;
...
Then in a click event (for testing right now) I have this code:
private void button2_Click(object sender, EventArgs e)
{
map.DrawCircle(340, 258);
}
Once I get the circle drawn on the other form, then I will remove the code from the click event and move it another event that does the updating on the location. If it's possible, I would like to put a label by the circle that has the person's name. Right now this is a proof of concept, I just need help getting the circle on the form to start with.
Thanks.
I tried It out by myself and came up with that:
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StackoverflowHelp
{
public partial class Form1 : Form
{
Form2 form = new Form2();
public Form1()
{
InitializeComponent();
form.Show();
}
private void Button1_Click(object sender, EventArgs e)
{
form.DrawCircle(100, 100);
}
}
}
Form2.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StackoverflowHelp
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
DrawCircle(10, 10);
}
public void DrawCircle(int x, int y)
{
Graphics gf = Graphics.FromImage(pictureBox1.Image);
gf.DrawEllipse(new Pen(Color.Red), new Rectangle(x, y, 20, 20));
gf.Dispose();
pictureBox1.Refresh();
pictureBox1.Invalidate();
pictureBox1.Update();
}
}
}
Instead of calling CreateGraphics() on the picturebox I created the graphics object using the current image.

How to save an image file using C#?

I'm working with C#, só I start one "Windows Form application" in order to use the "picturebox", where I can draw some things. I would like to know if there's a way to save a file in some kind of file (like JPG). Here's an example, where I draw a simple line in a pictureBox with 300 of Height and 300 of Width.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AskStack
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Here I declare 'MyDraw' and a Pen that I'm gonna use
Graphics MyDraw;
Pen BluePen = new Pen(Color.Blue, 10);
// What happens when I click in my button
private void ButtonDraw_Click(object sender, EventArgs e)
{
MyDraw.Clear(Color.White);
// Here I relate MyDraw to the pictureBox that I have in my Form
MyDraw = pictureBox1.CreateGraphics();
// Here I Just draw a simple line
MyDraw.DrawLine(BluePen, 25, 25, 80, 80);
// I don't know exactly what this does
MyDraw.Save();
}
}
}
I would like to know if there's a way to save this image in a file where I can easily acess it. Also, I would like to know if there's a way to save an JPG file and dimension the file's size WITHOUT using a pictureBox. Thanks!!!
You can try with this line of code:
pictureBox1.Image.Save(#"Path",ImageFormat.Jpeg);

Tesseract OCR: very inaccurate result

Below is my very simple program to test Tesseract performance. The result I got was not as expected though the picture was a high quality and very clear screenshot (not a complex picture with colors). Please take a look at my code and the result below. I'm not sure if I did something wrong or the Tesseract engine can not handle this?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using tessnet2;
namespace ImageProcessTesting
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int up_lef_x = 1075;
int up_lef_y = 0070;
int bo_rig_x = 1430;
int bo_rig_y = 0095;
int width = bo_rig_x - up_lef_x;
int height = bo_rig_y - up_lef_y;
var bmpScreenshot = new Bitmap(width, height, PixelFormat.Format32bppArgb);
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(
1075,
0070,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
// bmpScreenshot.Save("C:\\Users\\Exa\\Screenshot.png", ImageFormat.Png);
var image = bmpScreenshot;
var ocr = new Tesseract();
ocr.Init(#"C:\Users\Exa\Desktop\tessdata", "eng", false);
var result = ocr.DoOCR(image, Rectangle.Empty);
string result_str = "";
foreach (Word word in result)
result_str += word.Text;
MessageBox.Show(result_str);
}
}
}
96DPI screen shots are typically not adequate for OCR. As written in Tesseract wiki:
There is a minimum text size for reasonable accuracy. You have to consider resolution as well as point size. Accuracy drops off below 10pt x 300dpi, rapidly below 8pt x 300dpi. A quick check is to count the pixels of the x-height of your characters. (X-height is the height of the lower case x.) At 10pt x 300dpi x-heights are typically about 20 pixels, although this can vary dramatically from font to font. Below an x-height of 10 pixels, you have very little chance of accurate results, and below about 8 pixels, most of the text will be "noise removed".
However, if you know what exact font it is, you can try re-train tesseract to get better result.

C# Moving a cross into a picturebox based on the Thumbstick Position

I want to draw a cross into a picturebox. In the next step I want to move the cross based on my Data.
Which is the Thumbsticks position. I want it to appear similar to the figure below.
Here is my Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SlimDX;
using SlimDX.XInput;
namespace Controller_Test
{
public partial class Form1 : Form
{
GamepadState Controller = new GamepadState(UserIndex.One);
Graphics drawArea;
public Form1()
{
InitializeComponent();
timer1.Enabled = true;
drawArea = pictureBox1.CreateGraphics();
}
private void timer1_Tick(object sender, EventArgs e)
{
Controller.Update();
var LeftStick = Controller.LeftStick;
float LeftStickX = LeftStick.Position.X;
float LeftStickY = LeftStick.Position.Y;
Pen blackPen = new Pen(Color.Black);
// horizontal Line
drawArea.DrawLine(blackPen, x1+LeftStickX, y1-LeftStickY, x2+LeftStickX, y2-LeftStickY);
// vertical Line
drawArea.DrawLine(blackPen, x1+LeftStickX, y1-LeftStickY, x2+LeftStickX, y2-LeftStickY);
}
}
public class GamepadState
{Get Postiton......}
}
My problem now is, if I move the Thumbstick every time a new cross is drawn but the old one is still in the
Picturebox like in the figure below. If i use the pictureBox1.Invalidate():/pictureBox1.Refresh(); Funtcion
the cross becomes invisible and is not displayed anymore. The interval of the timer is on 1.
What could i change in order to get the code to work?

Trying to load layers to a control c#

im trying to load some rectangles as "layers" of the form, i loaded an image as also a layer of the form, but the problem with those rectangles is that they "overlay" the image, erasing portions of it, i want them to be seen as boxes of the image to display info, and i also want to be able to overlay a rectangle onto another rectangle without erasing eachother.
here is the class of the rectangle
namespace Imagen_capas
{
class rectangulotransp : UserControl
{
public Pen pen11;
private Rectangle Myrectangle;
public rectangulotransp(int x,int y,int alto, int ancho, Rectangle tamacontrol)
{
Size = tamacontrol.Size;
Location = tamacontrol.Location;
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
Myrectangle = new Rectangle(x, y, alto, ancho);
pen11 = nuevopen();
}
private Pen nuevopen()
{
Pen mypen1 = new Pen(Color.Red);
return mypen1;
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawRectangle(pen11,Myrectangle);
base.OnPaint(e);
}
}
}
And the code of the form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Imagen_capas
{
public partial class Form1 : Form
{
rectangulotransp rect;
rectangulotransp rect2;
public Form1()
{
InitializeComponent();
rect = new rectangulotransp(50, 14, 500, 100,new Rectangle(0,0,Width+400,Height));
// this.Controls.Add(rect);
rect2 = new rectangulotransp(0, 50, 20, 100,new Rectangle(20,50,Width,Height));
this.Controls.Add(rect2);
this.Controls.Add(rect);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
I think the problem is that when you set Transparent background, the rectangle is using the Form Backcolor and it seems to you that is erasing the other rectangle.
Maybe you could try painting your transparent rectangle as 4 lines instead of a rectangle.
Hope it helps you
my friends, i solved it in this way.
I created a class for the rectangle, and then another class for a control, in which i painted all the rectangles just like you told me, then the image, and then i added it as a layer of the form using the controls.add, in that way i was also able to put an image under it without being erased by the rectangles.
thanks!!

Categories

Resources