Hi,
ich habe eben schnell einen kleinen ImageViewer gebastellt. Leider läd mein Programm die Bilder mit glBitmap ungeheuer langsam. Die Bilder sind ".jpg"s und auch nicht klein (2500*3500 Pixel) aber auch bei Bitmaps funktioniert nichts mehr er braucht 15 Sekunden um nur 6 dieser Bilder zu laden. Es sollen aber etwa 30-50 werden. Was kann ich machen damit es schneller geht?
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Das Problem liegt an JPEGs. Die sind sehr umständlich kodiert. Und das Dekodieren dauert seine Zeit. Daran kann man nichts ändern. Wenn du die Bilder als Bitmaps hast, dann tauscht du die Zeit zum dekodieren gegen Zeit zum Lesen auf der Platte ein. Weniger dekodierarbeit dafür deutlich mehr Daten zum Einlesen. Du hast also die freie Auswahl.
Ein bisschen was kann man allerdings trotzdem tun. Die glBitmap kann seit 2.0 Bilder auch mi der libJPEG laden. Die Implementation davon ist besser als die von Delphi. Entsprechend kann man alleine dadurch schon ein paar Prozent einsparen.
30-50? Kann es sein, dass du Thumbnails darstellen möchtest? Wenn ja, dann kannst du Zeit sparen in dem du die jpegs kleiner lädst als sie sind. Es gibt beim Laden der Bilder eine Option die man setzen kann. Das ist allerdings mit der glBitmap nicht direkt vorgesehen. Deswegen hole ich da jetzt nicht weiter aus sondern erst dann wenn es wirklich an dem liegt.
Außerdem kannst du durch Pralelisierung auch einiges Sparen. Sofern die PCs es natürlich hergeben. Allerdings kommt man dann sehr schnell in Gefilde wo man aufwendige Verwaltungen benötigt.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Noch eine Zwischenfrage. Was willst du denn benutzen? Die jpegs von Delphi oder die libjpeg? Denn die Wege sind sehr unterschiedlich. Mag ungern doppelt schreiben, wenn nur eines genutzt wird.
Die Bilder haben etwa die größe von Thumbnails wie schaffe ich es denn sie kleiner zu Laden als sie sind?
Wenn das JPG progressiv gespeichert ist musst du, vernünftige Library vorausgesetzt, nur den Anfang der Datei von der Festplatte einlesen. Jedes gute Grafikprogramm sollte in der Lage sein JPGs progressiv zu speichern. Bezüglich der Dateigröße/Qualität gibt es dabei übrigens keinen Nachteil.
@Lossy Ex: Wenn du die Defines meinst würde ich die von Delphi benutzen (lasse mich aber auch gern umstimmen, vorallem wenn das andere schneller ist).
@Coolcat: Was ist progressiv (ich beschäftige mich nicht so mit JPGs weil ich meist BMPs benutze), es sind halt Fotos (keine Ahnung wie die Komrimiert sind wo kann man das denn sehen?)
@Coolcat: Was ist progressiv (ich beschäftige mich nicht so mit JPGs weil ich meist BMPs benutze), es sind halt Fotos (keine Ahnung wie die Komrimiert sind wo kann man das denn sehen?)
Schon mal größere Bilder bei langsamer Internetverbindung im Browser angeschaut? Es gibt zwei Arten:
1. Das Bild baut sich von oben nach unten auf. (normal)
2. Das Bild ist progressiv gespeichert und man sieht zuerst eine total pixelige Version die dann immer besser wird.
Wenn du z.B. 1/64 (= 1,56%) des Bildes geladen hast siehst du bei Variante 1 noch nicht sonderlich viel. Bei Variante 2 siehst du aber bereits das Bild mit einem Achtel der Auflösung, in deinem Beispiel 321x437, was für Thumbnails ausreicht.
Mir wurde das Verfahren mal so erklärt, wobei es da allerdings nicht explizit um JPG ging. Für die Idee sollte es aber schon mal reichen:
Man beginnt mit einem 1x1 Pixel Bild und speichert dann immer die Differenz zum nächstgrößeren Bild. Also:
Bild: 1x1
4 Differenzen für 2x2 Bild
4 * 4 = 16 Differenzen für 4x4 Bild
16 * 4 = 64 Differenzen für 16x16 Bild
usw...
Die Differenzen sind normalerweise relativ kleine Zahlen (=> z.B. Farbwert +1 oder -1 => viele Wiederholungen) und lassen sich daher extrem gut komprimieren.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Coolcat: Also das was ich meinte ist eine Spezialfeatures bei JPEGs. Das liegt wohl daran wie JPEGs kodiert werden. Ob progressive das jetzt noch positiv beeinflussen können weiß ich nicht.
Mori: Ich hatte vor eben die glBitmap zu erweitern, weil ich nicht genau weiß wie ich das erklären soll was man wie wo machen muss. Dann ist mir aber aufgefallen, dass das gar nicht sinnvoll geht. Denn JPEGs werden normal wie folgt geladen.
- Einlesen des Headers (recht fix)
- Einstellen der Ausgabe (inklusive skalierung nur Variablen setzen)
- Dekodieren des Bildes (beansprucht am meisten Zeit)
Das Problem ist nun, dass bei mir alle 3 Schritte in eine Methode fallen. Damit wäre es nur möglich, dass du eine Skalierung vor dem Laden setzt. Aber von den Bildern immer 1/16tel der Größe zu benutzen ist nicht sinnvoll. Wenn zum Beispiel mal ein kleines Bild kommt, dann wird dein Thumbnail zu klein. Entsprechend wird es wohl darauf hinaus laufen, dass du die Ladenroutine selber schreiben müsstest.
Bei den Delphi JPEGs ist das relativ einfach. Denn die sind Bereits eine Klasse.
- Du musst eine Instanz der Klasse TJPEGImage erstellen.
- LoadFromFile aufrufen.
- Anhand der Height/Width musst du berechnen wie stark du das Bild verkleinerst. Es sind nur folgende Skalierungen (Eigenschaft Scale) möglich (Voll, Halb, Viertel, Achtel)
- Anschließend muss das JPEG einem Bitmap zugewiesen werden, da es damit dekodiert wird.
- Das Bitmap muss anschließend von der glBitmap eingelesen werden.
Die Funktion LoadJPEG macht das alles. Hier mal ein Auszug.
Code:
var
bmp: TBitmap;
jpg: TJPEGImage;
begin
bmp := TBitmap.Create;
try
jpg := TJPEGImage.Create;
try
jpg.LoadFromStream(Stream);
jpg.Scale:= jsHalf;// Hier wird die Skalierung gesetzt.
jpg.Performance:= jpBestSpeed;// Das hier holt noch etwas geschwindigkeit raus
bmp.Assign(jpg);
AssignFromBitmap(bmp);
finally
jpg.Free;
end;
finally
bmp.Free;
end;
end;
Genau das Gleiche könntest du auch machen. Mit Scale kannst du das Bild verkleinern und Performance dient dazu da noch ein paar Milisekunden mehr bei raus zu holen. Der Weg über ein Bitmap muss leider so sein. Da ist das jpeg von der Struktur her etwas beknackt.
Wenn man die libJPEG benutzen würde könnte man auf so etwas verzichten. Und das JPEG direkt in den Speicher der glBitmap dekodieren. Allerdings wenn du wissen willst was du dafür machen musst, dann kannst du ja mal in der glBitmap zwischen der Zeile 3450 und 3730 schauen. Dort sind die Strukturen und die Methoden die zum Laden notwendig sind. Und das möchte ich dir ungern direkt auf Auge drücken. Das ist schon harte Kost.
Danke schonmal für die Antworten. Mich würde mal der Aufbau einer JPG interessieren. Die Unit JPEG habe ich in Delphi 5 (professional) nur als cdu, weshalb ich mir nicht die Lade-Rutine ansehen kann.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Die Unit jpeg gibts auch nur als dcu. Warum auch immer. Denn die basiert eigentlich auf einer Pascalübersetzung von den Quellen der libjpeg. Also irgendwie so was.
Allerdings die Laderoutine stammt nicht aus der unit jpeg sondern aus meiner glBitmap.
Was den Aufbau angeht. Da kann ich dir eigentlich nur den Wikipediaartikel JPEG ans Herz legen. Jpegs sind weit Komplexer als DDS (selbst komprimierte), TGAs oder BMPs. Ich weiß das auch nur so Schemenhaft. Deswegen benutze ich ja auch nur externe Quellen dafür.
Mitglieder in diesem Forum: 0 Mitglieder und 7 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.