Entwickler-Ecke
Multimedia / Grafik - Bitmap schnell skalieren
Martok - Mo 12.03.12 23:32
Titel: Bitmap schnell skalieren
Hallo!
Ich bin echt irritiert, dass dazu nichts in der Library ist - oder ich es nicht finde. ;)
Wie auch immer: ich habe ein TBitmap und ein TCanvas eines Fensters. Das Bitmap soll gestretcht werden. Das grundsätzlich in ganzzahligen Faktoren, also 1fache, doppelte, 3fache Größe etc (immer vergrößern also).
StretchDraw hat da ein Problem: es ist eben eine Allzweck-Funktion und als solche etwas langsam - das geht manuell mit Sicherheit schneller. Glaub ich :think:
Das Problem ist aber, dass die üblichen ScanLine-basierten Varianten natürlich ein Bitmap als Ziel brauchen. Ich möchte aber nicht noch ein Bitmap haben. Das Fenster ist ja im Prinzip schon eins ;)
Also: was ist schneller als StretchDraw und kann ein Bitmap fix skaliert auf ein Canvas werfen?
Viele Grüße,
Martok
jaenicke - Di 13.03.12 07:45
Am schnellsten ist da vermutlich das schnell selbst zu implementieren. Hätte ich jetzt 10 Minuten würde ich es machen, aber ich muss gleich los...
Die Idee ist simpel:
Größe passend setzen, dann die Zeilen von unten nach oben mit Scanline durchgehen.
Martok - Di 13.03.12 08:06
Danke für die Ideen!
bummi hat folgendes geschrieben : |
ich weiß nicht ob es schneller ist, aber man kann auch das Canvas vor dem "Malen" transformieren |
Warum grade ich das übersehen hab, löse doch sonst alles mit GM_ADVANCED... ist aber exakt gleich schnell.
jaenicke hat folgendes geschrieben : |
Größe passend setzen, dann die Zeilen von unten nach oben mit Scanline durchgehen. |
Schon klar, aber wie ich schrieb:
Martok hat folgendes geschrieben : |
Ich möchte aber nicht noch ein Bitmap haben. Das Fenster ist ja im Prinzip schon eins |
Ich mein, nochmal 5MB für ein weiteres Offscreen-Bitmap wäre nicht das Problem, aber schöner würde ich das schon finden. Schon weil ich vermute, dass nochmal umkopieren dann auch ncht schneller wird ;)
jaenicke - Di 13.03.12 08:25
Wo habe ich etwas von einer zusätzlichen Bitmap geschrieben? :gruebel:
Ich meine sowas, mit den äußersten Pixeln bin ich grad nicht sicher ohne es zu testen, den Rest machst du schon:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| type TPseudoRGB = packed record First: Word; Last: Byte; end; PPseudoRGB = ^TPseudoRGB; var Test: TBitmap; NewLine, OldLine, LastOldLine, OldWidth: Integer; x, x2, OldPixel, NewPixel1, NewPixel2, NewPixel3: PPseudoRGB; begin Test := TBitmap.Create; try Test.LoadFromFile(...); Test.PixelFormat := pf24bit; LastOldLine := Test.Height - 1; OldWidth := Test.Width - 1; Test.SetSize(Test.Width * 3, Test.Height * 3); for OldLine := LastOldLine downto 0 do begin OldPixel := Test.ScanLine[OldLine]; NewLine := OldLine * 3; NewPixel1 := Test.ScanLine[NewLine]; NewPixel2 := Test.ScanLine[NewLine + 1]; NewPixel3 := Test.ScanLine[NewLine + 2]; for x := 1 to OldWidth do begin for x2 := 1 to 3 do begin NewPixel1.First := OldPixel.First; NewPixel1.Last := OldPixel.Last; Inc(NewPixel1); NewPixel2.First := OldPixel.First; NewPixel2.Last := OldPixel.Last; Inc(NewPixel2); NewPixel3.First := OldPixel.First; NewPixel3.Last := OldPixel.Last; Inc(NewPixel3); end; Inc(OldPixel); end; end; Test.SaveToFile(...); finally Test.Free; end; |
Blup - Di 13.03.12 11:34
jaenicke hat folgendes geschrieben : |
Ich meine sowas, mit den äußersten Pixeln bin ich grad nicht sicher ohne es zu testen, den Rest machst du schon: |
Da gibt es tatsächlich noch Probleme, aber so gehts:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:
| procedure SkaliereBMP(ABitmap: TBitmap; AFaktorX, AFaktorY: Integer); type TBGR = packed record B: Byte; G: Byte; R: Byte; end; PBGR = ^TBGR; var OldWidth, OldHeight, NewWidth, NewHeight, x1, x2, y1, y2: Integer; OldPixel, NewPixel: PBGR; begin ABitmap.Pixelformat := pf24Bit; OldWidth := ABitmap.Width; OldHeight := ABitmap.Height; NewWidth := OldWidth * AFaktorX; NewHeight := OldHeight * AFaktorY; if AFaktorX > 1 then begin ABitmap.SetSize(NewWidth, OldHeight); for y1 := 0 to OldHeight - 1 do begin OldPixel := ABitmap.ScanLine[y1]; NewPixel := OldPixel; Inc(OldPixel, OldWidth); Inc(NewPixel, NewWidth); for x1 := OldWidth - 1 downto 0 do begin Dec(OldPixel); for x2 := AFaktorX - 1 downto 0 do begin Dec(NewPixel); NewPixel^ := OldPixel^; end; end; end; end; if AFaktorY > 1 then begin ABitmap.SetSize(NewWidth, NewHeight); for y1 := OldHeight - 1 downto 0 do begin OldPixel := ABitmap.ScanLine[y1]; for y2 := AFaktorY - 1 downto 0 do begin NewPixel := ABitmap.ScanLine[y1 * AFaktorY + y2]; Move(OldPixel^, NewPixel^, SizeOf(TBGR) * NewWidth); end; end; end; end; |
Martok - Di 13.03.12 21:58
Danke euch Beiden. Funktioniert wunderbar - ist aber noch langsamer :D
Allerdings hat mich das dazu gebracht, mal etwas zu testen, und ich hab einfach mal ein Bitmap in der Endgröße ohne irgendwelche Bearbeitung geblittet. Wie sich rausstellt, ist tatsächlich das Kopieren der Pixel an sich so langsam, die Skalierung ist schon verdammt schnell.
Wobei langsam auch relativ ist. Schnell genug ist das auch so, aber: 60FPS kosten 80% auf einem Kern, da ist nicht mehr viel Luft für Logik...
Immerhin: falls mal jemand so eine Funktion sucht, wird er jetzt eine finden :zustimm:
uall@ogc - Mi 14.03.12 22:26
StretchDraw ist ziemlich schnell. Wichtig ist, dass du nicht die Farbtiefe änderts d.h. das Pixelformat des ZielBitmaps sollte auf das des Ausgangsbitmaps gesetzt werden. Außerdem solltest du das Zielbitmap nur ein einziges mal erstellen wenn du mehrere Frames bearbeitest. Farbraumwechsel + Speicher reservieren ist langsam, wobei ersteres noch vernachlässigbar ist.
platzwart - Do 15.03.12 00:56
Schau dir mal die Graphics32 an (dort beispielsweise TBitmap32 oder so ähnlich). Die sind extrem schnell. Hatte mir bei einem Projekt gegenüber dem Standard TBitmap einen Performanceschub von über dem 50-fachen gebracht. Konnte damit auf einem Vierkernprozessor 4 Bilder gleichzeitig verarbeiten und dabei 110.000.000 Pixelzugriffe pro Sekunde realisieren...
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!