繁体   English   中英

通过onPaint方法获取图像绘制的像素值

[英]Get pixel value of image draw through onPaint methode

我正在开发一个自定义 C# UserControl WinForm 以在使用鼠标缩放时在背景上显示图像并显示滚动条。 为此,我重写了OnPaint方法。 在其中,如果我加载了图像,根据一些参数,我知道源矩形和目标矩形的大小。 同样,我知道缩放时始终保持屏幕左上角的比例和平移适用于什么。 对于缩放,我使用滚动鼠标事件来更新缩放工厂。

这是我与此覆盖方法相关的代码。

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    // Draw image
    if(image != null)
    {
        // 
        Rectangle srcRect, destRect;
        Point pt = new Point((int)(hScrollBar1.Value/zoom), (int)(vScrollBar1.Value/zoom));

        if (canvasSize.Width * zoom < viewRectWidth && canvasSize.Height * zoom < viewRectHeight)
            srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height);  // view all image
        else if (canvasSize.Width * zoom < viewRectWidth)
            srcRect = new Rectangle(0, pt.Y, canvasSize.Width, (int)(viewRectHeight / zoom));  // view a portion of image but center on width
        else if (canvasSize.Height * zoom < viewRectHeight)
            srcRect = new Rectangle(pt.X, 0, (int)(viewRectWidth / zoom), canvasSize.Height);  // view a portion of image but center on height
        else
            srcRect = new Rectangle(pt, new Size((int)(viewRectWidth / zoom), (int)(viewRectHeight / zoom)));   // view a portion of image
    
        destRect = new Rectangle((int)(-srcRect.Width/2),
            (int)-srcRect.Height/2,
            srcRect.Width,
            srcRect.Height); // the center of apparent image is on origin
 
        Matrix mx = new Matrix(); // create an identity matrix
        mx.Scale(zoom, zoom); // zoom image

        // Move image to view window center
        mx.Translate(viewRectWidth / 2.0f, viewRectHeight / 2.0f, MatrixOrder.Append);

        // Display image on widget
        Graphics g = e.Graphics;
        g.InterpolationMode = interMode;
        g.Transform = mx;
        g.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel);
    }
}

我的问题是当我在这个 WinForm 的 MouseMove 覆盖方法上时如何获取像素值?

我认为理解只有在使用 PaintEventArgs 的方法中才有可能,但我不确定如何处理它。 我尝试了很多东西,但现在我得到的更好的是在屏幕上使用鼠标 position 并使用这些“错误”坐标在原始 bitmap 中找到像素值。 我无法将屏幕上的这个相对 position 与此处显示的图像像素的真实坐标联系起来。 也许有一种方法可以“仅”获取不通过我用于绘画方法的图像 bitmap 的像素值? 或者可能不是。

预先感谢您的帮助。 此致。

我无法完全理解您的绘图代码,但您可以对鼠标坐标进行逆变换。 因此,您可以将鼠标坐标转换回原点并将其1/zoom 这个简单的过程为您提供了图像空间坐标。

我提供了一个带有自己的绘图代码(不是您的代码/算法)的示例代码,但这仍然可以让您了解逆变换。 这很简单,所以看看示例代码。

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 GetPixelFromZoomedImage
{
    public partial class MainForm : Form
    {
        public Form1()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
            InitializeComponent();
        }
        private float m_zoom = 1.0f;
        private Bitmap m_image;
        private Point m_origin = Point.Empty;
        private Point m_delta = Point.Empty;
        private SolidBrush m_brush = new SolidBrush(Color.Transparent);
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.TranslateTransform(m_origin.X, m_origin.Y);
            g.ScaleTransform(m_zoom, m_zoom); 
            g.DrawImageUnscaled(m_image, Point.Empty); 
            g.ResetTransform();
            g.FillRectangle(m_brush, ClientSize.Width - 50, 0, 50, 50);
            base.OnPaint(e);
        }
        protected override void OnHandleCreated(EventArgs e)
        {
            m_image = (Bitmap)Image.FromFile("test.png");
            base.OnHandleCreated(e);
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                m_delta = new Point(m_origin.X - e.X, m_origin.Y - e.Y);
            }
            base.OnMouseDown(e);
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                m_origin = new Point(e.X + m_delta.X, e.Y + m_delta.Y); 
                Invalidate();
            }
            int x = (int)((e.X - m_origin.X) / m_zoom);
            int y = (int)((e.Y - m_origin.Y) / m_zoom);
            if (x < 0 || x >= m_image.Width || y < 0 || y >= m_image.Height)
                return;
            
            m_brush.Color = m_image.GetPixel(x, y); 
            Invalidate();
            base.OnMouseMove(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            float scaleFactor = 1.6f * (float)Math.Abs(e.Delta) / 120;
            if(e.Delta > 0) 
                m_zoom *= scaleFactor; 
             else
                m_zoom /= scaleFactor;
            m_zoom = m_zoom > 64.0f ? 64.0f : m_zoom;
            m_zoom = m_zoom <  0.1f ?  0.1f : m_zoom;
            Invalidate();
            base.OnMouseWheel(e);
        }
        
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM