Autor |
Beitrag |
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 12.03.12 23:32
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
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
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
bummi
Beiträge: 1248
Erhaltene Danke: 187
XP - Server 2008R2
D2 - Delphi XE
|
Verfasst: Di 13.03.12 01:19
ich weiß nicht ob es schneller ist, aber man kann auch das Canvas vor dem "Malen" transformieren
www.delphipraxis.net...rehung-und-zoom.html
unit ExCanvasTools;
_________________ Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 13.03.12 08:06
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
jaenicke
Beiträge: 19285
Erhaltene Danke: 1743
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 13.03.12 08:25
Wo habe ich etwas von einer zusätzlichen Bitmap geschrieben?
Ich meine sowas, mit den äußersten Pixeln bin ich grad nicht sicher ohne es zu testen, den Rest machst du schon: 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; |
Für diesen Beitrag haben gedankt: BenBE, Martok
|
|
Blup
Beiträge: 174
Erhaltene Danke: 43
|
Verfasst: 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:
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; |
Für diesen Beitrag haben gedankt: BenBE, Martok
|
|
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 13.03.12 21:58
Danke euch Beiden. Funktioniert wunderbar - ist aber noch langsamer
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
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Für diesen Beitrag haben gedankt: BenBE
|
|
uall@ogc
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: 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.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
Für diesen Beitrag haben gedankt: BenBE
|
|
platzwart
Beiträge: 1054
Erhaltene Danke: 78
Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
|
Verfasst: 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...
_________________ Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
|
|
mvollmer
Beiträge: 42
Erhaltene Danke: 3
Delphi (Seattle), C (MPLAB X)
|
Verfasst: Do 15.03.12 13:03
[OT]
graphics32.org/wiki/Main/TBitmap
Zitat: | Main /
TBitmap
WTF?
|
[/OT]
Btw: Was ist mit StrechtBlt?
|
|
|