Laden...

Zoomen durch größere Bilder

Erstellt von NewNoise vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.972 Views
N
NewNoise Themenstarter:in
71 Beiträge seit 2008
vor 16 Jahren
Zoomen durch größere Bilder

Hallo,

ich bin neu hier. Also erstmal ein allgemeiner Gruß an alle hier schon anwesenden!

Ich schreibe derzeit ein Viewer-Programm, welches Landkarten darstellt.

Diese Karten soll man entsprechend zoomen können, was auch super funktioniert.
Zunächst habe ich die Karte immer neu gezeichnet (DrawLine), was aber bei einem Volumen von 400TSD Lines ewig dauert.
Dann habe ich die Karte in 10 Zoomstufen gezeichnet und als .png gespeichert.
Der aufruf der ersten zoomstufen (1-5) geht nun auch schnell und toll.

Problematisch wirds danach.

Die Ladezeit steigt exponentiell an, extrem! Dabei dauert das Laden der "größten" zoomstufe ca. 40 sek. obwohl das Bild "nur" 3mb groß ist (10TSDx6TSD px).

Habt ihr eine Idee, wie ich die Ladezeit verkürzen kann?

Die Bitmap-Variable leere ich immer mit Dispose().

Beste Grüße
noise

871 Beiträge seit 2005
vor 16 Jahren

Hallo,

liegen deine Daten im Pixel- oder Vektorformat vor? Zuerst sprichst Du von DrawLine was mich auf Vektoren schliessen lässt, anschliessend nennst Du die größe in Pixel.

Wenn Du mit Pixeldaten arbeitest:

1.) Einen Backbuffer verwenden und den sichtbaren Bereich skaliert auf deine anzeige klatschen
2.) GetPixel und SetPixel um Längen geschlagen. 800 mal schneller

Grüsse,
Egon

1.361 Beiträge seit 2007
vor 16 Jahren

Hi, dass das Laden so lange dauert, kann ich mir schon vorstellen.

Klar, dass PNG mag mit 3 MB relativ klein sein.
Aber PNG komprimiert es ja auch.

Wenn es in den Speicher geladen wird um angezeigt zu werden, muss es in ein passendes Format umgewandelt werden.
Und das verwendet bei 24Bit-Farbauflösung nunmal 1 Byte pro Farbe.

Bei 10.000 x 6.000 Pixeln sind das 3 x 10.000 x 6.000 Bytes (3 Farben - RGB)

Was umgerechnet

3 x 10.000 x 6.000 Bytes
= 180000000 B
= 175781 KB
= 171,6 MB
sind.

Und das ist dann schon etwas groß 😉

Sinnvollerweise könntest du diese Monsterbild auch kacheln und nur die Kacheln anzeigen, die auch auf den Bildschirm passen.
(Wer hat schon nen Bildschirm mit ner Auflösung von 10.000 x 6.000 ??? )

beste Grüße
zommi

K
13 Beiträge seit 2008
vor 16 Jahren
SetViewportExtEx

In der GDi32 ist SetViewportExtEx dafür vorgesehen. Das sollte auch für übergroße DCs, bzw. Bitmaps funktionieren. Ein Beispiel findest du hier:
http://www.activevb.de/tipps/vb6tipps/tipp0707.html
Muß allerdings übersetzt werden. Das sollte aber kein so großes Problem sein.

Klaus

N
NewNoise Themenstarter:in
71 Beiträge seit 2008
vor 16 Jahren

hallo,
danke zunächst für die antworten.

@ egrath: den einbau der klasse die schneller als get/set pixel is hab ich soweit, wobei ich noch nicht verstehe, was mir das nützt. und was ich unter einem backbuffer zu verstehen habe, mit dem ich sklaliert klatschen kann, weiß ich beim besten willen nicht, hast du da nen bsp evtl.?

@klaus l: ich hab mir das bsp. gerade mal angesehen und hier ist das problem, dass er halt die vorhanden grafik vergrößert. in der art und weise, kann ich das auch problemlos umsetzen, hilft mir aber in meinem falle nicht, weil ich die bilder größer zeichnen muss. ich zoome also nicht in dem ich ein bild-ausschnitt vergrößere sind ich vergrößere das bild.
da die straßen auf der karte halt nur mit 1px breite gezeichnet werden habe ich sonst irgendwann irgendwelche pixeligen strecken.

@ zommi: danke, jetzt weiß ich immerhin, warum es solange dauert 🙂

K
13 Beiträge seit 2008
vor 16 Jahren
Bitmap oder Vektorgrafik?

@klaus l: heißt das, dass die grafik (also zb. mit 2000x1500 px) auf zb. 4000x3000px "gestreckt wird" oder was passiert dabei? das problem ist nämlich, dass die grafik sehr "fein" ist und es mit strecken leider nich funktioniert, weil es dann verpixelt aussieht.

Beim Zoomen, wird natürlich gestreckt. Da führt kein Weg dran vorbei. Eine Bitmap wird dabei auf jeden Fall pixeliger, da die Bildpunkte größer werden. Ein besseres Ergebnis kannst du nur mittels Vektorgrafik erreichen, d.h. wenn der sichbare Ausschnitt in einem anderen Maßstab neu gezeichnet wird. Du mußt also erstmal erklären, in welchem Format deine Daten vorliegen.

Gruß,

Klaus

N
NewNoise Themenstarter:in
71 Beiträge seit 2008
vor 16 Jahren

ah jetzt hatte ich es in meinem post gerade verändert.

also meine daten liegen so vor, dass ich ca. 400TSD kanten habe, jeweils mit start und endpunkt. diese verbinde ich dann durch eine linie (drawline).
wenn ich das ganze nun auf einer bitmap von 1000px x 800px zeichne, entsteht halt in der mitte wo ganz viele straßen sind quasi ein schwarzer fleck.
wenn ich das ganze aber auf 10 000px x 8 000px zeichne, wird es halt wesentlich genauer.

d.h. ich möchte quasi von zoomstufe zu zoomstufe eine größere bitmap als grundlage haben.

da das zeichnen mit drawline von 400TSD strecken doch recht lang dauert, habe ich die zoomstufen als png dateien gespeichert, weil ich dachte, dass die ausgabe einer datei unproblematisch sei und schnell geht.
unproblematisch ist es, aber ab einer bildgröße von 5 000px x 4 000px dauert es einfach wahnsinnig lange.

ich suche nun nach einer möglichkeit entweder die bilder schneller aufzurufen oder eine art und weise zu finden, wie ich schneller zeichnen kann.

danke
noise

K
13 Beiträge seit 2008
vor 16 Jahren

d.h. ich möchte quasi von zoomstufe zu zoomstufe eine größere bitmap als grundlage haben.

Aua 😉

da das zeichnen mit drawline von 400TSD strecken doch recht lang dauert, habe ich die zoomstufen als png dateien gespeichert,

Du wirst doch wohl nicht alles zeichnen, wenn man nur einen Ausschnitt sieht, oder?

aber ab einer bildgröße von 5 000px x 4 000px dauert es einfach wahnsinnig lange.

Wundert mich nicht 😉

ich suche nun nach einer möglichkeit entweder die bilder schneller aufzurufen oder eine art und weise zu finden, wie ich schneller zeichnen kann.

Zeichne nur den sichtbaren Teil. Du hast doch Vektorgrafik, da kannst du dir doch den Bereich ausrechnen den du zeichnen mußt.

Klaus

1.361 Beiträge seit 2007
vor 16 Jahren

Aber im voll ausgezoomten Zustand sieht man ja de facto alle Straßen.
Da bringt das mit dem "nur Ausschnitt zeichnen" nix.
Nur sind die meisten eben im Subpixelbereich, sodass man nix sinnvolles mehr erkennen kann.

Man müsste evtl. für jede Zoomstufe ne eigene Vektorgraphik haben. (mit unterschiedlichem Detailreichtum)
Aber, so genau weiß ich dacht auch nich.

Standard wäre halt wirklich: Jede Zoomstufe hat eigene Bitmap.
(Ob das hier wirklich Sinn macht is fraglich, weil deine Graphik ja wirklich ne strichzeichnung ist und kein Foto oder so)
Aber Trick dabei wäre dann: man nehme sich nicht das fertige Bitmap-Dateiformat, sondern schreibe sich ein eigenes, was mit der Redundanz umgehen kann.

Ein Bild in der Zoomstufe k hat beispielsweise 100x100 Pixel auflösung
Ein Bild der Zoomstufe k+1 dann 200x200.
Beim zoomen um exakt eine Stufen werden also aus jedem Pixel 4.
Bloß dass man nicht alle 4 Pixel abspeichert, sondern immer bloß 3.
Ein Pixel aus dem 100x100 Bild ist ja quasi der Durchschnitt aus den 4 dazugehörigen Pixeln (Nennen wir diese mal a, b, c, d) eines Bilder der größeren Zoomstufe.

Denn aus a, b, c und (a+b+c+d)/4 kannst du ja die fehlende Größe d berechnen.
Also hat man noch nicht einmal Redundanz.
Und auch keinen qualitätsverlust (Im Prinzip, real gibt es doch einen, da ja der Mittelwert evtl. keine ganze Zahl ist, er aber wieder abgerundet wird.

Abschließend kann man dann auch das 200x200 Bild wieder gekachelt als 4 Stück à 100x100 abgespeichern. (Wem es schonmal aufgefallen ist, bei GoogleMaps werden auch immer exakt gleichgroße Quadrate besser aufgelöst. - Manche früher als andere, dann merkt man das)

Aber so etwas wäre denkbar.

beste Grüße
zommi

N
NewNoise Themenstarter:in
71 Beiträge seit 2008
vor 16 Jahren

Hallo,
also danke nochmal für die Antworten.
Ich bin gerade dabei und versuche, dass er ab der Zoomstufe, die mit laden des Bildes nicht mehr schnell genug ist jeweils den Ausschnitt zeichnet, der sichtbar ist.
Nun habe ich allerdings eine technische Frage.
Undzwar zeichne ich die Straßen indem ich Start- und Endpunkte der Straßen kenne.
Wenn nun allerdings Start- und/oder Endpunkt außerhalb des sichtbaren Bereiches liegt, die Straße allerdings durch den sichtbaren Bereich verläuft habe ich ein Problem, da ich nicht weiß wie ich den Fall abfragen kann.
Habt ihr da ne Idee?
Danke
noise

1.361 Beiträge seit 2007
vor 16 Jahren

Hi,

dafür musst du jede Straße (Strecke im geometrischen Sinne) auf einen Schnittpunkt mit den Begrenzungskanten deines Sichtbereichs überprüfen.

Also:
Schneidet sich die Straße mit der oberen Kante (mit den koordinaten (0,0) (0,width))
Schneidet sich die Straße mit der linken Kante (mit den koordinaten (0,0) (height, 0))
Schneidet sich die Straße mit der unteren Kante (mit den koordinaten (height, 0), (height, width))
...

Ahso, musst gucken, vielleicht hattest du ja dein Koordinatensystem umgedreht (is ja manchmal doof, dass von oben nach unten der Y-Wert größer wird und nicht umgekehrt)

Ach und wegen Schnittpunkt prüfen - bin mir grad nicht sicher, obs C#-eigene Methoden gibt, wenn nicht. Selbst ist der Programmierer.

Schönes Dokument zu geometrischen Algorithmen (und dazu auch Schnittpunkt zwischen Strecken - mit allen sonderfällen) is Praktische / Angewandte Informatik 2

//EDIT:
du kannst natürlich eine Abfrage dann sogar weglassen.
Du prüfst ja zuerst ob Start- oder Endpunkt im sichtbaren Rechteck liegen.
Wenn du jetzt auch noch die Schnittpunkte mit linker, obere und rechter Kante geprüft hast, kannste dir einen Vergleich mit der unteren Kante sparen.

Weil wenn eine Straße durch die untere Kante hinein in den sichtbaren Bereich des Bildes ragt,...
kann sie nur durch die rechte, linke oder obere Kante wieder rausgehen - durch die untere geht ja nich mehr, (is ja ne Strecke) - oder aber sie endet im sichtbaren Bereich. Aber all diese Fälle hast du schon überprüft

Wenn also deine Strecke Kante Nr. 4 schneiden könnte, hätte sie auf alle Fälle schon Kante 1, 2 oder 3 geschnitten oder aber, der Start / Endpunkt läge im inneren.

Spart immerhin 1/4 der Rechenzeit 😉

beste Grüße
zommi

N
NewNoise Themenstarter:in
71 Beiträge seit 2008
vor 16 Jahren

hallo.
so funktioniert nun alles schnell und sauber.
danke danke danke

C
401 Beiträge seit 2007
vor 16 Jahren

Hi,

eine andere Möglichkeit wäre evtl. auch die Grafik am Anfang, also die mit 10k * 6k px in einer geringeren Qualität darzustellen. So spart man auch eine Menge Zeit. Je nach Zoomstufe wird dann der sichtbare Bereich einfach neu geladen und immer in etwas besserer Qualität. Vielleicht bringt das ja nochmal einen kleinen Leistungsschub.

Gruß

Dario