2D-Grafik Bild ohne AWT, Swing und JavaFX rotieren

RalleYTN

Bekanntes Mitglied
Hallo Leute!
Wie der Titel schon sagt möchte ich ein Bild rotieren. Das Problem ist jetzt jedoch, dass mir nicht die AWT, Swing und JavaFX Klassen zur Verfügung stehen und ich an Java 5 gefesselt bin.
Das heisst ich muss mir meine eigene Bild-Klasse schreiben und die ganzen Algorithmen die ich brauche ebenfalls selber schreiben.

Momentan speichere ich Bilder in einem Zweidimensionalen Integer Array. In diesem Raster werden die Farben im Format ARGB gehalten.

Bis jetzt habe ich den folgenden Algorithmus:
Java:
    public SimpleImage rotate(int width, int height, int rotationCenterX, int rotationCenterY, double degrees) {
       
       int imgWidth = this.data.length;
       int imgHeight = this.data[0].length;
       double radians = Math.toRadians(degrees);
       int[][] data = new int[width][height];
       
       for(int x = 0; x < imgWidth; x++) {
           
           for(int y = 0; y < imgHeight; y++) {
               
               int newX = (int)(Math.cos(radians) * (x - rotationCenterX) - Math.sin(radians) * (y - rotationCenterY) + rotationCenterX);
               int newY = (int)(Math.sin(radians) * (x - rotationCenterX) + Math.cos(radians) * (y - rotationCenterY) + rotationCenterY);
           
               try {
                   
                   data[newX][newY] = this.data[x][y];
                   
               } catch(ArrayIndexOutOfBoundsException exception) {}
           }
       }
       
       return new SimpleImage(data);
   }

Das Funktioniert auch schon ganz gut.... Allerdings nur wenn ich das Bild um 90, 180 oder 270 Grad drehen möchte. Wenn ich das Bild nun um 45° drehen möchte kommt folgendes dabei raus: {siehe Anhang}

Es befinden sich schwarze Punkte überall im Bild. Ich habe jetzt schon mindestens 'ne Stunde gesucht und konnte nicht herausfinden wie ich das Verhindern kann.

Hat jemand eine Idee wie ich den Algorithmus abändern/erweitern muss damit ich kein Problem mit diesen toten Punkten bekomme?
 

Anhänge

  • Ergebnis45.jpg
    Ergebnis45.jpg
    22,6 KB · Aufrufe: 77

Thallius

Top Contributor
das funktioniert halt nicht so einfach sondern ist wesentlich komplexer als du denkst. Wenn du nicht um gerade Winkel drehst, dann bekommst du ja bei Ganzen Pixel Koordinaten zu mehreren Quellpunkten den gleichen Zeilpunkt und wiederum bestimmt Zielpunkte werden gar nicht getroffen.

Um um jeden beliebigen Winkel drehen zu können musst du mit Subpixeln rechnen. Das bedeutet du Must Deine Ergebnis Koordinaten in float behandeln und dann mehrere zielpixel gleichzeitig setzen und nicht nur setzen sondern auch noch zumischen.

Um mal ein einfaches Beispiel mit total fiktiven werten zu geben

Nehmen wir an du hast den Quellpixel 100, 100 und berechnest nun die neue Position. Sagen wir das Ergebnis wäre 50.5, 50,5. dann Must du die Pixel 50,50 und 50,51 und 51,50 und 51,51 jeweils auf diese Farbe setzen.

Würde nun ein weiters quellpixel auf so ein bereits gesetztes Pixel treffen. Dann Must du es im Verhältnis zumischen. Sagen wir du hast ein Ergebnis Pvon 49.25, 49.25 dann würde dem Pixel 50,50 die neue Farbe mit 25% zugemischt.

Gruß

Claus
 

RalleYTN

