mikrocontroller.net

Forum: PC-Programmierung c# Probleme beim Rotieren eines Bildes bei DrawImage


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von hase (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich versuche in c# 2 Bilder zusammenzufügen (Wasserzeichen). 
Gleichzeitig habe ich aber das Problem dass ich manche Bilder drehen 
muss (andere nicht).

Zuerst lade ich mit die BitmapFrame´s und füge dann im DrawinContext die 
Beiden Frames ein.

Soll ein Bild gedreht werden, schreibe ich ein PushTransform davor, 
welches dann die 90° anwendet. Hier mal der Code für ein Bild:
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
  //wenn rotiert wird
  drawingContext.PushTransform(new RotateTransform(90, baseHeight / 2, baseWidth / 2));
  drawingContext.DrawImage(baseimage, new Rect(0, 0, baseWidth, baseHeight));
}

//wenn rotiert wird
int tmp = baseWidth;
baseWidth = baseHeight;
baseHeight = tmp;

RenderTargetBitmap bmp = new RenderTargetBitmap(baseWidth, baseHeight, dpi, dpi, PixelFormats.Pbgra32);

leider habe ich das Problem, dass mein Bild bei der Ausgabe nicht mittig 
sitzt. Ich habe Oben und Links einen schwarzen Rand.

=> Wenn ich das Bild nicht rotiere, passt es perfekt

welchen Denkfehler habe ich?
=> wenn ich das Bild auf exakt 1/4 der Breite verschiebe (negativ von 
links, positiv von oben) ansetze, passt das Bild... das ergibt aber für 
mich keinen Sinn <- woher kommt die Verschiebung?

> Im Anhang ein kleiner Export

VIelen Dank

von hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
kleiner Nachtrag:
drawingContext.PushTransform(new RotateTransform(90, baseHeight / 2, baseWidth / 2));

oder
drawingContext.PushTransform(new RotateTransform(90, baseWidth / 2, baseHeight / 2));

verschiebt lediglich das Bild nach oben oder unten, kommt aber nicht der 
gewollten Drehung näher.

von Dirk K. (merciless)


Bewertung
0 lesenswert
nicht lesenswert
Kannst du mal den ganzen Code-Ausschnitt posten,
so dass man sehen kann, was baseHeight und baseWidth
zugewiesen wird?

merciless

