2015-02-20 2 views
0

, поэтому я реализую проект, который может читать изображение, панорамировать его, масштабировать и делать другие вещи .. все шло хорошо, пока я не попытался реализовать ничью правой кнопкой мыши.Как рисовать на масштабируемом изображении в окнах C# Формы

проблема заключается в том, когда я рисую линию, линия, которая появляется на изображении, не соответствует линии, нарисованной на экране, что означает ее смещение, и я знаю его из-за изменения размера и масштабирования изображения, но когда я рисую линии на изображении с его оригинальным размером (изображение) и с панорамированием; У меня нет никаких проблем.

вот код.

поэтому сначала здесь, как я загрузить изображение, когда я нажимаю просмотреть и выбрать изображение

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

функция imageResize выполняет следующие действия:

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

затем в обработчик событий для события pictureBox_Paint я написал:

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); 
} 

, как вы можете видеть, размер изменен не изначально NAL размера изображения я сделал это, потому что я хотел изображения, чтобы показать на контроле PictureBox централизованного и наполнил теперь следующая часть ГДЕ МОЯ ПРОБЛЕМА НАЧАЛА

я должен рисовать линии на изображении с помощью правой кнопки мыши, так что я реализованного pictureBox_MouseDown & pictureBox_MouseUp обработчики событий

// 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; 
} 
} 

здесь мышь вверх обработчик события

//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; 
} 

так в конце концов, я хочу, чтобы иметь возможность опираться на повторное размера изображения и сделать его соответствуют ре al image, а также на экране, где я рисую линию спасибо и извините за длинный пост, но эта проблема сводила меня с ума.

+0

Короткая версия: вам нужно а) вычислить точки от события мыши, чтобы соответствовать зумом (назад, так как вы направленных на увеличенный мир) и b) масштабировать графический объект (вперед, используя преобразование матрицы) до того же масштаба, что и изображение в окне изображения. – TaW

+0

Если вы хотите использовать WPF, я задал аналогичный вопрос в прошлом. Вопрос и ответ могут быть полезны - http://stackoverflow.com/questions/14729853/wpf-zooming-in-on-an-image-inside-a-scroll-viewer-and-having-the-scrollbars-a – JMK

+0

@TaW я знал (A), но я не знал (B) существовал ... звучит как хороший трек, чтобы найти решение .. спасибо. –

ответ

1

Подкласс PictureBox, который поддерживает возможность применения масштабирования не только до Image, но и для графики, которую вы рисуете на ее поверхности.

Он включает в себя функцию SetZoom для масштабирования, масштабируя как себя, так и матрицу.

Он также имеет функцию ScalePoint, которую вы можете использовать для расчета немасштабированных координат по координатам пикселя, которые вы получаете в событиях мыши.

Идея состоит в том, чтобы использовать Transformation Matrix для масштабирования любых пикселей, которые объект Graphics будет рисовать в событии Paint.

Включая небольшой код для формы для тестирования.

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);  } 

} 

Вот код, в форме, которая делает тестирование:

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.Линии показывают, как использовать обычные команды рисования ..

enter image description hereenter image description hereenter image description hereenter image description here

+0

спасибо очень много, ваш намек был уже достаточно :) , но спасибо за все усилия, чтобы написать код, и, конечно, он выглядит более эффективным и организованным. К сожалению, человек, который дал мне эту задачу, явно попросил не реализовывать ее, используя преобразования в C#. Я выяснил проблему с моим кодом, но я не буду публиковать свой ответ, потому что я думаю, что ваш лучше. –

+0

Интересно. Без масштабирования преобразования также будут работать координаты. Там вам также нужно масштабировать Widths of Pens, а затем некоторые. – TaW

Смежные вопросы