Autor Beitrag
the_titan
Hält's aus hier
Beiträge: 4



BeitragVerfasst: 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:

ausblenden 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 user profile iconNarses: Code- durch Delphi-Tags ersetzt
Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Mi 27.01.2010 um 15:42
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Mi 27.01.10 16:41 
ich schreibs jetzt mal nur so runter, 100%ig muss es nicht stimmen:

ausblenden 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..3of 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 //R-Wert
      P^[2] := 0 //G-Wert
      P^[3] := 0 //B-Wert
  
      inc(P);
    end;
  end;


ansonsten gibt's im Delphitreff ein Tutorial!

LG
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: Mi 27.01.10 17:49 
Ansonsten kann man da sicher mit Assembler noch jede Menge optimieren. :wink:

Abgesehen davon hat Rot-Machen nichts mit Helligkeit zu tun.
FinnO
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Mi 27.01.10 17:51 
Tschuldigung, dass ich lebe :D

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Mi 27.01.10 18:33 
öhm. Heller ist das dann aber nicht :P
Jakob_Ullmann
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1747
Erhaltene Danke: 15

Win 7, *Ubuntu GNU/Linux*
*Anjuta* (C, C++, Python), Geany (Vala), Lazarus (Pascal), Eclipse (Java)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: Mi 27.01.10 18:40 
joa. Multiplikation wird bei PS explizit als solche gehandled, also ist imho eine sache für sich.
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: 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



BeitragVerfasst: Mi 27.01.10 21:38 
user profile iconthe_titan hat folgendes geschrieben Zum zitierten Posting springen:
@ 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1331
Erhaltene Danke: 123

Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 779
Erhaltene Danke: 1

Vista, XP, W2K
Delphi, .Net, Deutsch und Englisch
BeitragVerfasst: 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



BeitragVerfasst: 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).