Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Ein Bild mit einer Farbe multiplizieren? (https://www.delphipraxis.net/107175-ein-bild-mit-einer-farbe-multiplizieren.html)

Cyberstorm 23. Jan 2008 18:40


Ein Bild mit einer Farbe multiplizieren?
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo.

ich möchte ein bild (tbitmap) mit einer farbe einfärben.

ich möchte sie aber nicht überblenden, sondern mit einem variablen faktor "multiplizieren".
also in diversen bildbearbeitungsprogrammen gibt es ja verschiedene modi, um bilder "übereinanderzupacken".

wie funktioniert rechnerisch multiplizieren bei einem bild?


wennich zum beispiel das nachfolgende bild miteinem grünton mischen will,
überblendeich esim moment nur (bild2) ich will aber (bild3) errechnen.

das ist der selbe farblayer (in bild2 und 3) mit 50%(soll im programm der faktor sein) transparenz nur einmal in photoshop mit "norma" und einmal mit "multiplizieren":

beim multiplizieren bleibt übrigens auch bei 100% noch was vom original übrig, beim normalen überblenden natürlich nur noch komplett die grüne farbe...

[edit=SirThornberry]Bilder in Anhang gepackt - Mfg, SirThornberry[/edit]

Larsi 23. Jan 2008 18:58

Re: Ein Bild mit einer Farbe multiplizieren?
 
kannste nicht über das original bitmap n neues drauftun was leicht transparent ist. das zweite hat dann zum beispiel die farbe grün. wenn du was ganz anderes gemeint hast, sry! :)

Die Muhkuh 23. Jan 2008 19:06

Re: Ein Bild mit einer Farbe multiplizieren?
 
Da steht doch, was er möchte. Die Farben multiplizieren und nichts transparent machen...

Larsi 23. Jan 2008 19:08

Re: Ein Bild mit einer Farbe multiplizieren?
 
und warum macht dass was ch jetzt gemacht habe was anderes als das multiplizieren?

Cyberstorm 23. Jan 2008 19:10

Re: Ein Bild mit einer Farbe multiplizieren?
 
sieh dir doch mal die beiden bilder an (normal und multiplizieren) dann enddeckst du sicherlich auch einen unterschied...

Die Muhkuh 23. Jan 2008 19:10

Re: Ein Bild mit einer Farbe multiplizieren?
 
Weil dann das raus kommt, was oben bei "normal" steht.

Namenloser 23. Jan 2008 19:12

Re: Ein Bild mit einer Farbe multiplizieren?
 
Weil es etwas anderes ist, wenn man eine Farbe transparent dazu rechnet (Farbe1*(1-transparenz)+farbe2*transparenz), oder Farbe1*Farbe2.

DeddyH 23. Jan 2008 19:13

Re: Ein Bild mit einer Farbe multiplizieren?
 
Ich gebe mal einen Link weiter, den heute morgen jemand gepostet hat (weiß nur leider gerade nicht mehr, wer :oops: ): http://www.aggpas.org/

Corpsman 23. Jan 2008 19:20

Re: Ein Bild mit einer Farbe multiplizieren?
 
In meinem Raytracer heist Multiplizieren Komponenten weise

D.h.

Orginalfarbe RGB => Trippel ( x,y,z) mit x,y,z in [ 0..1 ]

Dito mit Multiplicant RGB => Tripel ( a,b,c)

dann Neue Farbe = ( x*a*256,y*b*256,z*c*256)

Probier mal das .

So wie ich dich da Verstehe geht dein Wunsch aber mittels +

Neue Farbe = ( (x+a)*256,(y+b)*256,(z+c)*256)

du must die einzelwerte nur noch Begrenzen

also der Art

max(0,Min(255,round((x+a)*255))) ...

Cyberstorm 23. Jan 2008 19:54

Re: Ein Bild mit einer Farbe multiplizieren?
 
hi.

du hast einen raytracer programmiert?
sehr interessant! (ich studiere 3d animation) :-).

vielen dank, werde ich morgen mal ausprobieren, bin jetzt leider nicht mehr zuhause.