von Horst (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
hase schrieb:
> ich versuche in c# 2 Bilder zusammenzufügen

🤦🤦

Das ist etwa so dämlich wie:

"Ich versuche mit einem Klebestreifen 2 Bilder zusammenzufügen."

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
hase schrieb:

> leider habe ich das Problem, dass mein Bild bei der Ausgabe nicht mittig
> sitzt. Ich habe Oben und Links einen schwarzen Rand.
>
> => Wenn ich das Bild nicht rotiere, passt es perfekt
>
> welchen Denkfehler habe ich?

Du hast nicht darüber nachgedacht, wo wohl das Zentrum der Rotation 
liegen mag...

von c.m. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
was passiert denn wenn du beim rotieren nicht den mittelpunkt angibst 
(resp 0/0)?

von hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@c-hater

> Du hast nicht darüber nachgedacht, wo wohl das Zentrum der Rotation
> liegen mag...

doch sogar sehr lange... <- aber bestimmt nicht richtig :D

> new RotateTransform(90, baseHeight / 2, baseWidth / 2);

Leider bringt mich das nicht weiter. Ich dachte immer, die halbe Höhe 
und die halbe Breite meiner "Bildgröße" (oder auch die Größe einer 
Fläche) müsste der Mittelpunkt sein.

@Dirk
Es ist völlig egal, ob ich hierfür ein Bild oder ein Rechteck nehme...
drawingContext.DrawImage(baseimage, new Rect(0, 0, baseWidth, baseHeight));

und auch baseWidth und baseHeight ist per definition egal. Wenn ich hier 
festwerte (z.B. 1000 & 2000) angebe und später in das Bild schreibe mit.
RenderTargetBitmap bmp = new RenderTargetBitmap(baseWidth, baseHeight, dpi, dpi, PixelFormats.Pbgra32);

ist das ganze "verschoben".

@Horst
> Wertvolle Beiträge auf dem Niveau, kennt man sonst nur von Trump auf
> Twitter...
> Selbst wenn du C# offenkundig nicht magst, kennst du doch nicht die
> Gegebenheiten, warum ich das tue???

Cheers

von hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@c.m.
dann wird das Bild aus dem Rand gedreht (weil es an der oberen Linken 
ecke angefasst wurde) <- hier wird es in der Tat perfekt getroffen.

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
hase schrieb:

> doch sogar sehr lange... <- aber bestimmt nicht richtig :D

Das ist ja nun offensichtlich...

Ob die ein echter Programmierer bist, zeigt sich in genau solchen 
Situationen. Die erste Idee war offensichtlich falsch. Was mache ich 
nun?

Tipp: Doku lesen schadet definitiv nicht. Auch wenn sie im konkreten 
Fall nicht gerade sehr schick ist und im ersten Anlauf einigermaßen 
un/miß-verständlich. Sie liefert aber Stoff für weitere Hypothesen, die 
man dann mit der Praxis abgleichen kann...

Nach einem Nachmittag zielgerichtetem Probierens hat man das Problem so 
weit im Griff, dass man das KONZEPT der Transformationen verstanden 
hat und es dann auch bei komplexeren Sachen als bei deinem primitiven 
Problem korrekt verwenden kann...

Und dann erschließt sich auch der Sinn der Formulierungen in der Doku...

von sid (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Also ehrlich,

wenn man die Antwort nicht kennt, den Fragenden anzublöken er soll halt 
mehr lernen ist doch auch Käse!

Ich kenne die Antwort auch nicht,
weiss aber, daß viele rotate implementationen schlicht und ergreifend um 
origin rotieren.

Also wär mein nächster Ansatz den Origin zu verschieben
(TranslateTransform((float)width/2, (float)height/2))
danach rotieren (RotateTransform(90)) und dann wieder zurückzuschieben 
(TranslateTransform(-(float)width/2, -(float)height/2))
und ja ich habe absichtlich keine code tags gesetzt, weil das vollends 
aus den Fingern gesogener Versuchsaufbau wäre,

Ich glaube übrigens, dass Du eventuell keine "zwischengespeicherten 
Werte"
nutzen kannst beim zweiten Translate, da sich width und height 
vertauscht haben könnten (naja oder Du musst halt auch tauschen)

Aber wie gesagt, ich weiss es nicht wirklich, ich rate nur mit quasi ;)

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
sid schrieb:

> weiss aber, daß viele rotate implementationen schlicht und ergreifend um
> origin rotieren.

Das tun sogar ausnahmlos alle. Denn: eine Rotation muss nunmal um 
irgendeinen Punkt herum passieren, sonst kann es keine Rotation sein...

Das Problem ist der Bezug von "origin". Also: In welchem 
Koordinatensystem ist dieser Punkt anzugeben...

von Frank S. (schroederde)


Bewertung
0 lesenswert
nicht lesenswert
Wo ist der allwissende Marvin?

Quick and Dirty. Alles was Du brauchst:

      BitmapImage sourceImage;
            if (filename == null)
                return;

            sourceImage = new BitmapImage(new Uri(filename));

            var dpiXProperty = 
typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | 
BindingFlags.Static);
            var dpiYProperty = 
typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | 
BindingFlags.Static);

            var dpiX = (int)dpiXProperty.GetValue(null, null);
            var dpiY = (int)dpiYProperty.GetValue(null, null);




            double sourceImageDpiX = sourceImage.DpiX;
            double sourceImageDpiY = sourceImage.DpiY;

            double centerX = sourceImage.PixelWidth / 2.0 / 
sourceImageDpiX * dpiX;
            double centerY = sourceImage.PixelHeight / 2.0 / 
sourceImageDpiY * dpiY;

            RotateTransform rotateTransform = new RotateTransform();
            rotateTransform.CenterX = centerX;
            rotateTransform.CenterY = centerY;
            rotateTransform.Angle   = SliderRotation.Value;

            double targetWidthInScreenUnits  = sourceImage.Width / 
sourceImageDpiX * dpiX;
            double targetHeightInScreenUnits = sourceImage.Height / 
sourceImageDpiY * dpiY;

            TranslateTransform translateTransform = new 
TranslateTransform();
            translateTransform.X = -1 * (centerX - 
targetWidthInScreenUnits / 2);
            translateTransform.Y = -1 * (centerY - 
targetHeightInScreenUnits / 2);

            TransformGroup transformGroup = new TransformGroup();
            transformGroup.Children.Add(rotateTransform);
            transformGroup.Children.Add(translateTransform);

            Image image = new Image();
            image.Stretch = Stretch.None;
            image.Source = sourceImage;
            image.RenderTransform = transformGroup;

            Canvas canvas = new Canvas();
            canvas.Background = Brushes.Lavender;
            canvas.Children.Add(image);
            canvas.Arrange(new 
Rect(0,0,sourceImage.PixelWidth,sourceImage.PixelHeight));

            RenderTargetBitmap zielBitmap = new 
RenderTargetBitmap((int)sourceImage.Width,(int)sourceImage.Height,source 
Image.DpiX,sourceImage.DpiY,PixelFormats.Default);
            zielBitmap.Render(canvas);
            ImageZiel.Source = null;
            ImageZiel.Source = zielBitmap;

von hase (Gast)


Bewertung
0 lesenswert
nicht lesenswert
dankschön <3

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.