Search code examples
c#wpfcoordinatespixel

How to get correct position of pixel from mouse coordinates?


I am getting the mouse coordinates using e.GetPosition. It returns the right coordinates when it is close to 0, however, the further I click from the top right of the image, the more inaccurate it gets.

I want to be able to click on a pixel and change the colour of it. But now it changes another pixel, not the one I click (except at 0,0).

 private void image_MouseDown(object sender, MouseButtonEventArgs e)
 {
       // coordinates are now available in p.X and p.Y
       var p = e.GetPosition(image);

       System.Drawing.Color red = System.Drawing.Color.FromArgb(255, 0, 0);

       //converting to bitmap
       MemoryStream outStream = new MemoryStream();

       BitmapEncoder enc = new BmpBitmapEncoder();
       enc.Frames.Add(BitmapFrame.Create(wBitmap));
       enc.Save(outStream);
       System.Drawing.Bitmap img = new System.Drawing.Bitmap(outStream);

       //calculating pixel position
       double pixelWidth = image.Source.Width;
       double pixelHeight = image.Source.Height;
       double dx = pixelWidth * p.X / image.ActualWidth;
       double dy = pixelHeight * p.Y / image.ActualHeight;

       //converting to int
       int x = Convert.ToInt32(dx);
       int y = Convert.ToInt32(dy);
           
       img.SetPixel(x, y, red);

       //putting it back to writable bitmap and image    
       wBitmap = BitmapToImageSource(img);
       image.Source = wBitmap;
}

image with changed pixel

I want to change a pixel like this in the image. However, it doesn't change the pixel I click at, but another one a bit further up.


Solution

  • In order to get the pixel position inside the Source bitmap for a mouse event on an Image element, you have to use the BitmapSource's PixelWidth and PixelHeight instead of Width and Height:

    private void ImageMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var image = (Image)sender;
        var source = (BitmapSource)image.Source;
        var mousePos = e.GetPosition(image);
    
        var pixelX = (int)(mousePos.X / image.ActualWidth * source.PixelWidth);
        var pixelY = (int)(mousePos.Y / image.ActualHeight * source.PixelHeight);
    
        ...
    }