¿Cómo puedo convertir de coordenadas del ratón a las coordenadas de píxel de un TransformedBitmap incrustado en una matriz más grande contenedor?

0

Pregunta

Similar a ¿Cómo puedo convertir de coordenadas del ratón a las coordenadas de píxel de un TransformedBitmap? pero con el añadido de las arrugas que mi Image en realidad está incrustado en una matriz más grande Grid, que tiene un fondo, y me gustaría que el píxel de coordenadas para ser preciso cuando se cierne en las regiones más allá de los límites de la imagen.

Aquí está mi XAML:

    <DockPanel>
        <Label DockPanel.Dock="Bottom" Name="TheLabel" />
        <Grid DockPanel.Dock="Top" Name="TheGrid" Background="Gray" MouseMove="TheGrid_MouseMove">
            <Image Name="TheImage" Stretch="Uniform" RenderOptions.BitmapScalingMode="NearestNeighbor" />
        </Grid>
    </DockPanel>

Y aquí está el código:

        public MainWindow()
        {
            InitializeComponent();

            const int WIDTH = 4;
            const int HEIGHT = 3;
            byte[] pixels = new byte[WIDTH * HEIGHT * 3];
            // top-left corner red, bottom-right corner blue for orientation
            pixels[0] = Colors.Red.B;
            pixels[1] = Colors.Red.G;
            pixels[2] = Colors.Red.R;
            pixels[(WIDTH * (HEIGHT - 1) + (WIDTH - 1)) * 3 + 0] = Colors.Blue.B;
            pixels[(WIDTH * (HEIGHT - 1) + (WIDTH - 1)) * 3 + 1] = Colors.Blue.G;
            pixels[(WIDTH * (HEIGHT - 1) + (WIDTH - 1)) * 3 + 2] = Colors.Blue.R;
            BitmapSource bs = BitmapSource.Create(WIDTH, HEIGHT, 96.0, 96.0, PixelFormats.Bgr24, null, pixels, WIDTH * 3);
            TheImage.Source = new TransformedBitmap(bs, new RotateTransform(90.0));
        }

        private void TheGrid_MouseMove(object sender, MouseEventArgs e)
        {
            Point p = TheGrid.TranslatePoint(e.GetPosition(TheGrid), TheImage);
            if (TheImage.Source is BitmapSource bs)
            {
                p = new Point(p.X * bs.PixelWidth / TheImage.ActualWidth, p.Y * bs.PixelHeight / TheImage.ActualHeight);
                if (TheImage.Source is TransformedBitmap tb)
                {
                    Matrix inverse = tb.Transform.Value;
                    inverse.Invert();
                    inverse.OffsetX = 0.0;
                    inverse.OffsetY = 0.0;
                    p = inverse.Transform(p);
                    int w = tb.Source.PixelWidth;
                    int h = tb.Source.PixelHeight;
                    p = new Point((p.X + w) % w, (p.Y + h) % h);
                }
                TheLabel.Content = p.ToString();
            }
        }

Para la mayor parte, esto funciona bien, pero si pasa el ratón en el gris a la izquierda de la imagen rotada (aproximadamente donde la X es en la imagen de abajo), se obtiene una coordenada y (0.5) que hace que se vea como en la imagen, cuando en realidad se fuera, y la coordenada debe ser superior a la altura de la imagen para reflejar esto.

enter image description here

Esto es importante porque estoy tratando de permitir que el usuario seleccione un retorno de la inversión, y necesito saber cuando la selección está más allá de la imagen límites, aunque todavía quiero que lo permita.

.net bitmapsource c# image
2021-11-23 17:48:44
1

Mejor respuesta

1

Usted puede realizar la transformación en un "punto de prueba" dentro de la imagen de ciertos límites (por ejemplo, el centro) y el modulo de operación en el transformado del punto de prueba. A continuación, utilice el desplazamiento entre el transformado del punto de prueba y el ajuste (por modulo) punto de prueba para ajustar el punto real.

var p = e.GetPosition(TheImage);

p = new Point(
    p.X * bs.PixelWidth / TheImage.ActualWidth,
    p.Y * bs.PixelHeight / TheImage.ActualHeight);

if (TheImage.Source is TransformedBitmap tb)
{
    var inverse = tb.Transform.Value;
    inverse.Invert();
    inverse.OffsetX = 0.0;
    inverse.OffsetY = 0.0;

    var w = tb.Source.PixelWidth;
    var h = tb.Source.PixelHeight;

    var v = new Vector(bs.PixelWidth / 2, bs.PixelHeight / 2); // test point
    var v1 = inverse.Transform(v); // transformed test point
    var v2 = new Vector((v1.X + w) % w, (v1.Y + h) % h); // adjusted

    p = inverse.Transform(p) - v1 + v2; // add adjusting offset
}

TheLabel.Content = $"x: {p.X:F2}, y: {p.Y:F2}";
2021-11-23 22:03:56

Un punto de prueba desde el centro de la imagen, muy buena idea. Gracias!
Craig W

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................