Jak mohu převést z myší souřadnice na pixel souřadnice TransformedBitmap?

0

Otázka

Moje otázka je podobná , Jak se dostat správnou polohu pixelu od myší souřadnice?, navíc s upozorněním, že obraz je potenciálně TransformedBitmap, kde salta a rotace může být použita, a ještě vrátit pixel souřadnice původního obrazu.

Můj Window's design vypadá takto:

    <DockPanel>
        <Label DockPanel.Dock="Bottom" Name="TheLabel" />
        <Image DockPanel.Dock="Top" Name="TheImage" Stretch="Uniform" RenderOptions.BitmapScalingMode="NearestNeighbor" MouseMove="TheImage_MouseMove" />
    </DockPanel>

a codebehind vypadá takto:

        public MainWindow()
        {
            InitializeComponent();

            const int WIDTH = 4;
            const int HEIGHT = 3;
            byte[] pixels = new byte[WIDTH * HEIGHT * 3];
            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 = bs;
        }

        private void TheImage_MouseMove(object sender, MouseEventArgs e)
        {
            Point p = e.GetPosition(TheImage);
            if (TheImage.Source is TransformedBitmap tb)
                TheLabel.Content = tb.Transform.Inverse.Transform(new Point(p.X * tb.PixelWidth / TheImage.ActualWidth, p.Y * tb.PixelHeight / TheImage.ActualHeight)).ToString();
            else if (TheImage.Source is BitmapSource bs)
                TheLabel.Content = new Point(p.X * bs.PixelWidth / TheImage.ActualWidth, p.Y * bs.PixelHeight / TheImage.ActualHeight).ToString();
        }

Když vznášející se v pravém dolním rohu (což jsem v modré barvě pro snadné sledování) non-transformovaný snímek, správně vidět souřadnice (~4, ~3), což jsou rozměry obrazu.

enter image description here

Nicméně, jakmile budete aplikovat transformace, například změnu TheImage.Source = bs; k TheImage.Source = new TransformedBitmap(bs, new RotateTransform(90.0));, vznášející se nad modrou místo toho dává (~4, ~0).

enter image description here

Myslím, že jeden by mohl se podívat na aktuální matice hodnoty transformovat, a zjistěte, jak nastavit bod, ve všech jednotlivých případech, ale zdá se, že by měl existovat jednodušší řešení pomocí inverzní transformace.

.net bitmapsource c# image
2021-11-23 06:19:28
1

Nejlepší odpověď

1

Pokud je Obraz prvku činí TransformedBitmap, střed Transformace je účinně ignorovat a rastr je posunuta do vhodné koordinovat nabídku.

Protože tento posun je aplikován na transfomation Bodu, budete muset kompenzovat, např. takto:

var p = e.GetPosition(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)
    {
        var w = tb.Source.PixelWidth;
        var h = tb.Source.PixelHeight;

        p = tb.Transform.Inverse.Transform(p);

        p = new Point((p.X + w) % w, (p.Y + h) % h);
    }

    TheLabel.Content = $"x: {(int)p.X}, y: {(int)p.Y}";
}

Výše uvedený kód bude však nepracuje správně při Transformaci centra je nastavena na jinou hodnotu než (0,0).

Za účelem, aby to fungovalo pro Transformace s libovolných střed, musíte vymazat hodnoty posunu v transformaci matice:

var p = e.GetPosition(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)
    {
        var w = tb.Source.PixelWidth;
        var h = tb.Source.PixelHeight;
        var t = tb.Transform.Value;
        t.Invert();
        t.OffsetX = 0d;
        t.OffsetY = 0d;

        p = t.Transform(p);

        p = new Point((p.X + w) % w, (p.Y + h) % h);
    }

    TheLabel.Content = $"x: {(int)p.X}, y: {(int)p.Y}";
}
2021-11-23 10:54:45

Díky!!! Pokud jeden vloží Image v Grid který má na pozadí a přesune MouseMove událost na Grid, pixel souřadnice nejsou přesné, pokud je mimo hranice obrazu, protože to dává jen odpovědi od 0..šířka a 0..výška. Nějaký nápad jak to opravit?
Craig W

Existuje více způsobů. Nejvíce jednoduché, připojit obslužné rutiny události pro další vnořené nadřazený prvek, který má stejné rozměry jako Obraz. Jinak existují metody, jako TransformToDescendant nebo podobné.
Clemens

Nejste si jisti, chápu. Lze přeložit bod z nadřazené distribuční soustavy na obrázku žádný problém. Ale například, když uživatel se vznáší na rohu otočený snímek, to bych jako y-ová souřadnice záporná, aby odrážely, které jsou nad rámec obrazu v původní orientaci. Měl bych upravit mou otázku, nebo začít nový?
Craig W

Lepší napsat nový.
Clemens

V jiných jazycích

Tato stránka je v jiných jazycích

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