IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

problème avec scanline


Sujet :

Delphi

  1. #1
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut problème avec scanline
    Voilà, j'ai essayé de faire un filtre rouge avec scanline sauf que ça ne marche pas. Pourquoi?

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, ExtDlgs;
     
    type
      TRGBArray = array[0..10000] of TRGBTriple;
      pTRGBArray =^TRGBArray;
      TForm1 = class(TForm)
        Image1: TImage;
        procedure FormCreate(Sender: TObject);
        procedure FormPaint(Sender: TObject);
      private
        { Déclarations privées }
        bmp : TBitmap;
        procedure FiltreRouge;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      bmp:=TBitmap.Create;
      Position:=PoScreenCenter;
      Height:=Image1.Picture.Height;
      Width:=Image1.Picture.Width;
      With bmp do
      begin
        Width:=Self.Width;
        Height:=self.Height;
      end;
    end;
     
    procedure TForm1.FormPaint(Sender: TObject);
    begin
      bmp.Assign(Image1.Picture.Bitmap);
      FiltreRouge;
      Canvas.Draw(0,0,bmp);
    end;
     
    procedure TForm1.FiltreRouge;
    var bitmap : TBitmap;
        x,y : integer;
        P : pTRGBArray;
    begin
      bitmap:=TBitmap.Create;
      With bitmap do
      begin
        Assign(Bmp);
        PixelFormat:=pf24Bit;
      end;
      For x:=0 to bitmap.Height-1 do
      begin
        P:=bitmap.ScanLine[x];
      end;
      For y:=0 to bitmap.Width-1 do
      begin
        P[y].rgbtBlue:=0;
        P[y].rgbtGreen:=0;
      end;
      Bmp.Assign(bitmap);
      bitmap.Free;
    end;
     
    end.
    Merci d'avance pour vos réponses.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 560
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 560
    Points : 25 156
    Points
    25 156
    Par défaut
    tes boucles ne devraient-elle pas être imbriquées ?
    la tu ne dois changer la dernière ligne de pixel
    Pense que tu ne laisse que le canal rouge, si tu n'as pas bcp de rouge dans ton image, ça sera très sombre

    Voir Utilisation de la propriété TBitMap.ScanLine III-B. Le programme Split

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      For x:=0 to bitmap.Height-1 do
      begin
        P:=bitmap.ScanLine[x];
        For y:=0 to bitmap.Width-1 do
        begin
          P[y].rgbtBlue:=0;
          P[y].rgbtGreen:=0;
        end;
      end;

  3. #3
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Voiçi une routine qui supprime n'importe quelle(s) composante(s) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    procedure SupprComposantesRGB_V1(Bmp : tBitMap; RGB : tStr3);
    type     pLigScan = ^tLigScan;
             tLigScan = array[Word] of TRGBTriple;
    var       x,y : Integer; Lig : pLigScan;
    begin     if (bmp=nil) or (RGB='') then EXIT;
              BMP.PixelFormat:=pf24bit;
              RGB:=UpperCase(RGB);
    
              if pos('R',RGB)>0 then begin // Supression des Rouges
                 for y:=0 to bmp.height-1 do begin
                     Lig := Bmp.ScanLine[y];
                     for x :=0 to bmp.Width-1 do Lig[x].rgbtRed:=0;
                 end;
              end;
              if pos('G',RGB)>0 then begin // Supression des Verts
                 for y:=0 to bmp.height-1 do begin
                     Lig := Bmp.ScanLine[y];
                     for x :=0 to bmp.Width-1 do Lig[x].rgbtGreen:=0;
                 end;
              end;
              if pos('B',RGB)>0 then begin // Supression des Bleus
                 for y:=0 to bmp.height-1 do begin
                     Lig := Bmp.ScanLine[y];
                     for x :=0 to bmp.Width-1 do Lig[x].rgbtBlue:=0;
                 end;
              end;
    end;
    A+.

  4. #4
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    Merci beaucoup pour la rapidité vos réponses!!!
    Le pire, c'est que j'ai trouvé la solution le lendemain de l'envoi du message!
    Merci également pour le tuto qui est super intéressant et pour la routine qui est bien plus technique mais qui est beaucoup mieux que ma pauvre procedure(que j'ai copié sur un tuto!!).
    Avec tout ça,je pense commencer à comprendre le fonctionnement de scanline!

  5. #5
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Basile le disciple :
    Merci également pour le tuto qui est super intéressant et pour la routine qui est bien plus technique mais qui est beaucoup mieux que ma pauvre procedure
    ... De rien, mais attention ma routine n'est pas optimisée si on supprime deux composantes elle scanne les Scanlines deux fois il est donc possible de multiplier sa vitesse d'exec par presque 2 (vu qu'il n'y a aucun intérêt à vouloir en supprimer trois sinon on la multiplierait par presque 3 : lol).

    A+.

  6. #6
    Membre actif Avatar de Basile le disciple
    Homme Profil pro
    étudiant Centrale Supélec
    Inscrit en
    Avril 2013
    Messages
    147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : étudiant Centrale Supélec

    Informations forums :
    Inscription : Avril 2013
    Messages : 147
    Points : 279
    Points
    279
    Par défaut
    Merci pour l'info.
    Vous m'encouragez vraiment à continuer ce formidable outil qu'est scanline !!

  7. #7
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Tiens pour t'encourager davantage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    type tComposantes = set of Char;
    
    procedure SupprComposantesRGB_V2(Bmp: tBitMap; RGB: tComposantes);
    var x, y: Integer; Bpp, Scan0, Tl, P: integer;
    begin if (bmp = nil) or (RGB = []) then EXIT;
      BMP.PixelFormat := pf24bit;
      Bpp := 3; // 3 bytes par Pixel pour pf24bit
      Scan0 := Integer(Bmp.ScanLine[0]); // On pointe le début du Bmp
      Tl := Integer(Bmp.ScanLine[1]) - Scan0; // Taille d'une ligne
      for y := 0 to bmp.height - 1 do begin
        for x := 0 to bmp.Width - 1 do begin
          P := Scan0 + y * Tl + x * bpp; // Position du pointeur courant
          if ('r' in RGB) or ('R' in RGB) then PRGBTriple(P)^.rgbtRed := 0;
          if ('g' in RGB) or ('G' in RGB) then PRGBTriple(P)^.rgbtGreen := 0;
          if ('b' in RGB) or ('B' in RGB) then PRGBTriple(P)^.rgbtBlue := 0;
        end;
      end;
    end;
    A+.

  8. #8
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 753
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 338
    Points
    13 338
    Par défaut
    Bmp.ScanLine[0] est visuellement le pixel en haut à gauche de l'image, mais en mémoire, il correspond à la taille de l'image moins une ligne. Le premier pixel se trouve effectivement à Bmp.ScanLine[Bmp.Height -1] (tête en bas).
    En définissant correctement le premier pixel, il est possible de n'utiliser qu'une boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pRGB := Bmp.ScanLine[Bmp.Height -1];
    for i := 0 to Bmp.Width *Bmp.Height -1 do
    On voit également de tout dans la déclaration du tableau de pixels. Deux exemples dans ce sujet :
    array[0..10000] of TRGBTriple et array[word] of TRGBTriple. A partir du moment ou la taille est de toute façon fausse, autant ne pas en donner ! Il est à mon sens plus lisible de l'écrire array[0..0] of TRGBTriple. Le seul but de cette déclaration étant d'avertir le compilateur qu'on pointe sur un tableau statique

  9. #9
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Andnotor :
    En définissant correctement le premier pixel, il est possible de n'utiliser qu'une boucle
    OK, bien vu.

    Voici donc deux versions V3 et V4 basées sur ce principe :

    A) Version V3 avec RGB du type tComposantes = set of Char;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    procedure SupprComposantesRGB_V3(Bmp: tBitMap; RGB: tComposantes);
    var i: Integer; Pix: PRGBTriple; SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) or (RGB = []) then EXIT;
     
      SupR:=('r' in RGB) or ('R' in RGB);
      SupG:=('g' in RGB) or ('G' in RGB);
      SupB:=('b' in RGB) or ('B' in RGB);
     
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
     
      for i := 0 to BMP.Width * BMP.height - 1 do begin
        if SupR then Pix^.rgbtRed := 0;
        if SupG then Pix^.rgbtGreen := 0;
        if SupB then Pix^.rgbtBlue := 0;
        Inc(Pix);
      end;
    end;
    B) Version V4 avec RGB du type tStr3 = string[3];

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    procedure SupprComposantesRGB_V4(Bmp: tBitMap; RGB: tStr3); 
    var i: Integer; Pix: PRGBTriple; SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) or (RGB = '') then EXIT;
     
      RGB:=UpperCase(RGB);
      SupR:=pos('R',RGB)>0;
      SupG:=pos('G',RGB)>0;
      SupB:=pos('B',RGB)>0;
     
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
     
      for i := 0 to BMP.Width * BMP.height - 1 do begin
        if SupR then Pix^.rgbtRed := 0;
        if SupG then Pix^.rgbtGreen := 0;
        if SupB then Pix^.rgbtBlue := 0;
        Inc(Pix);
      end;
    end;
    C) Code utilisé pour les tests de speed :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    procedure TForm1.Button1Click(Sender: TObject);
    var bmp: tBitMap; GTC : DWord; i,nbTours : integer;
    begin
      bmp := tBitMap.Create;
      with bmp do begin
        width := 1000; height := 1000; PixelFormat := pf24bit;
      end;
     
      with bmp.Canvas do begin
        brush.Color := clWhite;
        FillRect(ClipRect);
      end;
     
      nbTours:=1000;
      GTC:=GetTickCount;
      for i:=1 to nbTours
      do //SupprComposanteRGB_V1(Bmp,'rg'); // mis : 1654 ms, mis : 1638 ms, mis : 1622 ms
         //SupprComposantesRGB_V2(Bmp, ['r', 'g']); // mis : 1732 ms, mis : 1700 ms, mis : 1716 ms
         //SupprComposantesRGB_V3(Bmp, ['r', 'g']); // mis : 1061 ms, mis : 1046 ms, mis : 1061 ms
         SupprComposantesRGB_V4(Bmp, 'rg'); // mis : 1045 ms, mis : 1029 ms, mis : 1029 ms.
      Memo1.lines.Add('mis : '+intToStr(GetTickCount-GTC)+' ms');
      image1.Picture.Bitmap := Bmp;
      bmp.Free;
    end;
    D) Résultats des tests pour 1000 fois la suppression des composantes R et G dans un bitmap de 1000x1000 pixels, (moyennes de 3 essais consécutifs pour chaque routine) :

    - Avec SupprComposantesRGB_V1(Bmp,'rg') : mis 1638 ms
    - Avec SupprComposantesRGB_V2(Bmp, ['r', 'g']) : mis 1716 ms
    - Avec SupprComposantesRGB_V3(Bmp, ['r', 'g']) : mis 1056 ms
    - Avec SupprComposantesRGB_V4(Bmp, 'rg') : mis : 1034 ms.

    Le 1er résultat est surprenant car la version _V1 scanne le bmp 2 fois pour supprimer les deux composantes !!!???

    On comprend mieux que la version V3 à boucle unique soit 1,625 fois plus rapide que la V2 puisque la V2 est en plus ralentie notamment par le calcul de P := Scan0 + y * Tl + x * bpp; situé en plein dans la boucle la plus imbriquée.

    Et la version V4 avec RGB du type tStr3 = string[3] est née par simple curiosité et puisqu'elle est un chouilla plus rapide que la V3 avec son Set Of char autant en profiter.

    A+.

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 753
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 338
    Points
    13 338
    Par défaut
    Il faudrait aussi revoir les paramètres. Passer par une chaîne et des if n'est pas top :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    procedure SupprComposantesRGB(aBmp: TBitmap; aMask: TRGBTriple);
     
    Pix^.rgbtRed := Pix^.rgbtRed and aMask.rgbtRed;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    procedure SupprComposantesRGB(aBmp: TBitmap; R, G, B :byte);
     
    Pix^.rgbtRed := Pix^.rgbtRed and R;

  11. #11
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Andnotor :
    Passer par une chaîne et des if n'est pas top
    Voici la version V5 qui tient compte de cette remarque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure SupprComposantesRGB_V5(Bmp: TBitmap; R, G, B : byte);
    var i: Integer; Pix: PRGBTriple; SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) then EXIT;
     
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
     
      for i := 0 to BMP.Width * BMP.height - 1 do begin
        Pix^.rgbtRed := Pix^.rgbtRed and R;
        Pix^.rgbtGreen := Pix^.rgbtGreen and G;
        Pix^.rgbtBlue := Pix^.rgbtBlue and B;
        Inc(Pix);
      end;
    end;
    Résultats dans les mêmes conditions de tests que celles de mon message de 11h44:

    - Avec SupprComposantesRGB_V5(Bmp, 0, 0, 255); mis : 1342 ms, mis : 1342 ms, mis : 1326 ms, soit une en moyenne 1337 ms contre les 1034 ms avec SupprComposantesRGB_V4(Bmp, 'rg') de 11h44
    ... donc passer par une chaîne et des if s'avère un peu plus rapide alors que la suggestion allait dans le sens d'une simplification : dommage pou la V5.

    A+.

  12. #12
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Et voici la V6 avec R, G, B directement de type boolean, version simplifiée de la V4 ce qui fait gagner les quatre lignes suivantes de la V4:
    RGB:=UpperCase(RGB);
    SupR:=pos('R',RGB)>0;
    SupG:=pos('G',RGB)>0;
    SupB:=pos('B',RGB)>0;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure SupprComposantesRGB_V6(Bmp: TBitmap; R, G, B : boolean);
    var i: Integer; Pix: PRGBTriple; SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) then EXIT;
    
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
    
      for i := 0 to BMP.Width * BMP.height - 1 do begin
        if R then Pix^.rgbtRed:=0;
        if G then Pix^.rgbtGreen:=0;
        if B then Pix^.rgbtBlue:=0;
        Inc(Pix);
      end;
    end;
    A) Résultats dans les mêmes conditions de tests que celles de mes message précédents :

    - Avec SupprComposantesRGB_V6(Bmp, TRUE, TRUE, FALSE); // mis : 1045 ms, mis : 1030 ms, mis : 1046 ms : soit en moyenne 1040 ms contre les 1034 ms avec SupprComposantesRGB_V4(Bmp, 'rg')

    B) Résultats pour la suppression de R et G 100 fois sur un bmp de 10000x10000 :
    - Avec SupprComposantesRGB_V4(Bmp, 'rg') : mis en moyenne 10561 ms
    - Avec SupprComposantesRGB_V6(Bmp, TRUE, TRUE, FALSE) : mis en moyenne 10562 ms
    ... donc résultats à peu près kif-kif mais V6 plus simple que V4.

    A+.

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 560
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 560
    Points : 25 156
    Points
    25 156
    Par défaut
    Puisque l'on débat sur les perf

    Il manque les variantes const
    SupprComposantesRGB_V4_const(Bmp: tBitMap; const RGB: tStr3);

    Sinon entre Set of Char qui est un TSysCharSet donc 32octets c'est peu lourd pour trois valeurs !
    Comme c'est une paramètre sans marque var ou const il est intégralement recopié à chaque appel !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TRGBTripleFilter = (tfRed, tfGreen, tfBlue);
    TRGBTripleFilters = set of TRGBTripleFilter;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    procedure SupprComposantesRGB_V7(Bmp: tBitMap; const RGB: TRGBTripleFilters);
    var 
      i: Integer; 
      Pix: PRGBTriple; 
      SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) or (RGB = []) then EXIT;
     
      SupR:= tfRed in RGB;
      SupG:= tfGreen in RGB;
      SupB:= tfBlue in RGB;
     
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
     
      for i := 0 to BMP.Width * BMP.height - 1 do
      begin
        if SupR then Pix^.rgbtRed := 0;
        if SupG then Pix^.rgbtGreen := 0;
        if SupB then Pix^.rgbtBlue := 0;
        Inc(Pix);
      end;
    end;
    Que donne comme temps SupprComposantesRGB_V7(Bmp, [tfRed, tfGreen]); ?

  14. #14
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    ShaiLeTroll :
    Il manque les variantes const
    SupprComposantesRGB_V4_const(Bmp: tBitMap; const RGB: tStr3);

    Sinon entre Set of Char qui est un TSysCharSet donc 32octets c'est peu lourd pour trois valeurs !
    Comme c'est une paramètre sans marque var ou const il est intégralement recopié à chaque appel !
    Ok pour le Set of Char, mais bigre j'ai complètement oublié de déclarer la chaine comme constante!!!

    je refais les tests et je reviens.

    A+.

  15. #15
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    1 ) ShaiLeTroll :
    Que donne comme temps SupprComposantesRGB_V7(Bmp, [tfRed, tfGreen]); ?
    Résultats pour la suppression de R et G 100 fois sur un bmp de 10000x10000 :
    - Avec SupprComposantesRGB_V7(Bmp, [tfRed, tfGreen]) : mis : 10499 ms, mis : 10498 ms, mis : 10499 ms, soit en moyenne 10498,7 ms contre les 10562 ms de la V4 et de la V6 donc un facteur de gain de 1,006 ... même un petit gain c'est toujours bon à prendre.

    2) Et avec la V8 que voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure SupprComposantesRGB_V8(Bmp: TBitmap; const R, G, B : boolean); 
    var i: Integer; Pix: PRGBTriple; SupR, SupG, SupB: boolean;
    begin
      if (bmp = nil) then EXIT;
    
      BMP.PixelFormat := pf24bit;
      Pix := Bmp.ScanLine[bmp.height - 1];
    
      for i := 0 to BMP.Width * BMP.height - 1 do begin
        if R then Pix^.rgbtRed:=0;
        if G then Pix^.rgbtGreen:=0;
        if B then Pix^.rgbtBlue:=0;
        Inc(Pix);
      end;
    end;
    Résultats pour la suppression de R et G 100 fois sur un bmp de 10000x10000 :
    - Avec SupprComposantesRGB_V8(Bmp, TRUE, TRUE, FALSE); mis : 10437 ms, mis : 10312 ms, mis : 10327 ms : soit en moyenne 10359 ms contre les 10498,7 ms de la V7 : encore un facteur de gain de 1,01.

    Là je ne sais plus où gratter pour gagner en speed.

    A+.

  16. #16
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 753
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 338
    Points
    13 338
    Par défaut
    Essaye encore cette variante sur 32 bits avec un masque unique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    procedure SupprComposantesRGB_V9(aBmp: TBitmap; aMask :TRGBQuad);
    type
      PPixels = ^TPixels;
      TPixels = array[0..0] of dword;
    
    var
      i      :integer;
      Pixels :PPixels;
      Mask   :dword absolute aMask;
    
    begin
      Assert(aBmp <> nil);
    
      aBmp.PixelFormat := pf32bit;
      Pixels := abmp.ScanLine[aBmp.Height -1];
    
      for i := 0 to aBmp.Width *aBmp.Height -1 do
        Pixels[i] := Pixels[i] and Mask;
    end;
    
    //Appel
    const
      RedMask :TRGBQuad = (rgbBlue:$00; rgbGreen:$00; rgbRed:$FF; rgbReserved:$FF);
    
    SupprComposantesRGB(Bmp, RedMask);
    Remarque : const est un paramètre par valeur. Le compilateur l'optimise au niveau des chaînes et structures, mais ça reste par valeur. Seuls var et out sont par adresse

  17. #17
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Andnotor : Essaye encore cette variante sur 32 bits avec un masque unique :
    Résultats pour la suppression de R et G 100 fois sur un bmp de 10000x10000 :
    Avec SupprComposantesRGB_V9(Bmp, RedMask) mis : 10671 ms contre les 10359 ms de la V8 donc pas de gain et en plus le Bmp renvoyé est totalement noir et non Bleu !!!???

    A+.

    EDIT : Ne pas tenir compte des résultats de ce message qui ont été faussés par une erreur de manip ... voir les résultats dans mon message n° #22 plus loin:

  18. #18
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 560
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 560
    Points : 25 156
    Points
    25 156
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Remarque : const est un paramètre par valeur. Le compilateur l'optimise au niveau des chaînes et structures, mais ça reste par valeur. Seuls var et out sont par adresse
    Faudrait vérifier car l'aide est floue à ce sujet

    Les paramètres constante peuvent être transmis à la fonction par valeur ou par référence, selon le compilateur utilisé. Pour obliger le compilateur à transmettre un paramètre constante par référence, vous pouvez utiliser le décorateur [Ref] avec le mot clé const.
    Du coup, on se sait pas si c'est par valeur ou par référence, avec le compilateur actuel, est-ce en fonction de la plateforme, en fonction de l'ASM x86, x64 ou ARM ?

    masque unique
    Faudrait faire attention au BigEndian \ LittleEndian
    le FF de Reserved n'est-il pas avant les autres en X86 (LittleEndian)

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    typedef struct tagRGBTRIPLE {
            BYTE    rgbtBlue;
            BYTE    rgbtGreen;
            BYTE    rgbtRed;
    } RGBTRIPLE...
     
    typedef struct tagRGBQUAD {
            BYTE    rgbBlue;
            BYTE    rgbGreen;
            BYTE    rgbRed;
            BYTE    rgbReserved;
    } RGBQUAD;

    en absolute QUAD<-> DWORD, ou vont les Bytes ?
    En théorie, cela stocke Byte1, Byte2, Byte3 puis Byte4 donc rgbReserved est l'octet de poids poids fort qui est stocké à la fin

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RedMask :TRGBQuad = (rgbBlue:$00; rgbGreen:$00; rgbRed:$FF; rgbReserved:$FF);
    En mémoire, on a 00 00 FF FF si l'on traduit ça en little endian, c'est le nombre FF FF 00 00
    Même principe pour l'unicode 'a' c'est 00 61 pour nous, mais en little endian c'est 61 00 d'où le coup classique du zéro terminal Ansi anticipé lors d'une mauvaise conversion

    Enfin, RGBTriple et RGBQuad ne sont pas compatible en mémoire, ça fait quoi, ça déborde ailleurs ?

  19. #19
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 753
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 338
    Points
    13 338
    Par défaut
    Une nouveauté XE4 et multiplateforme alors

    Un paramètre constante (const) est semblable à une constante locale ou à une variable en lecture seule. Les paramètres constante sont semblables aux paramètres par valeur à cette différence qu'il n'est pas possible d'affecter une valeur à un paramètre constante dans le corps de la routine, ni de le transmettre comme paramètre var à une autre routine. Par contre, si vous transmettez une référence d'objet comme paramètre constante, il est quand même possible de modifier les propriétés de l'objet.

    L'utilisation de const permet au compilateur d'optimiser le code pour les paramètres de type structuré ou chaîne. Cela évite aussi de transmettre involontairement par adresse le paramètre à une autre routine.
    @Gilbert,

    J'ai pourtant testé

    TRGBQuad vs dword
    Le tableau de pixels est aussi déclaré en dword. Donc pas d'erreur possible...

  20. #20
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 560
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 560
    Points : 25 156
    Points
    25 156
    Par défaut
    ScanLine renvoi un pointeur, son contenu n'est-il pas un multiple de TRGBTriple ?
    Toi tu fais croire que le tableau de TRGBTriple est un tableau de Word ?
    Mais du coup, le nombre d'élément du tableau ne correspond pas entre TripleByte et QuadByte ?

    Là au niveau mémoire, j'y pige plus rien, cela ne modifierait les couleurs 4 canal par 4 canal ?
    RVBR puis BVRB puis VRBV puis RVBR ... et quand ça déborde ça va où ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Scanline et D7 : problème avec l'exemple de l'aide
    Par Jipété dans le forum Débuter
    Réponses: 8
    Dernier message: 31/08/2007, 16h15
  2. VC++ Direct3D8, problème avec LPD3DXFONT et LPD3DTEXTURE8
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 03/08/2002, 11h10
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo