Autor |
Beitrag |
the_titan
Hält's aus hier
Beiträge: 4
|
Verfasst: Mi 27.01.10 16:36
Hallo,
im Moment arbeite ich an einem Bildbearbeitungsprogramm. Für die Umsetzung der grundelegenden Funktionen, wie zum Beispiel Helligkeit und Kontrast verändern, benutze ich zwei ineinandergeschachtelte Zählschleifen für jede Bildzeile und dann jeweils für jedes Pixel in der Zeile. Dabei lese ich jeweils die Farbe des Pixels ein, teile die Farbe in drei RGB-Werte auf, führe die Berechnung aus und füge sie letztendlich wieder zum Typ TColor zusammen.
Hier ein Beispiel:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| procedure HelligkeitAendern(Bitmap : TBitmap; Helligkeit : Integer); var x,y : Integer; R,G,B : Byte; begin for y:=0 to Bitmap.Height-1 do for x:=0 to Bitmap.Width-1 do begin R := GetRValue(Bitmap.Canvas.Pixels[x,y]) + Helligkeit; G := GetGValue(Bitmap.Canvas.Pixels[x,y]) + Helligkeit; B := GetBValue(Bitmap.Canvas.Pixels[x,y]) + Helligkeit; Bitmap.Canvas.Pixels[x,y] := RGB(R,G,B); end; end; |
Das Problem dabei ist, dass dieses Verfahren sehr lange dauert - bei 5-Megapixel-Bildern bis zu einer Minute. Gibt es einen anderen Weg der schneller geht? Also vielleicht so, dass nicht jedes Pixel einzeln bearbeitet werden muss?
Ich würde mich sehr über eine Antwort freuen.
Vielen Dank im Vorraus,
euer Kay
Moderiert von Narses: Code- durch Delphi-Tags ersetztModeriert von Narses: Topic aus Sonstiges (Delphi) verschoben am Mi 27.01.2010 um 15:42
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 27.01.10 16:41
ich schreibs jetzt mal nur so runter, 100%ig muss es nicht stimmen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure makeRed(var Bitmap : TBitmap); type PixArray : Array[1..3] of TByte; PPixArray: ^PixArray; var P : PPixArray; begin
for x := 1 to Bitmap.Height do begin P := Bitmap.ScanLine[x]; for y := 1 to Bitmap.Width do begin P^[1] := 255 P^[2] := 0 P^[3] := 0 inc(P); end; end; |
ansonsten gibt's im Delphitreff ein Tutorial!
LG
|
|
Jakob_Ullmann
      
Beiträge: 1747
Erhaltene Danke: 15
Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
|
Verfasst: Mi 27.01.10 17:49
Ansonsten kann man da sicher mit Assembler noch jede Menge optimieren.
Abgesehen davon hat Rot-Machen nichts mit Helligkeit zu tun.
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 27.01.10 17:51
Tschuldigung, dass ich lebe
wie man exakt die Helligkeit verändert, hat Oliver Kahn ja schon ausreichend beschrieben. Da fehlt zwar noch die Bereichsprüfung, aber, ihm sollte mit meinem Code klar sein, wie er die jeweiligen Bytes jedes Pixels effizienter verändert.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Mi 27.01.10 18:28
Hallo,
rein optisch eine Frage, ist multiplizieren nicht angebrachter?
Also mehr in Richtung 10% heller, damit schwarz schwarz bleibt, wie jeder Jeck weiß : Dreimal Null ist Null bleibt Null...
Gruß Horst.
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 27.01.10 18:33
öhm. Heller ist das dann aber nicht 
|
|
Jakob_Ullmann
      
Beiträge: 1747
Erhaltene Danke: 15
Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
|
Verfasst: Mi 27.01.10 18:39
"Helligkeit" ist soweit ich weiß klar definiert. Das mit der Multiplikation / Division wäre dann eher Intensität.
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 27.01.10 18:40
joa. Multiplikation wird bei PS explizit als solche gehandled, also ist imho eine sache für sich.
|
|
platzwart
      
Beiträge: 1054
Erhaltene Danke: 78
Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
|
Verfasst: Mi 27.01.10 19:47
Graphics32, die bringen einen extremen Geschwindigkeitsvorteil, kann ich nur empfehlen.
_________________ Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
|
|
the_titan 
Hält's aus hier
Beiträge: 4
|
Verfasst: Mi 27.01.10 21:31
also erstmal vielen Dank für die vielen Antworten
es geht mir nicht darum wie die Berechnungen aussehen sollen (ob Addieren oder Multiplizieren ist ersmal egal), sondern wie ich die Bildmanipulation allegemein angehen soll um Zeit zu sparen. bei photoshop zum beispiel dauert es weniger als eine sekunde, und bei meinem programm manchmal mehr als eine minute
@ FinnO: ich habe deinen quelltext ausprobiert und nach ein bisschen syntaxverbesserung zum laufen bekommen, allerdings passiert dabei nichts.. habe ich vielleicht was übersehen?
@ Jakob_Ullmann: was meinst du mit Assembler? ist das eine komponente für delphi?
@ platzwart: danke für dein tipp... ich werde graphics32 gleich mal ausprobieren
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 27.01.10 21:38
the_titan hat folgendes geschrieben : | @ Jakob_Ullmann: was meinst du mit Assembler? ist das eine komponente für delphi? |
Wenn man programmiert, sollte man eigentlich schon etwas Ahnung von den Grundlagen haben: de.wikipedia.org/wiki/Assemblersprache
Allerdings wird sich der Arbeitsaufwand kaum lohnen. Die heutigen Compiler optimieren schon so gut, dass man als Mensch da kaum noch was reißen kann.
Hast du dir schon mal die Funktion Scanline angeguckt?
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Mi 27.01.10 21:42
*hüstel* nicht, dass ich die erwähnt hätte?
BTW: Scanline ist in der Regel SOO schnell, dass man da wirklich keine Probleme hat 
|
|
ene
      
Beiträge: 779
Erhaltene Danke: 1
Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
|
Verfasst: Do 28.01.10 10:25
Zu Scanline sollte man sich übrigens mal efg's Tech Note durchlesen.
_________________ Wir, die guten Willens sind, geführt von Ahnungslosen, Versuchen für die Undankbaren das Unmögliche zu vollbringen.
Wir haben soviel mit so wenig so lange versucht, daß wir jetzt qualifiziert sind, fast alles mit Nichts zu bewerkstelligen.
|
|
helgew
Hält's aus hier
Beiträge: 12
|
Verfasst: Fr 29.01.10 20:24
noch schneller gehts mit Adressberechnung und Laden der Daten in den stack frame der subroutine. Die Scanline-Aufrufe kann man sich sparen, wenn man Adressoffset und line delta bestimmt hat. Danach kann man den Adresszeiger immer weiter inkrementieren. Besonders spaßig ist blockweises laden und bearbeiten von Daten, was bei subpixelweisen (also pro Farbkanal angewandten) Operationen wie Helligkeit und Kontrast, Alphablending etc. fällig wird, da man hier auch gepackte Befehle anwenden kann (MMX-Befehlssatz).
Da ich schon eine Weile an dieser Front kämpfe: GDI ist der böse Flaschenhals, wenn du mit "schnell" ruckelfrei in Echtzeit meinst, wirst du genau da an die Grenzen stoßen (also bei BitBlt / StretchBlt, usw. wie es von Canvas.Draw() gekapselt wird).
|
|