Fare koordinatlarından dönüştürülen Bitmap'in piksel koordinatlarına nasıl dönüştürebilirim?

0

Soru

Sorum, fare koordinatlarından pikselin doğru konumunu nasıl alacağına benzer mi?, görüntünün potansiyel olarak bir TransformedBitmap çevirmelerin ve döndürmelerin uygulanabileceği ve yine de orijinal görüntünün piksel koordinatlarını döndürebileceği yerler.

Benim Window'nin tasarımı şuna benziyor:

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

ve kod arka tarafı şuna benziyor:

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

Dönüştürülmemiş görüntünün sağ alt köşesinde (kolay izleme için mavi renklendirdim) gezinirken, görüntü boyutları olan (~4, ~3) koordinatlarını doğru görürsünüz.

enter image description here

Ancak, bir dönüşümü uyguladıktan sonra, örneğin değiştirme TheImage.Source = bs; -e doğru TheImage.Source = new TransformedBitmap(bs, new RotateTransform(90.0));, mavinin üzerine gelmek yerine (~4, ~0) verir.

enter image description here

Dönüşümün gerçek matris değerlerine bakabileceğini ve tüm çeşitli durumlarda noktanın nasıl ayarlanacağını belirleyebileceğini düşünüyorum, ancak ters dönüşümü kullanarak daha kolay bir çözüm olması gerektiği anlaşılıyor.

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

En iyi cevabı

1

Bir görüntü öğesi dönüştürülen bir Bitmap'i işlediğinde, Dönüşümün merkez noktası etkin bir şekilde yoksayılır ve bitmap uygun bir koordinat aralığına kaydırılır.

Bu kayma bir Noktanın transfomasyonuna uygulanmadığından, bunu telafi etmeniz gerekir, örn. bunun gibi:

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

Dönüşüm merkezi dışında bir değere ayarlandığında yukarıdaki kod ancak düzgün çalışmaz (0,0).

Rasgele merkez noktasına sahip Dönüşümler için çalışmasını sağlamak için, dönüşüm matrisindeki ofset değerlerini temizlemeniz gerekir:

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

Teşekkürler! Eğer biri gömerse Image in a Grid bir arka plana sahip olan ve hareket eden MouseMove etkinliğe Grid piksel koordinatları, yalnızca 0'dan yanıtlar verdiği için görüntünün sınırları dışındayken artık doğru değildir..genişlik ve 0..yükseklik. Bunu düzeltmek için nasıl bir fikriniz var mı?
Craig W

Orada birden fazla yolu var. En basit olanı, olay işleyicisini Görüntü ile aynı boyutlara sahip başka bir iç içe geçmiş üst öğeye eklemektir. Aksi takdirde, TransformToDescendant veya benzeri yöntemler vardır.
Clemens

Emin olduğum izleyin. Noktayı ana ızgaradan görüntüye sorunsuzca çevirebilirim. Ancak, örneğin kullanıcı döndürülmüş görüntünün sağına geldiğinde, y koordinatının, orijinal yönlendirmedeki görüntünün sınırlarının üstünde olduklarını yansıtacak şekilde negatif olmasını isterim. Sorumu düzenlemeli miyim yoksa yeni bir soru başlatmalı mıyım?
Craig W

Yeni bir tane yazsan iyi olur.
Clemens

Diğer dillerde

Bu sayfa diğer dillerde

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