Sehr große bitmap darstellen



  • Hallo,

    ich möchte eine Karte in einem Fenster darstellen, welche sich verschieben und zoomen lässt. Die Karte hat eine sehr hohe Auflösung, sagen wir mal 50.000x50.000px.
    Für kleinere Bilddateien würde ich die Datei in den Speicher laden und eine HBITMAP erzeugen, welche ich in das Fenster zeichne.
    Habt ihr Ideen, wie ich das Problem lösen kann?

    Schöne Grüße



  • Mal ganz klassisch Tiling und Mipmapping.

    Tiling: du teilst das Ding in Kacheln auf, wobei jede Kachel z.B. 512x512 oder 1024x1024 Pixel hat. Dadurch kannst du in der 100% Zoomstufe schonmal gut arbeiten. Du musst ja dann immer nur die Kacheln geladen haben die du brauchst um den Anzeigebereich zu füllen.

    Mipmapping: damit auch kleinere Zoomstufen gut funktionieren berechnest du verkleinerte Varianten der Map, und speicherst diese zusätzlich ab.
    D.h. du speicherst eine Kopie mit 1/2 Breite und 1/2 Höhe, eine mit 1/4 Breite und 1/4 Höhe, eine mit je 1/8 usw.
    Jede kleinere Map ist dabei dann 1/4 (1/2 * 1/2) so gross wie die grössere Stufe.

    Alle Levels zusammen brauchen dabei 1/3 des Platzes von Level 0 (also der Original-Map) - sollte also zu verkraften sein.

    Und jedes Mip-Map Level teilst du natürlich wieder in Kacheln auf.

    Wenn du nur Zoomstufen 100%, 50%, 25%, 12.5% etc. erlaubst bist du fertig. Lässt sich ganz einfach mit GDI machen, jede Kachel wird "in" ihre eigene HBITMAP geladen wie du es gewohnt bist. Fehlt nur noch der Code der ermittelt was geladen werden muss, es dynamisch nachlädt, nicht mehr verwendete Dinge freigibt etc. Vielleicht noch mit nem schlauen "vorlade" Code, der Bereiche wo der User bald hinscrollen könnte bereits im Hintergrund vorlädt. Evtl. sogar die nächst kleinere und grössere Zoomstufe schon immer vorlädt, damit auch das Zoomen verzögerungsfrei geht.

    Wenn du "freie" Zoomstufen erlauben willst, und willst dass beim Wechseln von z.B. 51% auf 49% kein sprunghafter Wechsel in der Darstellungsqualität zu sehen ist, dann musst du die einzelnen Mip Levels noch interpolieren, z.B. einfach trilinear. Das würde ich dann nicht mehr mit GDI machen wollen, dafür würde ich dann Direct3D verwenden.

    ps:
    Wenn das ganze auch mit Festplatten noch gut laufen soll, dann vermutlich doch lieber ne grössere Kachelgrösse, z.B. 2048x2048. Bei 24 Bit/Pixel wären das dann 12 MB pro Kachel. Bei kleineren Kacheln würde dich das Laden von vielen relativ kleinen Files sonst unnötig ausbremsen.
    Bei SSDs sollte es egal sein, so lange du nicht extrem klein wirst. Also weniger als 512x512 würde ich trotzdem nicht machen. Wobei sich die ideale Grösse natürlich einfach experimentell ermitteln lässt.



  • Hey, danke für deine sehr gute Idee!

    Welches Dateiformat würdest du für die Bilder nehmen?
    Sollte ja möglichst gut komprimieren und sich trotzdem schnell dekomprimieren lassen (jaja, ich meine ja nur im Idealfall ;))



  • Bitmap schrieb:

    Welches Dateiformat würdest du für die Bilder nehmen?
    Sollte ja möglichst gut komprimieren und sich trotzdem schnell dekomprimieren lassen (jaja, ich meine ja nur im Idealfall ;))

    Uff.
    Verlustfrei oder darf's auch verlustbehaftet sein?
    Verlustbehaftet würd ich mal JPEG sagen.

    Verlustfrei kannst du PNG probieren. Wobei ich nicht sicher bin wie aufwendig das Dekomprimieren von PNG Files ist. Könnte sein dass das zu sehr bremst.

    => Ausprobieren.



  • Bitmap schrieb:

    Welches Dateiformat würdest du für die Bilder nehmen?

    hustbaers tiling und mipmapping ist da total tolerant. (hab ihn hoffentlich recht interpretiert, daß er für jede Kachel und Mipmap eine eigene Datei nimmst.)

    Egal. jpeg für Fotos, png für Karten mit vielen gleichen Pixels. Kannst sogar jede Datei in einem anderen Format speichern, welches gerade für diesen Kartenausschnitt am stärksten komprimiert.

    mipmapping, riesige Datei…
    hmm…
    wavelets!
    Wenn ich auf jenem Forentreffen Marc++us richtig verstanden habe (nicht wirklich) und mich recht erinnere (nicht wirklich) sollte ein wavelet-komprimiertes Bild keine Randartefakte zwischen den Kacheln haben und alle Zoom-Stufen bereits schnell zugreifbar beinhalten.



  • Bitmap schrieb:

    Welches Dateiformat würdest du für die Bilder nehmen?

    Wenn's was Eigenes sein kann, dann was Eigenes, sonst TIFF, das kann sowohl Kompression als auch Tiling...



  • hustbaer schrieb:

    Verlustfrei kannst du PNG probieren. Wobei ich nicht sicher bin wie aufwendig das Dekomprimieren von PNG Files ist. Könnte sein dass das zu sehr bremst.

    png ist eigentlich nur gzip nach einem trivialen vergleich des pixels mit dem pixel eins oberhalb(1). das sollte rasend schnell sein.

    (1) Ok, geschummelt. Aber das ändert die Laufzeit nicht:
    http://de.wikipedia.org/wiki/Portable_Network_Graphics#Vorfilter



  • dot schrieb:

    Bitmap schrieb:

    Welches Dateiformat würdest du für die Bilder nehmen?

    Wenn's was Eigenes sein kann, dann was Eigenes, sonst TIFF, das kann sowohl Kompression als auch Tiling...

    Die Frage ist, ob man Libs hat, um Ausschnitte schnell zu extrahieren. jpeg2000 sollte echt auch einen versuch wert sein.



  • Ja, ich würde für jede Kachel ne eigene Datei nehmen.

    EDIT: Was die Mip-Maps angeht: die würde ich jeweils als eigenes gekacheltes Bild abspeichern. Wobei jedes Mip Level dann weniger Kacheln hat als das nächst grössere Level. D.h. eine Kachel von Mip Level 1 entspricht 4 Kacheln von Mip-Level 0. Bei 1:1 Kachelung müsste man sonst nämlich für die ganz rausgezoomte Ansicht wieder unmengen an fuzzikleinen Files laden.

    volkard schrieb:

    Wenn ich auf jenem Forentreffen Marc++us richtig verstanden habe (nicht wirklich) und mich recht erinnere (nicht wirklich) sollte ein wavelet-komprimiertes Bild keine Randartefakte zwischen den Kacheln haben und alle Zoom-Stufen bereits schnell zugreifbar beinhalten.

    Ich schätze mit Wavelets sollte es möglich sein alles in einer einzigen Datei zu speichern, und effizient daraus zu laden - egal welche Zoomstufe. Wenn man das File-Format entsprechend optimiert.
    Ich vermute aber dass man da wenig fertigen Code verwenden wird können, und alles selbst implementieren muss. Wäre mir zu aufwendig.

    Wäre es mein Projekt, dann würde ich vermutlich die von mir beschriebene Variante umsetzen. Ganz einfach weil ich weiss dass es funktionieren wird, und dass ich es in relativ kurzer Zeit implementieren könnte.



  • volkard schrieb:

    dot schrieb:

    Bitmap schrieb:

    Welches Dateiformat würdest du für die Bilder nehmen?

    Wenn's was Eigenes sein kann, dann was Eigenes, sonst TIFF, das kann sowohl Kompression als auch Tiling...

    Die Frage ist, ob man Libs hat, um Ausschnitte schnell zu extrahieren. jpeg2000 sollte echt auch einen versuch wert sein.

    Stimmt, mit jpeg und jpeg2000 sollte das rein prinzipiell auch gehen...



  • dot schrieb:

    Stimmt, mit jpeg und jpeg2000 sollte das rein prinzipiell auch gehen...

    Ich meine explizit jpeg2000, weils wavelets drin hat. ich hab aber ein sehr ungutes gefühl, ob es genau passt, oder ob z.B. das layout im file cachunfreundlich ist oder so, was hustbaers lösung 1000-mal schneller machen würde (ebenso bei riesen-gif). und hustbaers ist so witzig schnell implementiert.



  • hustbaer schrieb:

    D.h. eine Kachel von Mip Level 1 entspricht 4 Kacheln von Mip-Level 0.

    Jo. Noch schnell image-magick installieren und ein kleines C++-Programm drum, das es paarhundertmal aufruft aus der Riesenkarte die die Kacheln jeder Zoom-Stufe (ich unterscheide jetzt mal nichtmehr zwischen Kacheln und Mipmaps) baut und fertig ist der Lack.
    Aus Jux noch alle Kacheln in ein paar übliche Formate konvertieren lassen und immer die kleinste nehmen, 5 Minuten mehraufwand, googlen, wie man in C++ die Dateigröße rausfindet.
    Aus Jux noch falls png oft auftaucht, OptiPNG, TinyPNG oder so benutzen, 2-3 Stunden mit erstem Rumexperimentieren. Hab damit oft noch bis zu 50% rausgeholt.



  • Hey, danke euch für die vielen und sehr guten/ausführlichen Antworten!

    Ich denke damit kann ich gut arbeiten, ihr habt mir sehr geholfen 👍

    Danke und schöne Grüße!


Anmelden zum Antworten