im ersten fall kommen doch immer werte über 256 raus (außer bei 0, 0). wie ist das dann zu verstehen?
also wenn da was weis ich 430 herauskommt?
das hat mich auch verwirrt und davon abgehalten die farben einfach zu multiplizieren.

in den anätzen fehlt nur irgendwie der faktor, mit dem ich die ganze geschichte von 0-100% regeln kann?
kannst du mir einen tipp geben, wie das zu implementieren wäre?

liebe grüße
konrad

Corpsman 23. Jan 2008 21:05

Re: Ein Bild mit einer Farbe multiplizieren?
 
Hossa Cyberstorm,

Ich Studiere Informatik, im 7. Semester mit Vetierfung VIS, und da schreibt jeder mal nen Raytracer

Im 1. Fall kommen Immer werte zwischen 0..1 raus
Du liest die RGB werte aus, dann Skalleirst du sie auf 0..1 ( Also durch 255 Teilen ) dann die Berechnung und danach wieder HochsKalieren => ex kommt wieder ein Wert zwischen 0..1 das ist mit ein rund warum OgenGL alles auf 0..1 abbilden kann.

Bei Meinem Raytracer genau wie bei anderen Kann man ,wenn dann doch Größere Werte Auftreten die Mittels Scaling oder clamping weiterverarbeiten.

Dein Faktor ist auch ganz einfach.

Stell dir For du willst dein Bild Grün Färben ( Grün = (0,255,0) )
dann willst du 50% Grün haben das ergibt dann (Farbe alt = ( x,y,z))

Delphi-Quellcode:
Prozent := 50 / 100;
Farbe_neu :=( max(0,min(255,round(0*Prozent +x))),max(0,min(255,round(255*Prozent +y))),max(0,min(255,round(0*Prozent +z))));
Wenns noch genauer sein mus , must bis zum We warten, habe einen Hauptseminarvortrag der mich aufhält.

omata 23. Jan 2008 22:10

Re: Ein Bild mit einer Farbe multiplizieren?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Cyberstorm,

da ich mich gerade mit einer 3D-Lasertriangulation beschäftigt habe und dort Bildverarbeitung eine entscheidene Rolle spielt,
habe ich meinen Verarbeitungsquellcode mal an dein Problem angespasst.

Vielleicht hilft dir das ja weiter.

Gruss
Thorsten

Cyberstorm 24. Jan 2008 08:28

Re: Ein Bild mit einer Farbe multiplizieren?
 
danke euch beiden!

werde ich gleich mal ausprobieren...

Cyberstorm 24. Jan 2008 10:04

Re: Ein Bild mit einer Farbe multiplizieren?
 
hmm also ersteinmal machen beide funktionen von euch (omata & corpsman) das selbe aber noch nicht ganz, was ich will :-).
zumindest wird bei 100% nicht komplett überblendet aber das ergebnis ist nicht wie ich will (siehe bilder).

habe dein programm mal gekürzt und das einlesen der komponente überlassen:
die scroll boxen haben als onchange ereignis FormCreate...

Delphi-Quellcode:
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Self.DoubleBuffered:=true;
  Shape.Brush.Color:=RGB(SbRot.Position, SbGruen.Position, SbBlau.Position);
  Image.Picture.LoadFromFile('ori.bmp');
  Calculate;;
end;

procedure TfrmMain.Calculate;
var
  Prozent: Real;
  x, y: Integer;
  P: PRGB;
begin
  Prozent:=SbProzent.Position / 100;
   for y:=0 to Image.Picture.Height-1 do
    begin
      P:=Image.Picture.Bitmap.ScanLine[y];
       for x:=0 to Image.Picture.Width-1 do
        begin
          p.Blue:=min(255, round(((p.Blue / 255) + ((SbBlau.Position / 255) * Prozent)) * 255));
          p.Green:=min(255, round(((p.Green / 255) + ((SbGruen.Position / 255) * Prozent)) * 255));
          p.Red:=min(255, round(((p.Red / 255) + ((SbRot.Position / 255) * Prozent)) * 255));
          Inc(p);
        end;
    end;
end;
damit kommen nun folgende ergebnisse bei 100% grün (0% rot und blau) und 50%, danach 100% faktor:

programm grün:255 prozent: 50%
http://cyberstorm.hopto.org/prog_half.jpg

programm grün:255 prozent: 100%
http://cyberstorm.hopto.org/prog_full.jpg

photoshop grün:255 prozent: 50%
http://cyberstorm.hopto.org/half.jpg

photoshop grün:255 prozent: 100%
http://cyberstorm.hopto.org/full.jpg

Corpsman 24. Jan 2008 10:12

Re: Ein Bild mit einer Farbe multiplizieren?
 
Ja was du nu gemacht hast is t das Clamping

Probier doch einfach mal das Scaling aus.

Als du Addierst die Farbanteile wie bisher

(r,g,b)
machst dann t := max(r,max(g,b));

und bei t > 255

(r/t*255,g/t*255,b/t*255)

Diese variante Behält den Farbwert, evtl ist das besser.

Cyberstorm 24. Jan 2008 10:17

Re: Ein Bild mit einer Farbe multiplizieren?
 
also ich habe gerade mal in der berechnung das "+" durch "*" ersetzt:

vorher:
Delphi-Quellcode:
(p.Blue / 255) + ((SbBlau.Position / 255)
nachher:
Delphi-Quellcode:
(p.Blue / 255) * ((SbBlau.Position / 255)
für Rot und Grün natürlich ebenso.

nun kommt bei grün:255 und 100% faktor das selbe ergebnis wie bei photoshop heraus (siehe letzer post).

ABER bei 50% kommt leider das bei raus :-/:

http://cyberstorm.hopto.org/dark_prog.jpg


ich guck mir ersteinmal den letzen post an und probiere das ausund melde mich dann nochmal.

Lun 24. Jan 2008 10:47

Re: Ein Bild mit einer Farbe multiplizieren?
 
Hi,

ich weiß ja nicht ob es hilft aber hier hast du eine Routine die ein Bitmap einfärbt den Raster kannste ja weglassen.
Weiß jetzt nicht ob es das ist was du suchst.

Unter Grafik / Icons / Farben / Cursor auf der Seite findest du
noch mehr Funktionen zum bearbeiten von Bildern.


greetz Lun

P.S: Wenn du das auf den Beispiel Foto bist, ich find Du kannst jede Farbe tragen, aber das Original gefällt mir am besten :mrgreen:

Cyberstorm 24. Jan 2008 10:57

Re: Ein Bild mit einer Farbe multiplizieren?
 
ich verzweifle langsam :-/.

also habe das jetzt folgendermaßen abgeändert:

Delphi-Quellcode:
procedure TfrmMain.Calculate;
var
  Prozent: Real;
  x, y, r, g, b, t: Integer;
  P: PRGB;
begin
  Prozent:=SbProzent.Position / 100;
   for y:=0 to Image.Picture.Height-1 do
    begin
      P:=Image.Picture.Bitmap.ScanLine[y];
       for x:=0 to Image.Picture.Width-1 do
        begin
          r:=round(((p.Blue / 255) + ((SbBlau.Position / 255) * Prozent)) * 255);
          g:=round(((p.Green / 255) + ((SbGruen.Position / 255) * Prozent)) * 255);
          b:=round(((p.Red / 255) + ((SbRot.Position / 255) * Prozent)) * 255);
          t:=max(r,max(g,b));
          if t>255 then
            begin
              r:=Round(r/t*255);
              g:=Round(g/t*255);
              b:=Round(b/t*255);
            end;
          p.Blue:=b;
          p.Green:=g;
          p.Red:=r;
          Inc(p);
        end;
    end;
end;
da kommt aber quatsch bei raus. wird dann blau wenn ich grün anmache und so sachen...

die sachen von der ddr ecke sind das selbe wie diealte funktion :-(

Corpsman 24. Jan 2008 11:06

Re: Ein Bild mit einer Farbe multiplizieren?
 
Du bringst mich noch dazu das ich hergehe und das geschwind implementiere...

Also Vergiss unsere bisherigen Codeschnipsel mahcs nochmal neu

1. Alter Farbwert Hohlen
2. Überblendfarbe Hohlen und dann Komponentenweise * Prozent
3. Alte Farbe + Neue Farbe
4. Behandlung des Überlaufes

5.1 Clamping ( d.h. die Min(max( .. Geschichte )


ODER


5.2 Scaling D.h. du schaust ob Max(r,b,g) > 255 , wenn Ja dann Skallierst du alle 3 Farbwerte so das der Max(R,G,B) = 255 wird.

6. Speichern.

Khabarakh 24. Jan 2008 11:34

Re: Ein Bild mit einer Farbe multiplizieren?
 
Ich glaube, ihr kommt etwas vom Weg ab.
Für den gewünschten Effekt muss doch für die originale Farbe C1, die "Multiplikator-Farbe" C2 und den Mischfaktor f (alle in [0, 1]) einfach nur folgende Formel angewendet werden:
Code:
C1 * (1 - f) + C1 * C2 * f
Und dabei ist definitiv kein Clamping/Scaling/... nötig.
Hab das mal schnell in Paint.Net nachgestellt, es kommen exakt die beiden Photoshop-Bilder aus #14 heraus.
Code:
CurrentPixel = src[x,y];
byte f = PrimaryColor.A; // der Alphakanal der Primärfarbe wird als Faktor missbraucht
CurrentPixel.R = (byte)
 ((CurrentPixel.R * (255 - f) + CurrentPixel.R * PrimaryColor.R * f / 255) / 255);
CurrentPixel.G = (byte)
 ((CurrentPixel.G * (255 - f) + CurrentPixel.G * PrimaryColor.G * f / 255) / 255);
CurrentPixel.B = (byte)
 ((CurrentPixel.B * (255 - f) + CurrentPixel.B * PrimaryColor.B * f / 255) / 255);
dst[x,y] = CurrentPixel;

Corpsman 24. Jan 2008 20:40

Re: Ein Bild mit einer Farbe multiplizieren?
 
Die Formel kannte ich noch nicht , sieht aber vielversprechend aus.

Cyberstorm 25. Jan 2008 12:42

Re: Ein Bild mit einer Farbe multiplizieren?
 
Danke! :-).

macht genau das, was photoshop macht - was ich will :-)

Cyberstorm 25. Jan 2008 12:53

Re: Ein Bild mit einer Farbe multiplizieren?
 
fall noch jemand eine copy & paste lösung braucht:

Delphi-Quellcode:
type
  TRGB = record
    Blue: Byte;
    Green: Byte;
    Red: Byte;
  end;

  PRGB = ^TRGB;

procedure Multi(src: TBitmap; r, g, b: Integer; Intensiv: Byte);
var
  P: PRGB;
  y, x: integer;
begin
  for y:=0 to src.Height-1 do
    begin
      P:=src.scanline[y];
      for x:=0 to src.Width-1 do
        begin
          P.Blue:=Round( ((P.Blue * (255 - Intensiv) + P.Blue * b * Intensiv / 255) / 255) );
          P.Green:=Round( ((P.Green * (255 - Intensiv) + P.Green * g * Intensiv / 255) / 255) );
          P.Red:=Round( ((P.Red * (255 - Intensiv) + P.Red * r * Intensiv / 255) / 255) );
          Inc(P);
        end;
    end;
end;
anmerkung: muss man nicht als funktion machen oder das bitmap als var parameter übergeben, da scanline ja speicheradressen zurückliefert und diese dann auch direkt im speicher geändert werden.

Phantom1 26. Jan 2008 10:07

Re: Ein Bild mit einer Farbe multiplizieren?
 
@Cyberstorm: du kannst deinen code noch etwas vereinfachen und auf geschwindigkeit optimieren, ich hab das mal für dich gemacht :wink:

Delphi-Quellcode:
procedure Multi(src: TBitmap; r, g, b, Intensiv: Byte);
var
  P: PRGBTriple;
  xy: integer;
begin
  if src.PixelFormat<>pf24bit then
    src.PixelFormat:=pf24bit;

  P:=src.scanline[src.Height-1];
  for xy:=0 to src.Height*src.Width-1 do begin
    P.rgbtBlue := (P.rgbtBlue shl 8 * not Intensiv + P.rgbtBlue * Succ(b) * Intensiv) shr 16;
    P.rgbtGreen := (P.rgbtGreen shl 8 * not Intensiv + P.rgbtGreen * Succ(g) * Intensiv) shr 16;
    P.rgbtRed  := (P.rgbtRed  shl 8 * not Intensiv + P.rgbtRed  * Succ(r) * Intensiv) shr 16;
    Inc(P);
  end;
end;
mfg

Muetze1 26. Jan 2008 17:12

Re: Ein Bild mit einer Farbe multiplizieren?
 
Zitat:

Zitat von Phantom1
@Cyberstorm: du kannst deinen code noch etwas vereinfachen und auf geschwindigkeit optimieren, ich hab das mal für dich gemacht :wink:

Du beachtest nicht das padding zwischen den einzelnen ScanLines! Jede ScanLine ist 32 Bit aligned und da du mit 24 bpp arbeitest ist nur jeder 4. Pixel 32 bit aligned und somit hast du eine große Chance auf falsche Pixeldaten zu zu greifen.
Hierbei wird dies aber nicht auffallen, da mit jedem Byte das gleich gemacht wird. Aus diesem Grund könntest du auch gleich mit einem PByte arbeiten.

Phantom1 26. Jan 2008 18:42

Re: Ein Bild mit einer Farbe multiplizieren?
 
Zitat:

Zitat von Muetze1
Du beachtest nicht das padding zwischen den einzelnen ScanLines! Jede ScanLine ist 32 Bit aligned und da du mit 24 bpp arbeitest ist nur jeder 4. Pixel 32 bit aligned und somit hast du eine große Chance auf falsche Pixeldaten zu zu greifen.
Hierbei wird dies aber nicht auffallen, da mit jedem Byte das gleich gemacht wird. Aus diesem Grund könntest du auch gleich mit einem PByte arbeiten.

Oh stimmt, da ich sonst immer mit 32bit arbeite hab ich jetzt im moment garnicht daran gedacht...

Hier die korrigierte Version:
Delphi-Quellcode:
procedure Multi(src: TBitmap; r, g, b, Intensiv: Byte);
var
  P: PRGBTriple;
  x, y: integer;
begin
  if src.PixelFormat<>pf24bit then
    src.PixelFormat:=pf24bit;

  for y:=0 to src.Height-1 do begin
    P:=src.scanline[y];
    for x:=0 to src.Width-1 do begin
      P.rgbtBlue := (P.rgbtBlue shl 8 * not Intensiv + P.rgbtBlue * Succ(b) * Intensiv) shr 16;
      P.rgbtGreen := (P.rgbtGreen shl 8 * not Intensiv + P.rgbtGreen * Succ(g) * Intensiv) shr 16;
      P.rgbtRed  := (P.rgbtRed  shl 8 * not Intensiv + P.rgbtRed  * Succ(r) * Intensiv) shr 16;
      Inc(P);
    end;
  end;
end;

Muetze1 26. Jan 2008 18:47

Re: Ein Bild mit einer Farbe multiplizieren?
 
Wie gesagt: der Code funktioniert auch in der vorherigen Version, da du mit jedem Byte die selbe Berechnung machst und weil die Padding Bytes auch einfach mit umgerechnet werden - aber da die nicht genutzt werden, ist das somit ohne Bedeutung.

Phantom1 26. Jan 2008 21:53

Re: Ein Bild mit einer Farbe multiplizieren?
 
Zitat:

Zitat von Muetze1
Wie gesagt: der Code funktioniert auch in der vorherigen Version, da du mit jedem Byte die selbe Berechnung machst und weil die Padding Bytes auch einfach mit umgerechnet werden - aber da die nicht genutzt werden, ist das somit ohne Bedeutung.

Doch es können Bild-Fehler im obigen code entstehen. Es werden zwar diese "nutzlosen" Bytes auch umgerechnet (was eigentlich nichts macht), jedoch fehlen dann zum schluß genau diese anzahl an bytes bzw pixel zur umrechnung. Je nach größe des Bildes bleiben dann viele Pixel unbearbeitet.

Muetze1 26. Jan 2008 23:18

Re: Ein Bild mit einer Farbe multiplizieren?
 
Zitat:

Zitat von Phantom1
Doch es können Bild-Fehler im obigen code entstehen. Es werden zwar diese "nutzlosen" Bytes auch umgerechnet (was eigentlich nichts macht), jedoch fehlen dann zum schluß genau diese anzahl an bytes bzw pixel zur umrechnung. Je nach größe des Bildes bleiben dann viele Pixel unbearbeitet.

Aso, stümmt, das hatte ich nicht bedacht.

Cyberstorm 27. Jan 2008 21:28

Re: Ein Bild mit einer Farbe multiplizieren?
 
vielen dank! aber der spass mit dem einfärben ist leider nicht wirklich zeitfressend.

optimiert lieber die hauptschleife hier :-) (die braucht über ne stunde für alle 160.000 bilder trotz 4x3Ghz) :P.
also allgemein geht es darum, dass ich ein mosaikbild errechne. dafür habe ich testpunkte, die ich mit teilen des originalbildes vergleiche. das ganze passiert in 4 threads --> 4 kataloge, weil quad core

bin offen für jede form von kritik!:

Delphi-Quellcode:
const
  TestPointsX = 56;
  TestPointsY = 42;
  MaxInt64 = Int64($7FFFFFFFFFFFFFFF);
  BELOW_NORMAL_PRIORITY_CLASS = $00004000;

type
  TRGB = record
    Blue: Byte;
    Green: Byte;
    Red: Byte;
  end;

  PRGB = ^TRGB;

  TRefPoints = array[0..TestPointsX-1, 0..TestPointsY-1] of TRGB;

  TPicInfoEntry = record
    FileLocation: string;
    Used: Boolean;
    RefPoints: TRefPoints;
  end;

  TCatalogue = record
    PicInfoList: array of TPicInfoEntry;
    Count: Integer;
  end;

  TImageTableEntry = record
    FileName: string;
    Match: Int64;
    CatThreadAddID: Byte;
    PicID: Integer;
    Avg: TRGB;
  end;

  TRndFillGrid = record
     ImgDone: array of Boolean;
     PicsLeft: Integer;
  end;

  TImageCompareThread = class(TThread)
    private
      procedure DrawStatus;
    protected
      procedure Execute; override;
    public
      CatID: Byte;
      SourcePic: array of TRefPoints;
      RndFillGrid: TRndFillGrid;
      B: TBitmap;
      P: PRGB;
      Terminating: Bool;
      constructor Create(CatalogID: Byte); virtual;
  end;


var
  ImageTable: array of TImageTableEntry;
  cs: TRTLCriticalSection;
  ImageCompareThread: array[1..4] of TImageCompareThread;
  Catalogs: array[1..4] of TCatalogue;
  ThreadReady: array[1..4] of Boolean;

procedure TImageCompareThread.Execute;
var
  i, j, k, m: Integer;
  Match: Int64;
begin
  SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_BELOW_NORMAL);
  {$IFDEF NO_RANDOM_FILL}
   for m:=0 to Length(SourcePic)-1 do
     begin
  {$ELSE}
   while RndFillGrid.PicsLeft>0 do
     begin
       m:=-1;
       while m=-1 do
         begin
           m:=Random(2350);
           if RndFillGrid.ImgDone[m] then m:=-1
            else
             begin
               Dec(RndFillGrid.PicsLeft);
               RndFillGrid.ImgDone[m]:=True;
               Synchronize(DrawStatus);
             end;
         end;
      {$ENDIF}
      if Terminating then
        begin
          self.Terminate;
          exit;
        end;
      EnterCriticalSection(cs);
      if ImageTable[m].FileName='' then ImageTable[m].Match:=MaxInt64;
      LeaveCriticalSection(cs);
      for i:=0 to Catalogs[CatID].Count-1 do
        begin
          Match:=0;
          for j:=0 to TestPointsX-1 do
           for k:=0 to TestPointsY-1 do
            begin //die nächsten drei zeilen werden verdammt oft durchgegangen...
              Inc(Match, Abs(Catalogs[CatID].PicInfoList[i].RefPoints[j, k].Blue - SourcePic[m, j, k].Blue));
              Inc(Match, Abs(Catalogs[CatID].PicInfoList[i].RefPoints[j, k].Green - SourcePic[m, j, k].Green));
              Inc(Match, Abs(Catalogs[CatID].PicInfoList[i].RefPoints[j, k].Red - SourcePic[m, j, k].Red));
            end;
          EnterCriticalSection(cs);
          if (Match < ImageTable[m].Match) and (Catalogs[CatID].PicInfoList[i].Used <> True) then
            begin
              if ImageTable[m].FileName<>''
               then Catalogs[ImageTable[m].CatThreadAddID].PicInfoList[ImageTable[m].PicID].Used:=False;
              ImageTable[m].CatThreadAddID:=CatID;
              ImageTable[m].PicID:=i;
              ImageTable[m].Match:=Match;
              ImageTable[m].FileName:=Catalogs[CatID].PicInfoList[i].FileLocation;
              Catalogs[CatID].PicInfoList[i].Used:=True;
            end;
          LeaveCriticalSection(cs);
        end;
    end;
  EnterCriticalSection(cs);
  ThreadReady[CatID]:=True;
  LeaveCriticalSection(cs);
end;

Lossy eX 28. Jan 2008 09:03

Re: Ein Bild mit einer Farbe multiplizieren?
 
Erst mal was einfaches, was keinen Einfluss auf die Geschwindigkeit hat. ;)

Das Int64($7FFFFFFFFFFFFFFF); geht auch einfacher und ohne Magic Number High(Int64);

Das Record TRGB ist nicht packed. Wenn du Alignment aktiviert hast, was standard der Fall ist, dann ist es in Wirklichkeit 4 Byte groß. Also für Dateien oder dierkten Speicherzugriff nur mit Vorsicht zu genießen.

Zu dem Algirithmus: Die Beste Optimierung ist, unnötige Dinge gar nicht erst auszuführen. So solltest du dir gut überlegen wie du den Code so umstellen kannst, dass keine doppelte Arbeit statt findet. Du vergleichst ein Bild mit allen anderen Bildern? Sehe ich das Richtig? Wenn ja, dann kannst du einiges an Zeit sparen, wenn du das aktuelle Bild nur mit den nachfolgenden Vergleichst. Kleines Beispiel mit 3 Bildern. Du vergleichst 1 mit 2 dann 1 mit 3. Wenn du jetzt 2 vergleichen willst, dann brauchst du es mit 1 nicht mehr vergleichen. Denn das wurde bereits bei dem ersten Bild verglichen. Also Musst du es nur noch mit 3 vergleichen. Sofern mein Kaffee heute schon ausreichend dosiert wurde. ;)

Dann solltest du dir evtl mal in der CPU Ansicht anschauen was der Kompiler aus deiner Schleife gemacht hat. Delphi optimiert sicher einiges aber ich denke [i]Catalogs[CatID].PicInfoList.RefPoints[j, k]. wird er nicht hin bekommen. Der erste Teil dieser Zeile verändert sich nicht. Da solltest du entweder mit with [i]Catalogs[CatID].PicInfoList do arbeiten oder dir einen Pointer auf die Objekte holen.

Aber ich denke du solltest dir auch mal anschauen wo die meiste Zeit drauf geht. Also entweder über den High Performance Counter messen welche ausgewählt stelle wie viel Zeit benötigt. Oder mit einem Profiler (z.B.: aqTime) mal schauen. Von aqTime gibt es eine 30 Tage Testversion. Allerings wäre es da evtl auch ganz interessant zu sehen wie häufig das ein oder andere aufgerufen wird. Das geht aber nicht wenn alles in einer Methode ist. Da dann evtl mal kurzzeitig auslagern etc.

PS: Könnte es etwas bringen die AffinityMask der Threads entsprechend zu setzen? Denn sonst springen die Threads zwischen den Kernen hin und her. Evtl entlastet das auch deren Cache.

PPS: Gehört diese Frage nicht auch eher in ein neues Thema??


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz