# CoverFlow in Java2D erstellt



## windl (22. Aug 2012)

Hi NG,

ich habe einen CoverFlow in Java2D erstellt. 
Der SourceCode ist ausbaufähig bzw. kann man einiges daran noch optimieren. Wollte den ersten Wurf trotzdem nicht für mich behalten, da evtl jeman Lust hat daran weiter zu entwickeln bzw gute Einwände hat wie man "eleganter" an das gesteckte Ziel kommt. 

Gesteuert wird der CF mit den Cursortasten.

cu 
Uwe


----------



## Marco13 (22. Aug 2012)

Krasse Sache, das sieht richtig cool aus :applaus: :toll:

Nur... ich sitz' hier im Moment an einer eigentlich recht flotten Kiste, und es ist ... schrecklich ruckelnd-langsam  Eher eine Cover-Slideshow als ein Cover_Flow_... 

Der Code ist etwas zu komplex, als dass ich ihn jetzt in der Mittagspause mal schnell nachvollziehen könnte. Aber ein Detail hat mich jetzt schon interessiert, nämlich wie du die 3D-Verzerrung mit reinem Java2D gemacht hast. Deswegen hab' ich mal danach gesucht, und die Codestelle gefunden, die sowohl die Antwort auf diese Frage liefert (tricky  ) als auch einen Teil der Antwort auf die Frage, warum es so langsam ist: getSubImage ist ziemlich teuer, und das Bild, das man damit bearbeitet, wird dann u.U. sehr viel langsamer gezeichnet (siehe ggf. auch http://www.java-forum.org/spiele-multimedia-programmierung/120318-performance-bufferedimages.html ). 

Deswegen... ändere vielleicht mal in der Picture3D#paintPicture-Methode in der Schleife das hier

```
//                BufferedImage sImage = matrix.bImage.getSubimage(i, 0, 1, matrix.bImage.getHeight());
//                gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1.0f));
//                gr.drawImage(sImage, (int)matrix.top[i].x, (int)matrix.top[i].y, 1,(int) (matrix.bottom[i].y - matrix.top[i].y), null);
//                gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.3f));
//                gr.drawImage(sImage,(int) matrix.bottom[i].x,(int)(5+ matrix.bottom[i].y +  (matrix.bottom[i].y-matrix.top[i].y)), 1, (int)(matrix.top[i].y-matrix.bottom[i].y) , null);


                gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,1.0f));
                int x = (int)matrix.top[i].x;
                int y = (int)matrix.top[i].y;
                int w = 1;
                int h = (int) (matrix.bottom[i].y - matrix.top[i].y);
                gr.drawImage(matrix.bImage, x, y, x+w, y+h, i, 0, i+1, matrix.bImage.getHeight(), null);

                gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.3f));
                x = (int) matrix.bottom[i].x;
                y = (int)(5+ matrix.bottom[i].y +  (matrix.bottom[i].y-matrix.top[i].y));
                w = 1;
                h = (int)(matrix.top[i].y-matrix.bottom[i].y);
                gr.drawImage(matrix.bImage, x, y, x+w, y+h, i, 0, i+1, matrix.bImage.getHeight(), null);
```

Die _eigentliche_ Bewegung ist damit schon eher "flüssig".

Es hakt manchmal immernoch ein bißchen - das könnte mit dem Animationsthread zu tun haben, müßte man genauer suchen. Und gelegentlich flackert es mit dem o.g. Verfahren etwas - das könnte mit der BufferStrategy und dem Fehlenden ImageObserver beim Zeichnen zu tun haben ... warum ist das so, und nicht mit normalem passive Rendering gemacht? "extends JPanel" statt "extends Canvas", und dann (ohne die while(true)-Schleife) in paintComponent den aktuellen Flow malen? Hab's kurz probiert, hat nicht sooo viel gebracht, war aber nur ein schneller gehackter Test, und ich frage mich, ob es für die andere Methode einen Grund gab....


----------



## windl (22. Aug 2012)

Hi Marco,

Danke für Deine Aussage. Habe Deinen Code gleich eingebaut. 
Eine wirkliche Verbesserung habe ich nicht feststellen können, da mein Code auf meinem Rechner auch schon sehr zügig lief. Daher bin ich für die Rückmeldung sehr dankbar.


----------



## Marco13 (22. Aug 2012)

windl hat gesagt.:


> da mein Code auf meinem Rechner auch schon sehr zügig lief



Kann da jemand anderes (durch einen Vergleich der beiden Varianten) noch was dazu sagen? 

Was für einen Rechner/GraKa hast du denn?


----------



## windl (22. Aug 2012)