Bekanntes Mitglied
Das Ergebnis ist zwar immernoch noch nicht perfekt, jedoch gibt es keine Lücken mehr :)
Java:
    public SimpleImage rotate(double degrees, int width, int height, int rotationCenterX, int rotationCenterY) {
     
       int imgWidth = this.data.length;
       int imgHeight = this.data[0].length;
       double radians = Math.toRadians(degrees);
       int[][] data = new int[width][height];
       Integer[][] buffer = new Integer[width][height];
     
       for(int x = 0; x < imgWidth; x++) {
         
           for(int y = 0; y < imgHeight; y++) {
             
               double newX = Math.cos(radians) * (x - rotationCenterX) - Math.sin(radians) * (y - rotationCenterY) + rotationCenterX;
               double newY = Math.sin(radians) * (x - rotationCenterX) + Math.cos(radians) * (y - rotationCenterY) + rotationCenterY;
               int pixel = this.data[x][y];
               float ratioX = (float)((int)newX - newX);
               float ratioY = (float)((int)newY - newY);
             
               try {
                 
                   buffer[(int)newX][(int)newY] = pixel;
                 
               } catch(ArrayIndexOutOfBoundsException exception) {}

               try {
                 
                   if(ratioX != 0.0F) {
                     
                       Integer bufferPixel = buffer[(int)newX + 1][(int)newY];
                       buffer[(int)newX + 1][(int)newY] = bufferPixel != null ? ColorUtils.mix(pixel, bufferPixel, ratioX) : pixel;
                   }
                 
               } catch(ArrayIndexOutOfBoundsException exception) {}
             
               try {
                 
                   if(ratioY != 0.0F) {
                     
                       Integer bufferPixel = buffer[(int)newX][(int)newY + 1];
                       buffer[(int)newX][(int)newY + 1] = bufferPixel != null ? ColorUtils.mix(pixel, bufferPixel, ratioY) : pixel;
                   }
                 
               } catch(ArrayIndexOutOfBoundsException exception) {}
             
               try {
                 
                   if(ratioX != 0.0F && ratioY != 0.0F) {
                     
                       float ratio = (ratioX + ratioY) / 2;
                       Integer bufferPixel = buffer[(int)newX + 1][(int)newY + 1];
                       buffer[(int)newX + 1][(int)newY + 1] = bufferPixel != null ? ColorUtils.mix(pixel, bufferPixel, ratio) : pixel;
                   }
                 
               } catch(ArrayIndexOutOfBoundsException exception) {}
           }
       }
     
       for(int x = 0; x < width; x++) {
         
           for(int y = 0; y < height; y++) {
             
               Integer bufferPixel = buffer[x][y];
               data[x][y] = bufferPixel != null ? bufferPixel : 0x00000000;
           }
       }
     
       return new SimpleImage(data);
   }

upload_2017-5-11_23-25-57.jpeg
latest
 

Thallius

Top Contributor
Mach das Bild mal grün und mische den rest dann darauf. Ich denke die scharzen ausfransungen sind immer noch Lücken. Aber sieht ja schon deutlich besser aus.

Um die Lücken gänzlich zu vermeiden solltest du anders herum gehen. Du solltest durch die Zielpixel mit ganzzahlen iterieren und zum Zielpixel dann den oder die Quellpixel errechnen. Dann hast du für jedes Zielpixel einen garantierten Farbwert.

Gruß

Claus
 

RalleYTN

Bekanntes Mitglied
Ich habe das Bild einmal über einen grünen Hintergrund gezeichnet. Es sind jetzt schon keine Lücken mehr drin. Die Qualität des Bildes steigt auch, wenn ich das Farbenmischen komplett weg lasse(ist dann aber auch noch nicht ganz perfekt). Das mit dem anders herum rechnen klingt aber nach einer guten idee. Ich werde es mal ausprobieren und später das Ergebnis posten. :)
 

Thallius

Top Contributor
Auf jeden Fall sieht man oben am Bild, das das Mischen irgendwie nicht stimmen kann. Denn sonnst müßtest du einen geraden Rand haben der durch ein Graustufen Antialising geglättert ist. Du hast am oberen Rand nur schwarze und weisse Pixel. Es müssten sich aber auch graue Pixel ergeben wie am unteren Rand

