Comment puis-je convertir les coordonnées de la souris pour les coordonnées des pixels d'une TransformedBitmap incorporé dans un grand conteneur parent?

0

La question

Semblables à Comment puis-je convertir les coordonnées de la souris pour les coordonnées des pixels d'une TransformedBitmap? mais avec la ride que mon Image est en fait intégré dans un plus grand parent Gridqui a un arrière-plan, et je voudrais les coordonnées des pixels d'être aussi précis lorsque vous placez le curseur dans les régions au-delà des limites de l'image.

Voici mon code 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>

Et voici le code:

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

Pour la plupart, cela fonctionne bien, mais si vous passez dans le gris à gauche de l'image pivotée (à peu près où le X est dans la capture d'écran ci-dessous), vous obtenez une coordonnée de (0,5) qui la fait ressembler vous êtes dans l'image, alors qu'en réalité, vous êtes à l'extérieur, et la coordonnée doit être supérieure à la hauteur de l'image pour en tenir compte.

enter image description here

Ceci est important parce que je suis en train de permettre à l'utilisateur de sélectionner un ROI, et j'ai besoin de savoir quand la sélection est au-delà de l'image de limites, même si j'ai encore envie de le permettre.

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

La meilleure réponse

1

Vous pouvez effectuer la transformation sur un "point de test" à l'intérieur de l'image limites (par exemple, le centre) et le modulo sur le transformé du point d'essai. Utilisez ensuite le décalage entre la transformée de point de test et le résultat de l'ajustement (par modulo) point de test pour régler le point réel.

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 point de test à partir du centre de l'image, belle idée. Merci!
Craig W

Dans d'autres langues

Cette page est dans d'autres langues

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