Es handelt sich hierbei um ein Fujitsu Notebook mit einer Onboard Grafikkarte(Intel(R)HD Graphics)
OS = Windows7 64 Bit


----------



## Flown (22. Aug 2012)

Zur Performance kann ich jetzt sagen, dass beides etwas hakt, aber ich habe schon den ersten Bugreport. Bei mir fliegt das Bild ewig weiter wenn man schnell eine der Pfeiltaste drückt.


----------



## windl (22. Aug 2012)

OK - da muss ich mal schauen woran das liegt. Habe bis jetzt wohl eher vorsichtiger gedrückt 
Aber passt die Performance oder ist es auch eher eine SlomotionAnwendung????:L


----------



## Flown (22. Aug 2012)

Es ist in Ordnung, aber es wäre schon schöner, wenn es flüßiger von statten gehen würde. Interessant wäre auch noch, wie sich das Programm verhält, wenn man mehrere Bilder hat?!


----------



## windl (22. Aug 2012)

Ich habe mehrere Bilder eingebunden und es klappt super. Konnte nicht mehr Bilder mitgeben, da ich nur eine bestimmte Anzahl an KB ins Forum laden kann.
Muss mir das Verhalten heute Abend mal auf einem anderen Rechner anschauen. Wäre es nicht flüssig, hätte ich den Source niemals veröffentlicht


----------



## Marco13 (22. Aug 2012)

Hm seltsam. Hier auf einem 3GHz Core i7 mit Win7 und einer GeForce GTX 560 war es wirklich nicht mehr als "Bewegung" zu erkennen (sondern nur als sich ändernde Bilder). Mal schauen ob noch jemand was dazu sagt.


----------



## Apo (22. Aug 2012)

Ich habe es auch grad getestet und kann Marcos Verhalten nur bestätigen.

In der Originalversion habe ich gefühlte 3 Frame pro Sekunde.
Mit der Verbesserung von Marco läuft es flüssiger. Aber Ruckler sind immer noch drin.

Getestet wurde es auf einem Core 2 Duo E8500 @ 3,16 GHz mit Win Vista mit einer GeForce 8800 GTX.

Die Idee ist auf jeden Fall sehr schön und applelike.


----------



## windl (22. Aug 2012)

Habe es jetzt auf einem ca 4 Jahre alten Rechner getestet.
Windows 7 - 64 Bit und Java 1.7.

Ergebnis: Das Scrollen der Bilder ist mehr als akzeptabel. Starkes Flackern und nun bewegen sich einige Bilder bei zu schnell aufeinander folgenden Tastenbewegungen einfach weiter.

Muss mal schauen wie ich das in den Griff bekomme.


----------



## Marco13 (22. Aug 2012)

Und noch ein Test auf einem 2.4er QuadCore mit GeForce 8800: Das gleiche. Mit der ursprünglichen Version werden pro Übergang vielleicht 1 oder 2 Zustände angezeigt. Mit der geänderten Version ist die Bewegung flüssig, aber manchmal flackert und hakt es ein bißchen (was nicht impliziert, dass das Flackern daher kommt - bei 1-2 FPS sieht man ein "flackern" ja nicht).

