如何在 C# windows 窗体中绘制可缩放图像 [英] How to Draw on Zoomable Image in C# windows Forms

查看:43
本文介绍了如何在 C# windows 窗体中绘制可缩放图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在实施一个项目,该项目可以读取图像平移、缩放和执行其他操作......一切都很顺利,直到我尝试使用鼠标右键实现绘图.

so am implementing a project that can read image pan it, zoom it and do other stuff.. everything was going well until i tried implementing a draw with right mouse button.

问题是当我画一条线时,图像上出现的线与我在屏幕上画的线不对应,这意味着它发生了偏移,我知道这是因为图像的重新调整大小和缩放,但是当我用原始大小(图像)和平移在图像上绘制线条时;我没有问题.

the problem is when i draw a line, the line that appears on the image does not correspond to the line i drew on screen, meaning its shifted and i know its because of the re-sizing and zooming of the image, but when i draw lines on the image with its original size(the image) and with panning also ; i have no problem.

这是代码.

所以首先这里是当我点击浏览并选择图像时我如何加载图像

so first here is how i load the image when i click browse and select image

Myimage = new Bitmap(ImagePath);
resized = myImage.Size;
imageResize();
pictureBox.Paint += new    System.Windows.Forms.PaintEventHandler(this.pictureBox_Paint);
                pictureBox.Invalidate();

imageResize 函数执行以下操作:

the imageResize function does the following:

void imageResize()
{     
//calculated the size to fit the control i will draw the image on   
 resized.Height = someMath;
 resized.Width = someMath;
}

然后在我写的pictureBox_Paint事件的事件处理程序中:

then in the event handler for the pictureBox_Paint event i wrote:

private void pictureBox_Paint(object sender,      System.Windows.Forms.PaintEventArgs e)
{
// Create a local version of the graphics object for the PictureBox.
Graphics PboxGraphics = e.Graphics;
PboxGraphics.DrawImage(myImage, imageULcorner.X, imageULcorner.Y,     resized.Width, resized.Height);
}

如您所见,调整后的尺寸不是原始图像尺寸,我这样做是因为我希望图像显示在图片框控件上集中并填充现在下一部分是我的问题开始的地方

as you can see the resized size is not the original image size i did this because i wanted the image to show on the picturebox control centralized and filled now the next part IS WHERE MY PROBLEM BEGINS

我必须使用鼠标右键在图像上画线,所以我实现了pictureBox_MouseDown &pictureBox_MouseUp 事件处理程序

i have to draw lines on image using right mouse button so i implemented pictureBox_MouseDown & pictureBox_MouseUp event handlers

// mouse down event handler
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
else if (mouse.Button == MouseButtons.Right)
{
mouseDown = mouse.Location;
mouseDown.X = mouseDown.X - imageULcorner.X;
mouseDown.Y = mouseDown.Y - imageULcorner.Y;
draw = true;
}
}

这里是鼠标向上事件处理程序

here is the mouse up event handler

//Mouse UP
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
else if (mouse.Button == MouseButtons.Right)
{
if (draw)
 {
mouseLocationNow.X = mouse.X - imageULcorner.X;
mouseLocationNow.Y = mouse.Y - imageULcorner.Y;
//
// get graphics object of the image ( the original not the resized)
// as the resized image only appears when i draw on the graphics of the
// pictureBox control
// i know the problem lies here but how can i fix it
//
Graphics image = Graphics.FromImage(myImage);
Pen pen = new Pen(Color.Red, 2);
image.DrawLine(pen, mouseLocationNow, mouseDown);
pictureBox.Invalidate();
}
draw = false;
}

所以最后我希望能够在重新调整大小的图像上绘制并使其对应于真实图像以及我绘制线条的屏幕感谢并抱歉发了这么长的帖子,但这个问题让我发疯了.

so in the end i want to be able to draw on the re-sized image and make it correspond to the real image and also to the screen where i draw the line thanks and sorry for the long post but this problem has been driving me crazy.

推荐答案

这是一个 PictureBox 子类,它不仅支持将缩放应用于 Image到您在其表面绘制的图形.

Here is a PictureBox subclass that supports the ability to apply zooming not only to the Image but also to graphics you draw onto its surface.

它包括一个 SetZoom 函数,通过缩放自身和矩阵来放大.

It includes a SetZoom function to zoom in by scaling both itself and a Matrix.

它还有一个 ScalePoint 函数,您可以使用它从鼠标事件中接收到的像素坐标计算未缩放的坐标.

It also has a ScalePoint function you can use to calculate the unscaled coordinates from the pixel coordinates you receive in the mouse events.

这个想法是使用 Transformation Matrix 来缩放 Graphics 对象将在 Paint 事件中绘制的任何像素.

The idea is to use a Transformation Matrix to scale any pixels the Graphics object will draw in the Paint event.

我包含了一些用于测试表单的代码.

I include a little code for the form for testing.

public partial class ScaledPictureBox : PictureBox
{
    public Matrix ScaleM { get; set; }

    float Zoom { get; set; }
    Size ImgSize { get; set; }

    public ScaledPictureBox()
    {
        InitializeComponent();
        ScaleM = new Matrix();
        SizeMode = PictureBoxSizeMode.Zoom;
    }

    public void InitImage()
    {
        if (Image != null)
        {
            ImgSize = Image.Size;
            Size = ImgSize;
            SetZoom(100);
        }
    }

    public void SetZoom(float zoomfactor)
    {
        if (zoomfactor <= 0) throw new Exception("Zoom must be positive");
        float oldZoom = Zoom;
        Zoom = zoomfactor / 100f;
        ScaleM.Reset();
        ScaleM.Scale(Zoom , Zoom );
        if (ImgSize != Size.Empty) Size = new Size((int)(ImgSize.Width * Zoom), 
                                                   (int)(ImgSize.Height * Zoom));

    }

    public PointF ScalePoint(PointF pt)
    {   return new PointF(pt.X / Zoom , pt.Y / Zoom );     }

}

这是表单中进行测试的代码:

Here is the code in the Form that does the testing:

public List<PointF> somePoints = new List<PointF>();

private void scaledPictureBox1_MouseClick(object sender, MouseEventArgs e)
{
    somePoints.Add(scaledPictureBox1.ScalePoint(e.Location) );
    scaledPictureBox1.Invalidate();
}

private void scaledPictureBox1_Paint(object sender, PaintEventArgs e)
{
    // here we apply the scaling matrix to the graphics object:
    e.Graphics.MultiplyTransform(scaledPictureBox1.ScaleM);
    using (Pen pen = new Pen(Color.Red, 10f))
    {
        PointF center = new PointF(scaledPictureBox1.Width / 2f, 
                                   scaledPictureBox1.Height / 2f);
        center = scaledPictureBox1.ScalePoint(center);
        foreach (PointF pt in somePoints)
        {
            DrawPoint(e.Graphics, pt, pen);
            e.Graphics.DrawLine(Pens.Yellow, center, pt);
        }
    }
}

public void DrawPoint(Graphics G, PointF pt, Pen pen)
{
    using (SolidBrush brush = new SolidBrush(pen.Color))
    {
        float pw = pen.Width;
        float pr = pw / 2f;
        G.FillEllipse(brush, new RectangleF(pt.X - pr, pt.Y - pr, pw, pw));
    }
}

以下是绘制几个点后的结果,显示了在四种不同缩放设置下的相同点;ScaledPictureBox 显然放在 AutoScroll-Panel 中.线条显示如何使用常规绘图命令..

Here are the results after drawing a few points showing the same points in four different zoom settings; the ScaledPictureBox is obviously placed in an AutoScroll-Panel. The lines show how to use the regular drawing commands..

这篇关于如何在 C# windows 窗体中绘制可缩放图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