Suche Verfahren für (Echtzeit-)Resizing
-
Moin,
ich möchte die Bildgröße eines 2D-Spiels (im Fenstermodus) an die Fenstergröße anpassen.
Bisher verwende ich dafür das Halbtonverfahren. Wenn das Fenster kleiner als die Originalauflösung ist, dann liefert das auch sehr gute Ergebnisse.
Nur wenn man das Bild vergrößert, ist es extrem hässlich, gerade bei kontrastreichen Kanten (z.B. Schrift)... letztendlich ist es dann auch nicht schöner als das Blockverfahren (d.h. wenn man Pixelreihen und -spalten einfach dupliziert), ist dafür aber deutlich langsamer und führt schon zu Framerateeinbrüchen.Deshalb suche ich nach einem Verfahren, das angenehmer fürs Auge ist und trotzdem noch in Echtzeit funktioniert. Es gibt zwar einige gute Verfahren, z.B. der Lanczos-Filter, welche aber viel zu langsam sind. Notfalls kann das Verfahren ja nur für Nutzer mit halbwegs aktueller CPU angeboten werden, aber für den Lanczos-Filter benötigt man schon einen kleinen Supercomputer, wenn das ganze in Echtzeit funktionieren soll.
Wie machen das eigentlich TFT-Bildschirme? Die müssen das eingehende Bild je nach Auflösung auch vergrößern und bekommen das meist auch gut hin.
Hat da jemand einen Vorschlag?
-
Flachbildschirme machen das Ganze auch nicht software-mäßig, sondern hardwaremäßig
Sprich, das Bild wird über im Bildschirm eingebaute Schaltkreise auf die eigentlichen Pixel angepasst und dabei gefiltert. So wie auch in einem Grafikchip Schaltkreise zum Filtern von Texturen etc. eingebaut sind. Deshalb sind die auch so schnell.
Lanczos ist wirklich recht langsam. Eine Möglichkeit wäre noch die einfache lineare Interpolation, die schneller ist und kaum ein schlechteres Bild liefert, aber das kostet je nach Auflösung immer noch viel Rechenzeit.
Besser wäre doch, das Ganze von der Grafikkarte machen zu lassen.Wie bzw. womit (Engine, GDI/OpenGl/D3D/... ) lässt du denn jetzt rendern bzw. arbeitest du?
-
Lanczos funktioniert wunderbar in Echtzeit.
Ich guck Videos am Computer z.B. grundsätzlich nur über Lanczos aufskaliert...
Du brauchst bloss eine effiziente Implementierung.Was schneller ist, und auch halbwegs OK aussieht, ist bicubic interpolation.
http://en.wikipedia.org/wiki/Bicubic_interpolation
-
Powerpaule schrieb:
Flachbildschirme machen das Ganze auch nicht software-mäßig, sondern hardwaremäßig
Sprich, das Bild wird über im Bildschirm eingebaute Schaltkreise auf die eigentlichen Pixel angepasst und dabei gefiltert. So wie auch in einem Grafikchip Schaltkreise zum Filtern von Texturen etc. eingebaut sind. Deshalb sind die auch so schnell.
So etwas hatte ich schon befürchtet. Irgendein Algorithmus muss dort wohl auch zur Anwendung kommen, aber wenn das alles fest verdrahtet ist, können da vermutlich auch ohne weiteres etwas aufwänderige Verfahren angewendet werden.
Eine Möglichkeit wäre noch die einfache lineare Interpolation, die schneller ist und kaum ein schlechteres Bild liefert, aber das kostet je nach Auflösung immer noch viel Rechenzeit.
"Lineare Interpolation klingt sehr nachdem, was ich zur Zeit schon verwende (eingefügte Pixelreihen/-spalten bekommen als Farbe einen Mittelwert der umliegenden Pixel). Wenn der Skalierfaktor ganzzahlig ist (also z.B. 800x600 -> 1600x1200), funktioniert das zwar recht gut, andernfalls wird es aber sehr unschön.
Besser wäre doch, das Ganze von der Grafikkarte machen zu lassen.
Wie bzw. womit (Engine, GDI/OpenGl/D3D/... ) lässt du denn jetzt rendern bzw. arbeitest du?Denke ich auch, die Grafikkarten haben heutzutage ja im Vergleich zu den normalen CPUs eine unglaubliche Rechenleistung, wie ich jetzt erfahren habe. Ich wusste zwar schon, dass sie etwas mehr packen, aber mit solch einem Unterschied hatte ich nicht gerechnet.
Aber wie führe ich eigenen Code auf der Grafikkarte aus? CUDA scheint genau in die Richtung zu gehen, aber das wird nur von neuen Grafikkarten unterstützt.
Zur Zeit verwende ich nur die GDI (SetDIBitsToDevice) für die Grafikausgabe (hat den Vorteil, dass es ab Windows 95 und auch mit WINE immer tadellos läuft). Vermutlich wird man mit GDI nicht weit kommen, aber falls sowas mit OpenGL möglich ist, wäre das sehr erfreulich.hustbaer schrieb:
Lanczos funktioniert wunderbar in Echtzeit.
Ich guck Videos am Computer z.B. grundsätzlich nur über Lanczos aufskaliert...
Du brauchst bloss eine effiziente Implementierung.Hm, interessant... erledigt das die Grafikkarte oder wird das tatsächlich von der CPU gemacht?
hustbaer schrieb:
Was schneller ist, und auch halbwegs OK aussieht, ist bicubic interpolation.
http://en.wikipedia.org/wiki/Bicubic_interpolationBicubic interpolation liefert durchaus gute Ergebnisse, deswegen habe ich mich in den letzten Tagen etwas damit beschäftigt. Das Problem liegt bei besagter effizienten Implementierung... wo kann man eine solche finden? Man findet im Internet genug Implementierung, die sind aber nicht wirklich optimiert und schon gar nicht für Bitmaps.
Ich habe erst einmal FreeImages Implementierung übernommen... Das Aufskalieren von 800x600 nach 1024x768 dauert 500 ms, womit das viel zu langsam ist. Ich hab mich daraufhin selbst an einer Implementation versucht. Die benötigt nun rund 350-400 ms. Wenn ich ohne SSE-Unterstützung compiliere, dauert es >700ms. Auf einer halbwegs aktuellen Dual Core-CPU wird man damit vermutlich auch nicht mehr als 6-7 fps erzielen. Sicherlich ist da noch Raum für Optimierungen, aber ich beginne langsam daran zu zweifeln, dass ich jemals >20 fps erreichen werde.
-
Nanyuki schrieb:
Ich hab mich daraufhin selbst an einer Implementation versucht. Die benötigt nun rund 350-400 ms. Wenn ich ohne SSE-Unterstützung compiliere, dauert es >700ms. Auf einer halbwegs aktuellen Dual Core-CPU wird man damit vermutlich auch nicht mehr als 6-7 fps erzielen. Sicherlich ist da noch Raum für Optimierungen, aber ich beginne langsam daran zu zweifeln, dass ich jemals >20 fps erreichen werde.
poste eine kleine applikation als contest, so haben hier schon so einige ihr ziel erreicht
an sich sollte man das aber locker fluessig bekommen.
-
Nanyuki schrieb:
Eine Möglichkeit wäre noch die einfache lineare Interpolation, die schneller ist und kaum ein schlechteres Bild liefert, aber das kostet je nach Auflösung immer noch viel Rechenzeit.
"Lineare Interpolation klingt sehr nachdem, was ich zur Zeit schon verwende (eingefügte Pixelreihen/-spalten bekommen als Farbe einen Mittelwert der umliegenden Pixel). Wenn der Skalierfaktor ganzzahlig ist (also z.B. 800x600 -> 1600x1200), funktioniert das zwar recht gut, andernfalls wird es aber sehr unschön.
Nönö, es wird schon richtig interpoliert, d.h. wenn der neue Pixel beispielsweise bei x = 4.25 liegt, bekommt er eben 75% von Pixel 4 und 25% von Pixel 5, so ganz grob ausgedrückt. Das sieht dann auch gut aus, und ich glaube einen ähnlichen Algorithmus wird auch in der Bildschirm-Hardware verwendet, da er im Grunde recht einfach zu verwirklichen ist. Und das ist letztendlich auch die Art und Weise, wie Grafikkarten Texturen interpolieren. Aber wie auch immer. Jedenfalls habe ich so etwas mal bei einer eigenen Bilddatenkspeicherklasse implementiert, und der Algorithmus benötigt ca. 1/3 der Zeit, den ein ebenfalls implementierter Lanczos-Algo benötigt. (und der Qualitätunterschied ist wirklich gering)
-
Nanyuki schrieb:
[...] Die benötigt nun rund 350-400 ms. Wenn ich ohne SSE-Unterstützung compiliere, dauert es >700ms.
Verzichte mal auf Floating-Point. Klingt "oldschool" ist aber ~3x schneller.
Powerpaule schrieb:
der Algorithmus benötigt ca. 1/3 der Zeit, den ein ebenfalls implementierter Lanczos-Algo benötigt. (und der Qualitätunterschied ist wirklich gering)
Das kommt auf den Einsatzzweck an.
Skalierungen unter 50% brauchen naturgemaess mehr als 2x2 Samples.
Hohe Frequenzen (feine Bildstrukturen) werden durch das Filter generell wenig und nicht gleichmaessig bedaempft (Aliasing).
-
Nanyuki schrieb:
hustbaer schrieb:
Lanczos funktioniert wunderbar in Echtzeit.
Ich guck Videos am Computer z.B. grundsätzlich nur über Lanczos aufskaliert...
Du brauchst bloss eine effiziente Implementierung.Hm, interessant... erledigt das die Grafikkarte oder wird das tatsächlich von der CPU gemacht?
Ich schätze mal dass es in Software gemacht wird. Guck in den ffdshow Code rein, da müsste es zu finden sein
(Bzw. ist natürlich leicht möglich dass es in einer der von ffdshow verwendeten Libraries wie z.B. libavcodec implementiert ist)Ich gehe auch davon aus dass das brutalst optimiert ist, also mit MMX/SSE oder was auch immer. Aber wie gesagt, läuft für z.B. 640x480 -> 1280x960 (25fps) in Echtzeit (<= 10% Rechenzeit eines Q6600 - also <= 40% eines Cores -- schwer zu sagen wieviel genau, da da das Dekodieren des Videos schon mit dabei ist).
@Powerpaule:
Der Qualitätsunterschied zwischen bilinear und Lanczos ist nicht "wirklich gering", sondern dramatisch. Der Unterschied zwischen bikubisch und Lanczos ist kleiner, aber immernoch deutlich sichtbar. Natürlich hängt es vom Ausgangsmaterial ab - wenn das schon ziemlich schwammig ist, wird man kaum einen Unterschied sehen. Wenn das aber schön scharf ist, ist der Unterschied wie gesagt ziemlich gross.Wo du natürlich Recht hast: Lanczos ist deutlich aufwendiger als bilinear oder bikubische Interpolation.