Was für eine GraKa hat denn dein letzter Rechner? Bisher schien es ja nur auf NVIDIA-Karten langsam zu sein ... ???:L (ist aber sehr ins Blaue, ich versuch' nur die möglichen Gründe einzugrenzen...)


----------



## windl (22. Aug 2012)

Hi Marco,

ich habe gleich Deinen Source eingebaut da dieser wesentlich besser arbeitet als meine Version .
Das Haken habe ich auch - und verstehe nicht genau warum? An den Berechnungen kann es eigentlich kaum liegen - diese habe ich auf ein Minimum reduziert.
Zudem habe ich extra ein "Active-Paint" eingebaut (Bufferstrategy) um dem Betriebssystem das Zeichnen abzunehmen um sicher zu stellen, dass auch wirklich jeder Zustand gemalt wird.
Ich kann augenblicklich nicht nachvollziehen woher dieses wilde Flackern kommt!?
Hast Du noch eine Idee?


----------



## Marco13 (22. Aug 2012)

Was heißt "besser"? Es sollte schneller sein, aber wie viel das (warum) bringt oder nicht, ist ja noch nicht ganz klar...

Ja, das Haken und Flackern... Ich habe selbst noch nicht viel mit Active Rendering gemacht, und weiß nicht genau, wo dort überall Haken (  ) im Sinne von Stolperfallen sein können. Auf jeden fall birgt es ein nicht zu verachtendes Problempotential, wenn man zeichnet und gleichzeitig die zu zeichnenden Daten in einem anderen Thread verändert (und ich denke, dass dass zumindest _leichter_ in den Griff zu bekommen sein könnte, wenn man passive Rendering verwendet - aber das ist nur ein Bauchgefühl...). 
Insgesamt ist das ja schon so komplex, dass man es nicht durch Draufschauen sofort komplett nachvollziehen kann ... Ggf. würde ich mir die neue Version dann aber nochmal ansehen und vielleicht ein bißchen rumprobieren, vielleicht ergibt sich ja noch was...


----------



## windl (22. Aug 2012)

So,
nun habe ich einiges geändert.
Bei mir läuft auf 3 Rechnern der Coverflow recht ordentlich.
Das Haken und Flackern ist weg - sowie das unkontrollierte durchwandern von den Bildern.

Danke für das Testen und die guten Ratschläge!!


----------



## Flown (23. Aug 2012)

Ist jetzt ne runde Sache, super geworden. Sieht toll aus.

Ein kleines Manko hat es noch. Wenn man die Spiegelungen ansieht, dann siehst du, dass die Bilder im Hintergrund (also wenn es von einem Cover überdeckt wird) "durchscheinen". Aber das ist ja eine i-tüpfelchen-reiterei von mir.


----------



## windl (23. Aug 2012)

Hi Flown,

vielen Dank für Dein Lob! 
Auf die Spiegelung habe ich mich im Augenblick noch überhaupt nicht fokussiert. 

Hast Du eine Idee wie man das Umsetzen könnte?


----------



## Flown (23. Aug 2012)

Ich bin in Java2D/3D leider nicht so gut bewandert. Aber ich nehme einmal an, dass man dass mit der richtigen blend-Function oder Alpha-Function macht?!

[EDIT]Vielleicht bin ich auch von meiner Arbeit geschädigt, aber man sollte nur Software ausliefern die keine Warnings enthalten. Also die ungenützten imports noch rauslöschen.[/EDIT]


----------



## Marco13 (23. Aug 2012)

Flown hat gesagt.:


> [EDIT]Vielleicht bin ich auch von meiner Arbeit geschädigt, aber man sollte nur Software ausliefern die keine Warnings enthalten. Also die ungenützten imports noch rauslöschen.[/EDIT]



Das hängt nur von der Frage ab, welche Warnings man in Eclipse eingeschaltet hat und welche nicht


----------



## Marco13 (23. Aug 2012)

Hab's nochmal ganz kurz angestartet... die Änderung von
try{Thread.sleep(25);}catch(Exception error){}
zu
Thread.yield();
bewirkt zwar, dass es "schneller" ist, aber eine flüssige Bewegung mit einer bestimmten Geschwindigkeit geht damit nicht mehr. Mal sehen, ob ich bei Gelegenheit nochmal genauer schauen kann.


----------



## windl (23. Aug 2012)

Hi Marco,

aber funktioniert es denn nun? Ist es flüssig in einer akzeptablen Geschwindigkeit?
Hast Du auch eine Idee wie ich die Spiegelung besser realisieren könnte? Flow hat da schon recht - sieht noch recht "billig" aus


----------



## Marco13 (23. Aug 2012)

"Funktioniert" hat es ja vorher auch. Wenn dort nur "yield" verwendet wird (wovon ich zumindest mal gelesen habe, dass es unter Windows eine "no-op" ist) ist der übergang komplett flüssig - aber eben auch sehr schnell (vielleicht 0.1 Sekunden). Sobald es das "sleep" wird, ruckelt es. DAS ist dann aber zumindest ein Zeichen dafür, dass das Ruckeln nicht am Zeichnen oder der Performance allgemein liegt, sondern dass dort irgendwas mit dem Threading oder der synchronisation nicht stimmt...


----------



## windl (23. Aug 2012)

Hi Marco,

ich befürchte fast, dass wir an dem Ruckeln nichts mehr ändern können. Dass das Cover in den Vordergrund tritt ist in 5 Einzelschritte unterteilt indem das Cover immer eine andere Position einnimmt. Dann schicken wir den Thread für eine bestimmte Zeit zum "Schlafen" - damit erzeugen wir einen künstlichen optischen Bruch und damit bekommen wir ein ruckeln.

Vielleicht könnte man es in den Griff bekommen - wenn man die Anzahl der Zeichenoperation hochsetzt - sprich - von 5 auf z.B. 20 Einzelschritte unterteilt. Muss ich mal ausprobieren.

Hast Du denn eine Idee wie ich die Spiegelung optisch "aufmotzen" könnte?


----------



## Marco13 (23. Aug 2012)

Für die Spiegelung... bei einem schnellen Test schien's 
                gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN,0.2f));
schon zu tun, wenn nicht... muss ein nicht-schneller Test her


----------

