Cum pot converti de la mouse-ul coordonatele pixel de coordonate de un TransformedBitmap?

0

Problema

Intrebarea mea este similar cu Modul de a obține poziția corectă a pixelilor de la mouse-ul coordonatele?, cu un plus de precizare că imaginea este un potențial TransformedBitmap, în cazul în care răstoarnă și rotații ar putea fi aplicate, și încă a reveni la coordonatele pixel din imaginea originală.

Mea Windowmodelului de proiectare se pare ca acest lucru:

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

și codebehind pare ca acest lucru:

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

Atunci când situându-se în partea de jos-dreapta sus (pe care am colorat-albastru pentru urmărirea ușoară) de non-transformat imagine, veți vedea corect coordonatele (~4, ~3), care sunt dimensiunile imaginii.

enter image description here

Cu toate acestea, odată ce ați aplica o transforma, de exemplu schimbarea TheImage.Source = bs; pentru a TheImage.Source = new TransformedBitmap(bs, new RotateTransform(90.0));, situându-se peste albastru în loc dă (~4, ~0).

enter image description here

Cred că unul ar putea uita-te la real matrice de valori a transforma, și de a determina cum să se adapteze la punct în toate diferite cazuri, dar se pare ca acolo ar trebui să fie o soluție mai ușoară, folosind inversul transforma.

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

Cel mai bun răspuns

1

Atunci când un element Imagine face o TransformedBitmap, punctul central al Transforma efectiv ignorate și bitmap este mutat într-un caz de coordonate gama.

Deoarece această schimbare nu este aplicat la transfomation de un Punct, trebuie să-l compenseze, de exemplu, ca aceasta:

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

Codul de mai sus va cu toate acestea să nu funcționeze corect atunci când a Transforma centrul este setat la altă valoare decât (0,0).

În scopul de a face să funcționeze pentru a Transforma arbitrar center point, trebuie să clar valori de compensare în a transforma matricea:

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

Multumesc!!! Dacă unul încorporează Image într-un Grid care are un fundal și mută MouseMove la eveniment Grid, pixel de coordonate nu mai sunt corecte, atunci când sunt în afara limitelor de imagine, deoarece oferă doar răspunsuri de la 0..lățime și 0..înălțime. Vreo idee cum se rezolva asta?
Craig W

Există mai multe moduri. Cel mai simplu, atașați event handler pentru un alt imbricate elementul părinte care are aceleași dimensiuni ca Imagine. În caz contrar, există metode ca TransformToDescendant sau similare.
Clemens

Nu sunt sigur că înțeleg. Pot traduce ideea de mamă grilă la imagine nici o problema. Dar, de exemplu, atunci când utilizatorul trece la dreapta rotit imaginea, aș dori y-coordonata să fie negativă, pentru a reflecta faptul că ei sunt mai presus de limitele de imagine în orientare original. Ar trebui să-mi editez întrebare sau de a începe unul nou?
Craig W

Mai bine scrie unul nou.
Clemens

În alte limbi

Această pagină este în alte limbi

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