Posts Tagged drawline

A brand new version of eDigitizer with improved functions

Since the eDigitizer 2.0 released in a couple of year ago, new functions were requested and fulfilled. Some minor bugs were fixed. Now it is time to announce that a brand new version 2.10 is released. The new version brings the following new functions to the application.

  1. The linear distance of each segment is calculated and added together. This is the total distance between the first and last points. When you save the digitized data to file, you automatically get the points and the distances.
  2. Draw markers and line segments between adjacent points. That will help user to keep track of what is digitized and how good he does the job.

The following functions are either fixed or enhanced.

  1. The image can be restored by clicking the restore button. After the image is restored to its original, all line segments and point markers on the image will disappear.
  2. When you load a new image, all digitized information (data) will be cleaned. So make sure to save your digitized data before you do that.
  3. Save image function will save the image plus the point markers and line segments. So be careful that you do not overwrite the original image.
  4. During the digitizing period and after axes are digitized, you should not switch between two different size modes. if you do, the digitized data will be messed up.

The new version need .Net 2.0 and above framework to run. It can be used in Windows XP, Windows Vista, and Windows 7 etc.

To get the new release, just simply download the zip file and unpacked files into a folder; double click the eDigitizer application file; you can run the application right way.

Here is a snapshot for you to view.

Download the new release: eDigitizer210



Tags: , , , , , ,

Draw on stretched, zoomed, or centered images in PictureBox in C#

When I wrote an application, eDigitizer 2.0 and its new release eDigitizer 2.10,  that allows user to draw lines on images in the PictureBox control, I encountered a problem that lines or shapes I drew on the image are off the place, that is, not positioned in the place I clicked. The problem does not occur if I show images in “normal” SizeMode. I googled a long time and saw people were asking the very question again and again but not any useful solutions. Since the problem irritated me, I decided to write my own method to solve the problem.

The fact is the size of PictureBox control and the size of image are not same. We have to project the x,y coordination of the mouse click on PictureBox control to the x’,y’ coordination of the loaded image. For the different SizeMode type, the projection is different.

For the PictureBoxSizeMode.StretchImage mode, the loaded image is stretched to fill PictureBox control. The ratio to stretch image in the x axis is based on the width of the image and PictureBox control while the ratio to stretch image in the y axis is based on the height of the image and the PictureBox control. The two ratios are independent.

For the PictureBoxSizeMode.CenterImage mode, the center of the loaded iamge will overlap with the center of the PictureBox control. If the image is smaller than the PictureBox control, it will be inside the control. Otherwise, only the center potion with the same size as the control shows. There is no skew and distortion.

For the PictureBoxSizeMode.Zoom mode, it is a little bit complicated. The ratio to shrink or enlarge the image is same in both of the axes. We can get an x_ratio that is the ratio of width of the image and the control and y_ratio that is the ratio of height of the image and the control. The ratio to be used in the zoom is the larger one in the two ratios. If the x_ratio is the larger one, the image will fill the control in the x axis. Otherwise the image will file the control in the y axis. The tricky part is how to get the right projection in the direction where the image does not fill the control. We have to project the width or height of the image in the ratio first and then calculate the border space between the image and the control.

The above ideas were put into one method that needs three input arguments: the image object, and x and y value of the mouse click point in the control. The output is an array with two elements projected x and y values in the image object. The algorithm works well for images loaded in a PictureBox control. Here is the source code.

int [] xy_projection(Bitmap myBitmap2, int x, int y)
	int heightB = myBitmap2.Height;
	int heightP = pictureBoxBoard.Height;
	int widthB = myBitmap2.Width;
	int widthP = pictureBoxBoard.Width;
	double xRatio = (double) widthB / (double)widthP;
	double yRatio = (double) heightB / (double)heightP;
	int [] xy = new int[2];
	if (pictureBoxBoard.SizeMode == PictureBoxSizeMode.StretchImage)
		xy[0] = (int) (x * xRatio);
		xy[1] = (int) (y * yRatio);
	else if (pictureBoxBoard.SizeMode == PictureBoxSizeMode.CenterImage)
		int borderHeight = (heightP -heightB) / 2;
		int borderWidth = (widthP - widthB) / 2;
		xy[0] = x - borderWidth;
		xy[1] = y - borderHeight;
	else if (pictureBoxBoard.SizeMode == PictureBoxSizeMode.Zoom)
		double ratio = xRatio;
		bool x_filled = true;
		if ( ratio < yRatio)
			ratio = yRatio;
			x_filled = false;
		if (x_filled)
			heightB = (int) (heightB / ratio);
			int borderHeight = (heightP - heightB) / 2;
			xy[0] = (int) (x * ratio);
			xy[1] = (int) ((y - borderHeight) * ratio);
			widthB = (int) (widthB / ratio);
			int borderWidth = (widthP - widthB) / 2;
			xy[0] =(int) ((x - borderWidth) * ratio);
			xy[1] =(int) (y * ratio);
		xy[0] = x;
		xy[1] = y;
	return xy;

To draw on the image in the PictureBox control, you have to get the image from the control. Then generate a Graphics object from it. Now you can draw on the image based on mouse clicks. Whenever you get the mouse point x, y values, we have to use the above function to project the values to the image axes. To be nice, you have to release the memory that the Graphics object uses. In the following code snippet, we draw a cross at the mouse click location and connect the point with the previous mouse click point.

Color color = Color.Black;
Color veryTransparentColor = Color.FromArgb(77,color.R, color.G, color.B);
Bitmap myBitmap2 = (Bitmap)pictureBoxBoard.Image;
Graphics g = Graphics.FromImage(myBitmap2);

//Brush myBrush = new SolidBrush(color);
//g.DrawString(heightB.ToString()+","+widthB.ToString()+";"+heightP.ToString()+widthP.ToString(),this.Font, myBrush, mvPoint);

// draw a small cross
int penWidth = 2;
Pen myPen = new Pen(veryTransparentColor, penWidth);
int [] xy = xy_projection(myBitmap2, mvPoint.X, mvPoint.Y);
g.DrawLine(myPen, new Point(xy[0]-5,xy[1]), new Point(xy[0]+5,xy[1]));
g.DrawLine(myPen, new Point(xy[0],xy[1]-5), new Point(xy[0],xy[1]+5));

// connect two adjacent points if there are more than one points
// the position is not right.
if (myPoints.Count > 1)
	int myPos = myPoints.Count-1;
	int [] xy1 = xy_projection(myBitmap2, ((Point)myPoints[myPos-1]).X,((Point)myPoints[myPos-1]).Y);
	int [] xy2 = xy_projection(myBitmap2, ((Point)myPoints[myPos]).X,((Point)myPoints[myPos]).Y);

Tags: , , , , , , , , , , , , ,