Gruß

Claus
 

RalleYTN

Bekanntes Mitglied
Ich bin anscheinend zu doof den Quellpixel zu berechnen.
Java:
int sourceX = (int)(rotationCenterX - ((y + rotationCenterY) / Math.sin(radians)) + ((x + rotationCenterX) / Math.cos(radians)));
int sourceY = (int)(rotationCenterY - ((y + rotationCenterY) / Math.cos(radians)) - ((x + rotationCenterX) / Math.sin(radians)));
Ich habe jetzt einfach mal die Rechnung umgedreht bekomme jedoch nicht den Quellpixel. :/
 

Thallius

Top Contributor
Leider bin ich auch nicht der große Mathematiker. Ich habe das irgendwann vor gut 30 Jahren mal in C auf dem Amiga gemacht als es noch gar keine Libs für sowas gab. Deswegen erinnere ich mich auch nur noch waage :)
 

RalleYTN

Bekanntes Mitglied
Ok habs doch noch hinbekommen. Jetzt komme ich mit weniger Code aus, bin schneller und habe eine bessere Qualität. Das Bild wird jetzt jedoch gegen den Uhrzeigersinn gedreht.

Java:
    public SimpleImage rotate(double degrees, int width, int height, int rotationCenterX, int rotationCenterY) {
       
       int imgWidth = this.data.length;
       int imgHeight = this.data[0].length;
       double radians = Math.toRadians(degrees);
       int[][] data = new int[width][height];
       
       for(int x = 0; x < width; x++) {
           
           for(int y = 0; y < height; y++) {
               
               int sourceX = (int)(rotationCenterX - ((rotationCenterY - y) * Math.cos(radians)) + ((rotationCenterX - x) * Math.sin(radians)));
               int sourceY = (int)(rotationCenterY - ((rotationCenterY - y) * Math.sin(radians)) - ((rotationCenterX - x) * Math.cos(radians)));

               if(sourceX >= 0 && sourceX < imgWidth && sourceY >= 0 && sourceY < imgHeight) {

                   data[x][y] = this.data[sourceX][sourceY];
               }
           }
       }
       
       return new SimpleImage(data);
    }



upload_2017-5-13_14-2-8.jpeg
 

Thallius

Top Contributor
Super das schaut doch ziemlich nett aus. Ich verstehe aber immer noch nicht warum es da so Pixel "Aussreisser" an den Übergängen von Schwarz zu weiß im Bild gibt. Der Rahmen ist ja jetzt auch perfekt. Allerdings machst du ja jetzt auch überhaupt keine Subpixel mehr. Das wird es wohl sein
 

RalleYTN

Bekanntes Mitglied
Es ist auf jeden Fall ein annehmbares Ergebnis. Um die Sache mit der Drehrichtung zu lösen habe ich ganz einfach die Variable 'degrees' um 180 erhöht und das Ergebnis negiert. Jetzt dreht sich das Bild wieder im Uhrzeigersinn. Es gibt anscheinend noch andere Rotationsalgorithmen mit Bilinearer Interpolation die Ergebnisse mit besserer Qualität liefern. Jedoch reicht mein Mathematik wissen dafür nicht aus.

Danke für deine Hilfe @Thallius
 

Thallius

Top Contributor
Ist im Prinzip das Gleiche wie vorher. Du hast ja in diesem Fall auch eine float quell Koordinate. Denentsprechend holst du dir die vier Farben aus den benachbarten Pixeln und mischt sie im richtigen Verhältnis zusammen bevor du sie ins ERgebnis pixel setzt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
berserkerdq2 Habe ein svg bild, kann ich das zu svg koordinaten umrechnen, damit ich den Umriss zeichnen kann? Wenn ja wie? Allgemeine Java-Themen 1
berserkerdq2 Wenn ich einfach eine GIF in den Scenebuilder als Bild reinpacke, wird das dann asl Gif angezeigt Allgemeine Java-Themen 1
OnDemand Prüfen ob Bild defekt ist Allgemeine Java-Themen 4
Y Bild in JPanel setzen Allgemeine Java-Themen 2
Kirby.exe Bild im Zentrum spiegeln Allgemeine Java-Themen 14
I Apache POI Bild in Word ersetzen Allgemeine Java-Themen 15
OnDemand Bild prüfen ob defekt Allgemeine Java-Themen 3
L Input/Output Kassenzettel lesen aus einem Bild Allgemeine Java-Themen 2
K Bild in einem anderen Bild suchen Allgemeine Java-Themen 12
R Compiler-Fehler Bild per E-Mail versenden Allgemeine Java-Themen 3
M Java- Bild gewissen Anzahl von Sekunden anzeigen?! Allgemeine Java-Themen 4
RalleYTN 2D-Grafik Bild mit bilinearer Interpolation skalieren Allgemeine Java-Themen 31
S Telefonbuch mit Bild Allgemeine Java-Themen 4
A 2D-Grafik Text in ein Bild schreiben Allgemeine Java-Themen 11
Tacofan GIF-Bild wird "zerstört" Allgemeine Java-Themen 3
B Bild aus Jar kann nach Export nicht mehr gefunden werden Allgemeine Java-Themen 13
T Neuen Kanal in Bild (TIFF) einfügen à la Photoshop Allgemeine Java-Themen 2
Z Zahlen aus Bild auslesen Allgemeine Java-Themen 1
X Bild -> lokale Variable -> DB -> lokale Variable Allgemeine Java-Themen 3
E 3D Objekte in 2D Bild finden Allgemeine Java-Themen 5
R HtmlUnit: Canvas als Bild speichern Allgemeine Java-Themen 0
E am häufigsten vorkommenden Farben aus einem Bild Allgemeine Java-Themen 5
S Bild in Raster Allgemeine Java-Themen 1
S Bild in Frame Allgemeine Java-Themen 0
F Punkte in einem Bild finden Allgemeine Java-Themen 10
A Bild aufteilen für getData Allgemeine Java-Themen 3
P Wie füge ich ein Bild in die GUI ein? Allgemeine Java-Themen 7
F ImageJ: Linien und Schnittpunkte in Bild Allgemeine Java-Themen 1
A mit getClassLoader Bild laden Allgemeine Java-Themen 8
E Bild abspeichern Allgemeine Java-Themen 5
D Face.com - Gesicht im Bild finden Allgemeine Java-Themen 3
N Input/Output Bild von WebSite laden? Allgemeine Java-Themen 3
A Input/Output Bild in Java einlesen und analysieren! Allgemeine Java-Themen 8
S programm um bild auszulesen Allgemeine Java-Themen 2
R Bild offenbar zu groß um geladen zu werden? Allgemeine Java-Themen 12
K Quadrat in einem Bild erkennen Allgemeine Java-Themen 33
B Bild verschieben Allgemeine Java-Themen 6
T Bild in jar Paket einbinden Allgemeine Java-Themen 9
D Bild Typ bestimmen Allgemeine Java-Themen 9
0 2D-Grafik Bild einfärben Allgemeine Java-Themen 8
A Bild zusammenbauen! Allgemeine Java-Themen 5
A Bild von Webcam aufzeichnen Allgemeine Java-Themen 14
V 2D-Grafik Bild transparent machen. Allgemeine Java-Themen 4
H Bild einscannen und speichern Allgemeine Java-Themen 29
E Bild mit Listener einfügen Allgemeine Java-Themen 3
B Bild in String einbauen? Allgemeine Java-Themen 3
C Bild auf HDD speichern Allgemeine Java-Themen 4
X Bild aus dem Netz von URL runterladen und in GUI einbinden. Allgemeine Java-Themen 3
F Bild (Point) mit scrollen lassen Allgemeine Java-Themen 5
R Texterkennung - Text aus einem/r Bild/Grafik auslesen Allgemeine Java-Themen 2
B Bild- und Texterkennung Allgemeine Java-Themen 4
S Tracing eines Bildes (a.ka. Bild vektorisieren)..? Allgemeine Java-Themen 2
destroflyer *.dds-Bild anzeigen Allgemeine Java-Themen 12
F Bild aus externer Quelle laden und Skalieren? Allgemeine Java-Themen 11
X Bild im Memory zwischen speichern Allgemeine Java-Themen 11
R JAI - RGB Bild in 3 Einzelbilder zerlegen Allgemeine Java-Themen 4
P Ascii Bild aus einem input file nur kommt nix im outputfile an?????? Allgemeine Java-Themen 5
A Möglichkeiten, ein Bild schnell auszuwerten Allgemeine Java-Themen 56
D Java Thread, Bild wird nur am Ende gezeichnet Allgemeine Java-Themen 5
K Zeichnen auf ein Bild und Scrollen Allgemeine Java-Themen 7
data89 Barcodes in Bild erkennen Allgemeine Java-Themen 17
S Bild anhand von Koordinaten einteilen Allgemeine Java-Themen 7
K Transparente Bilder in Bild positionieren und speichern. Allgemeine Java-Themen 5
W Bild Spiegeln, aber Originalbild ausblenden Allgemeine Java-Themen 2
B Bild wird nicht angezeigt. Allgemeine Java-Themen 10
Developer_X Avatar/Bild ins Profil einbinden Allgemeine Java-Themen 10
C Bild in .txt speichern und wieder als Bild speichern Allgemeine Java-Themen 2
D Bild in text tabelle umwandeln Allgemeine Java-Themen 2
G bild in package Allgemeine Java-Themen 6
MQue bild zoomen Allgemeine Java-Themen 2
R Farbe im Bild ersetzen Allgemeine Java-Themen 11
R PDF einlesen und als Bild abspeichern Allgemeine Java-Themen 8
P Bild aus dem Internet speichern Allgemeine Java-Themen 4
K Schreiben von Bildern: Bild bleibt leer Allgemeine Java-Themen 7
ARadauer Bild verkleinern. Allgemeine Java-Themen 9
F Bild (File) komplett serialisieren Allgemeine Java-Themen 9
H Wie erstelle ich ein Bild ( GeoTIFF ) ? Allgemeine Java-Themen 2
Ark Bild immer als ARGB laden Allgemeine Java-Themen 2
N Hochgeladenes Bild verkleinern und speichern Allgemeine Java-Themen 2
N Graphics2D als Bild abspeichern Allgemeine Java-Themen 6
M bild verkleinern Allgemeine Java-Themen 9
MQue svg- Bild Allgemeine Java-Themen 34
S JPEG Bild übertragen mit RMI ? Allgemeine Java-Themen 4
V Wie kann ich ein Bild in einem Zip Archiv abspeichern? Allgemeine Java-Themen 3
ToNyXXL Als Mauszeiger eigenes Bild verwenden! Allgemeine Java-Themen 3
M bild erkennung Allgemeine Java-Themen 2
S Bild durchs Label laufen Allgemeine Java-Themen 14
T Bild verliert Inhalt. Allgemeine Java-Themen 6
T Icon -> Bild einladen Allgemeine Java-Themen 18
G Bild neu zeichnen Allgemeine Java-Themen 13
S Bild Größe verändern Allgemeine Java-Themen 2
R Bild flackert nach Java-Install - nur bei Laufschriften. Allgemeine Java-Themen 2
H Bild base64encode als String Allgemeine Java-Themen 9
S Bild aus Zwischenablage in Applet einfügen Allgemeine Java-Themen 2
T Ich bin unfähig ein Bild relativ zu addressieren ... Allgemeine Java-Themen 12
D JPEGEncoder -> Schwarz Weiß Bild Allgemeine Java-Themen 2
M Eingelesene Bild wird automatisch skaliert Allgemeine Java-Themen 4
R Bild wird trotz allem einfach nicht angezeigt. - AHHHHH!!!!! Allgemeine Java-Themen 30
R Bild downloaden und darstellen lassen Allgemeine Java-Themen 5
R Bild downloaden und dann Applet ausfüllen Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben