Home > database >  Get pixel value of image draw through onPaint methode
Get pixel value of image draw through onPaint methode

Time:08-13

I am developping a custom C# UserControl WinForm to display an image on background and display scrollbars when I zoom with the mouse. For this, I overrided the OnPaint method. In it, if I have an image loaded, according some parameters I know the source and destination rectangle sizes. In the same way, I know what scale and translation apply to always keeping the top left corner on screen when zooming. And for the zoom, I use the scrollmouse event to update the zoom factory.

Here is my code related to this override method.

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

My question is how to get the pixel value when I am on the MouseMove override method of this WinForm ?

I think understand that it is possible only in method with PaintEventArgs but I am not sure how to deal with it. I tried a lot of things but for now the better I got is use the mouse position on the screen and find the pixel value in the original bitmap with these "wrong" coordinates. I can't link this relative position on the screen with the real coordinates of the pixel of the image display at this place. Maybe there is method to "just" get the pixel value not passing through the image bitmap I use for the paint method ? Or maybe not.

Thank you in advance for your help. Best regards.

CodePudding user response:

I couldn't completely understand your drawing code but you can do an inverse transformation on mouse coordinate. So, you can translate the mouse coordinate back to the origin and scale it by 1/zoom. This simple process gives you the image space coordinate.

I provide an example code with its own drawing code (not your code/algorithm) but that can still give you the idea of inverse transformation. It is pretty simple so look at the example 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;

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 onm ouseDown(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 onm ouseMove(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 onm ouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
        }
        protected override void onm ouseWheel(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);
        }
        
    }
}

  • Related