Jak przeliczyć współrzędne myszy na współrzędne pikseli konwersji bitmapy?

0

Pytanie

Moje pytanie jest podobne do tego, jak uzyskać prawidłowe położenie piksela współrzędne myszy?, z dodaną zastrzeżeniem, że obraz jest potencjalnie TransformedBitmap, gdzie można byłoby zastosować salta i obroty, a przy tym zwrócić współrzędne pikseli obrazu źródłowego.

Mój Windowprojekt wygląda tak:

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

i kodowa podpowiedź wygląda tak:

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

Po umieszczeniu kursora w prawym dolnym rogu (który pomalował na niebiesko dla ułatwienia śledzenia) нетрансформированного obrazu poprawnie widzisz współrzędne (~4, ~3), które są wymiarami obrazu.

enter image description here

Jednak, jak tylko zastosować transformację, na przykład, zmień TheImage.Source = bs; Dla TheImage.Source = new TransformedBitmap(bs, new RotateTransform(90.0));, zawiesza się na niebieskim zamiast tego daje (~4, ~0).

enter image description here

Myślę, że można byłoby spojrzeć na rzeczywiste wartości macierzy transformacji i określić, jak korygować punkt w różnych przypadkach, ale wydaje się, że powinno być bardziej proste rozwiązanie z wykorzystaniem odwrotnej konwersji.

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

Najlepsza odpowiedź

1

Gdy element obrazu wyświetla przeksztalcony bitmapę, centralny punkt konwersji faktycznie jest ignorowany i rastrowy obraz przesuwa się w odpowiedni zakres współrzędnych.

Ponieważ zmiana ta nie ma zastosowania do poruszania się punktu, należy zrekompensować, np. tak:

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

Jednak powyższy kod będzie działać prawidłowo, jeśli dla centrum konwersji jest ustawiona na wartość inną niż (0,0).

Aby zmusić go do pracy na przemian z dowolnym punktem centralnym, należy oczyścić przesunięcie wartości w macierzy konwersji:

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

Dziękuję! Jeśli ktoś osadza Image w Grid który ma tło i przenosi MouseMove wydarzenie dla Gridwspółrzędne pikseli nie są dokładne, gdy znajdują się one poza granicami obrazu, ponieważ dają one odpowiedzi tylko od 0..szerokość i 0..wysokość. Jakieś pomysły jak to naprawić?
Craig W

Istnieje kilka sposobów. Najprościej dołączyć moduł obsługi zdarzeń do innego zagnieżdżonego elementu nadrzędnego, który ma te same wymiary, co i Obraz. W przeciwnym razie istnieją takie metody, jak TransformToDescendant lub podobne.
Clemens

Nie jestem pewien, czy rozumiem. Mogę bez problemu przełożyć punkt z nadrzędnym siatki na obraz. Ale, na przykład, gdy użytkownik przesunie kursor na prawo od obróconego obrazu, chciałbym, aby współrzędna y była negatywna, aby odzwierciedlić, że znajdują się one powyżej granic obrazu w oryginalnej orientacji. Czy mogę edytować swoje pytanie lub rozpocząć nowy?
Craig W

Lepiej napisz coś nowego.
Clemens

W innych językach

Ta strona jest w innych językach

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