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

Langage Delphi Discussion :

Graphisme : problème de mode de combinaisons de couleurs


Sujet :

Langage Delphi

  1. #61
    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,

    J'ai swapé les couleurs pour alimenter le bitmap en passant de RGB à BGR mais le problème des couleurs reste non résolu.

    Du coup je vais abandonner le canal Alpha et tenter de me débrouiller avec l'idée des couleurs décalées.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 745
    Points : 13 306
    Points
    13 306
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    Je ne comprend pas bien ta remarque...l'usage de layer ne change rien à la donne, si tu appliques deux layers de même couleur en XOR, l'effet s'annule, que ce soit un pixel, une ligne ou un layer n'y change rien.
    Si on reprend l'exemple du polygone, les suites de traits sont dessinées sur un layer (OR). C'est ce résultat qui est fusionné avec l'image de fond (XOR) pour former un 3ième bitmap: l'image finale.

  3. #63
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Si on reprend l'exemple du polygone, les suites de traits sont dessinées sur un layer (OR). C'est ce résultat qui est fusionné avec l'image de fond (XOR) pour former un 3ième bitmap: l'image finale.
    à condition qu'il veuille faire un OR entre les traits...ce qui ne semble pas être le cas.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 745
    Points : 13 306
    Points
    13 306
    Par défaut
    OR = exemple de Polyline.

    La logique serait d'avoir un buffer par forme. Peu importe le traitement qu'on leur fait subir. Le but final étant tout de même de pouvoir les déplacer indépendamment les unes des autres

  5. #65
    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,

    J'ai failli crier "victoire" de façon inopportune car avec l'idée des couleurs décalées je me suis bagarré pour obtenir l'effacement complet dans les zones de croisement et quand je l'ai enfin obtenu je ne m'étais pas aperçu que les couleurs dans les zones de croisements multiples n'étaient pas des clouleurs "pleines" mais du simple NotXor ce qui serait acceptable dans le cas des dessins éphémères lors d'un déplacement et que l'on fige en position et en couleur en mode Copy en fin de déplacement mais mon objectif est de laisser la possibilité de déplacer n'importe quel dessin en NotXor tant que l'ensemble des dessins n'est pas achevé ... je vais encore m'accrocher, et si je n'y arrive pas je réviserai mes objectifs à la baisse ...
    En tous cas je conserverai la possibilité de pouvoir déplacer indépendamment les dessins les uns des autres.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  6. #66
    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,

    Ouf, à force de tâtonner je crois avoir trouvé et en tous cas cela va dans la bonne direction : voici les nouveaux codes :
    - procedure DrawLine5 pour le tracé d'une droite,
    - procedure BmpAlpha( BMP : TBitMap; Alpha : byte) pour basculer le canal Alpha du BitMap de 0 à $FF ou inversement :
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    type tTraceMode = (tmAffiche,tmEfface,tmXOR,tmCopy);
     
    procedure DrawLine5( BMP : TBitMap; xo,yo,xe,ye, epTrait : integer; CoulPen : TColor; TraceMode : tTraceMode; BoutsRonds : boolean);
    type      PCardinal = ^Cardinal;
    var       Theta,miEp,si,co,mis,mic,
              ep,x,y,dx,dy,xo1,yo1,xe1,ye1,xo2,yo2,xe2,ye2,xorMin,xerMax,yorMin,yerMax,rr,d,u : Extended;
              ap,bp,ad,bds,bdi,bdg,bdd : Extended;
              iy,ix,iyp,ixp,yoMin,yeMax,xoMin,xeMax,r,i,j,xoc,xec,yoc,yec : integer;
              // Le BitMap :
              W,H     : integer;
              Scan0   : Integer;       //Valeur du pointeur d'entrée dans le Bitmap.
              Scan    : Integer;       //Pointeur temporaire destiné à être incrémenté.
              MLS     : Integer;       //Memory Line Size (en bytes) du Bitmap.
              Bpp     : Integer;       //Byte per pixel du Bitmap.
              PixMin,PixMax : Integer; //Bornes de l'intervalle d'appartenance du pointeur au BitMap
              pCoulPen: TRGBQuad;      //Pointe sur la couleur du crayon
              ymin1,ymax1,ymin2,ymax2,ymin,ymax : integer;
              lignes    : array of record xmin, xmax: Integer; end; // Le contour
              Q         : byte;        // Les quadrants
     
              procedure GSPixel;
              begin     Scan := Scan0;
                        Inc(Scan, iy*MLS + ix*Bpp);
                        if not ((Scan>=PixMin) and (Scan<=PixMax)) then EXIT; // Si on se trouve en-dehors de la mem du BMP
                        if not ((ix>=0) and (iy>=0) and (ix<=W-1) and (iy<=H-1)) then EXIT; // Si la droite dépasse les bords du Bmp
                        case TraceMode of
                             tmAffiche : if PRGBQuad(scan)^.rgbReserved = 0 then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmEfface  : if PRGBQuad(scan)^.rgbReserved = $FF then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmXOR     : PCardinal(scan)^ :=  PCardinal(scan)^ XOR coulPen;
                             else PRGBQuad(Scan)^:=pCoulPen; //<- pmCopy (utilisé uniquement lors d'un appel pour un tracé de finition)
                        end;
              end; // GSPixel
     
              procedure Rond(xc,yc,R : integer); // Embouts arrondis
              var       x,y : integer; e,u : Extended;
              begin     for y:=yc-R to yc+R do begin
                            e:=y-(yc-R); u:=sqrt(sqr(R)-sqr(R-e)); iy:=y;
                            for x:=xc-floor(u) to xc+floor(u) do begin ix:=x; GSPixel; end;
                        end;
              end;
     
    begin     // INITIALISATION DES VARIABLES :
              BMP.PixelFormat:=pf32bit; Bpp:=4; //<- vu que le code est du 32 bit pour le canal Alpha (si pf24bit alors Bpp:=3)
              with pCoulPen do begin
                   pCoulPen.rgbBlue :=GetBValue(CoulPen);
                   pCoulPen.rgbGreen:=GetGValue(CoulPen);
                   pCoulPen.rgbRed  :=GetRValue(CoulPen);
              end;
              case TraceMode of
                   tmAffiche, tmEfface : CoulPen:=RGB(GetBValue(CoulPen),GetGValue(CoulPen),GetRValue(CoulPen)); //<- on passe de RGB à BGR
              end;
     
              Scan0 := Integer(BMP.ScanLine[0]);
              MLS   := Integer(BMP.ScanLine[1]) - Scan0; //Memory Line Size
              W     := BMP.Width ;
              H     := BMP.Height;
              Bpp   := Abs(MLS div W);
              if Integer(BMP.ScanLine[H-1]) < Scan0 then begin  //Si c'est un  Bottom-Up DIB...
    	     PixMin := Integer(BMP.ScanLine[H-1]);
      	     PixMax := Scan0 + Bpp*W - Bpp;
              end else begin //sinon c'est un Top-Down DIB...
      	      PixMin := Scan0;
                  PixMax :=Integer(BMP.ScanLine[H-1]) + Bpp*W - Bpp;
              end;
     
              dx:=xe-xo; dy:=ye-yo;
              miep:=epTrait/2; rr:=miEp; ep:=0;
              if dx=0 then // Verticale
              begin if epTrait=1 then miep:=0;
                    xo1:=xo - miep; xo2:=xo + miep; yo1:=min(yo,ye); ye1:=max(yo,ye);
                    for ix:=trunc(xo1) to trunc(xo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        yoMin:=trunc(yo1-u); yeMax:=trunc(ye1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for iy:=yoMin to yeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              if ye=yo then // Horizontale
              begin if epTrait=1 then miep:=0;
                    yo1:=yo - miep; yo2:=yo + miep; xo1:=min(xo,xe); xe1:=max(xo,xe);
                    for iy:=trunc(yo1) to trunc(yo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        xoMin:=trunc(xo1-u); xeMax:=trunc(xe1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for ix:=xoMin to xeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              // Droites inclinées
     try
              Theta:=arcTan2(ye-yo,xe-xo);      ad:=tan(Theta); // Pente de l'axe de la droite
              si:=sin(Theta);   co:=cos(Theta); mis:=miep*si;  mic:=miep*co;
              xo1:=xo + mis;    yo1:=yo - mic;  xo2:=xo - mis; yo2:=yo + mic;
              xe1:=xe + mis;    ye1:=ye - mic;  xe2:=xe - mis; ye2:=ye + mic;
              dy:=abs(ye-yo);   dx:=abs(xe-xo);
              Q:=0;
              if (xe>xo) and (ye<yo) then Q:=1 else // Quadrants
              if (xe<xo) and (ye<yo) then Q:=2 else
              if (xe<xo) and (ye>yo) then Q:=3 else
              if (xe>xo) and (ye>yo) then Q:=4;
              bds:=yo1 - ad*xo1;   // Ordonnée à l'origine du bord supérieur
              bdi:=yo2 - ad*xo2;   // Ordonnée à l'origine du bord inférieur
              ap:=-1/ad;           // Pente des petits côtés perpendiculaires
              bdg:=-ap*xo1 + yo1;  // Ordonnée à l'origine du bord gauche
              bdd:=-ap*xe1 + ye1;  // Ordonnée à l'origine du bord droit
              ymin1:=min(round(ye1),round(yo2)); ymax1:=max(round(ye1),round(yo2));
              ymin2:=min(round(ye2),round(yo1)); ymax2:=max(round(ye2),round(yo1));
              ymin :=min(ymin1,ymin2);           ymax :=max(ymax1,ymax2);
              if epTrait>1 then begin
                 SetLength(lignes,ymax-ymin+2); // +2 sinon VA
                 for iy:=Low(lignes) to High(lignes) do begin
                     lignes[iy].xmin:=0; lignes[iy].xmax:=0;
                 end;
                 if BoutsRonds then begin // Embouts arrondis
                    Rond(xo,yo,round(miep)); Rond(xe,ye,round(miep));
                 end;
              end;
              if dy>=dx then // Droites très inclinées par rapport à l'horizontale
              begin // Les xmin et xmax :
                    yoMin:=round(min(yo1,ye1)); yeMax:=round(max(yo1,ye1));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bds)/ad; ix:=round(x);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    xoMin:=round(min(xo1,xo2)); xeMax:=round(max(xo1,xo2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:=ap*ix + bdg; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    yoMin:=round(min(yo2,ye2)); yeMax:=round(max(yo2,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdi)/ad; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    xoMin:=round(min(xe1,xe2)); xeMax:=round(max(xe1,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ap*ix + bdd; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do  for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
                    EXIT;
              end else // Droites inclinées à moins de 45° par rapport à l'horizontale
              begin // Les xmin et xmax :
                    xoMin:=round(min(xo1,xe1)); xeMax:=round(max(xo1,xe1));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bds; iy:=round(y);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    yoMin:=round(min(yo1,yo2)); yeMax:=round(max(yo1,yo2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdg)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    xoMin:=round(min(xo2,xe2)); xeMax:=round(max(xo2,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bdi; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    yoMin:=round(min(ye1,ye2)); yeMax:=round(max(ye1,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdd)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
              end;
      except
      end;
    end; // DrawLine5
     
    procedure BmpAlpha( BMP : TBitMap; Alpha : byte);
    //        Mise à Alpha = 0 ou Alpha = $FF du canal Alpha du BMP
    type      PCardinal = ^Cardinal;
    var       iy,ix : integer;
              // Le BitMap :
              W,H     : integer;
              Scan0   : Integer;       //Valeur du pointeur d'entrée dans le Bitmap.
              Scan    : Integer;       //Pointeur temporaire destiné à être incrémenté.
              MLS     : Integer;       //Memory Line Size (en bytes) du Bitmap.
              Bpp     : Integer;       //Byte per pixel du Bitmap.
              PixMin,PixMax : Integer; //Bornes de l'intervalle d'appartenance du pointeur au BitMap
     
              procedure GSPixelAlpha;
              begin     Scan := Scan0;
                        Inc(Scan, iy*MLS + ix*Bpp);
                        if ((Scan>=PixMin) and (Scan<=PixMax)) then // Si on se trouve dans la mem du BMP
                        PRGBQuad(scan)^.rgbReserved:=Alpha; //<- Alpha à 0 ou à $FF
              end;
     
    begin     // INITIALISATION DES VARIABLES :
              BMP.PixelFormat:=pf32bit; Bpp:=4; //<- vu que le code est du 32 bit pour le canal Alpha (si pf24bit alors Bpp:=3)
              Scan0 := Integer(BMP.ScanLine[0]);
              MLS   := Integer(BMP.ScanLine[1]) - Scan0; //Memory Line Size
              W     := BMP.Width ;
              H     := BMP.Height;
              Bpp   := Abs(MLS div W);
              if Integer(BMP.ScanLine[H-1]) < Scan0 then begin  //Si c'est un  Bottom-Up DIB...
    	     PixMin := Integer(BMP.ScanLine[H-1]);
      	     PixMax := Scan0 + Bpp*W - Bpp;
              end else begin //sinon c'est un Top-Down DIB...
      	      PixMin := Scan0;
                  PixMax :=Integer(BMP.ScanLine[H-1]) + Bpp*W - Bpp;
              end;
              for iy:=0 to H-1 do begin
                  for ix:=0 to W-1 do GSPixelAlpha;
              end;
    end; // BMPAlpha
    Code utilisé pour les tests :

    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
    var TraceMode : tTraceMode;
     
    procedure TfrmGen.SpeedButton3Click(Sender: TObject);
    var       i,RayI,RayE,xc,yc,xo,yo,xe,ye : integer;
    begin     if TraceMode=tmEfface then TraceMode:=tmAffiche else TraceMode:=tmEfface;
              //TraceMode:=tmCopy; //tmXor
              BMPSource.pixelFormat:=pf32bit;
     
              xc:=300; yc:=300; RayI:=100; RayE:=200;
              for i:=0 to 35 do begin
                  xo:=round(xc+RayI*cos(DegToRad(i*10)));
                  yo:=round(yc+RayI*sin(DegToRad(i*10)));
                  xe:=round(xc+RayE*cos(DegToRad(i*10)));
                  ye:=round(yc+RayE*sin(DegToRad(i*10)));
                  DrawLine5(BMPSource,xo,yo,xe,ye, 16, PalArc[i*10], TraceMode, True);
                  if TraceMode=tmAffiche then BmpAlpha(BMPSource,0)
                                         else BmpAlpha(BMPSource,$FF);
              end;
     
              xc:=110; yc:=150;
     
              DrawLine5(BMPSource,xc-40,yc+50,xc+40,yc-50, 40, clBlue, TraceMode, False);
              DrawLine5(BMPSource,xc-40,yc-50,xc+40,yc+50, 40, clBlue, TraceMode, False);
              DrawLine5(BMPSource,xc-70,yc,xc+70,yc,       40, clBlue, TraceMode, True);
     
              with BmpSource.canvas do begin
                   font.color:=clBlack; brush.color:=clWhite; brush.style:=bsSolid;
                   if TraceMode=tmAffiche then textOut(xc-60,yc-130,'Mode Affiche..');
                   if TraceMode=tmEfface  then textOut(xc-60,yc-130,'Mode Efface...');
              end;
     
             Image1.Picture.bitmap.Assign(bmpSource);
              Image1.Repaint;
    end;
    Les *.jpg ci-après montrent que si on ne bascule pas le canal Alpha à 0 après un tracé d'affichage (cas de la croix bleue : voir code du test) le déplacement du trèfle par dessus celle ci en modifie la couleur alors que le fait d'avoir basculé le canal à 0 après l'affichage de la rosace le déplacement du trèfle par dessus la rosace n'en altère pas les couleurs.

    A noter que ceci marche marche sans utiliser de BitMap intermédiaire mais pour l'instant il faut accepter le léger ralentissement nécessité par la mis à 0 du canal Alpha après chaque affichage (pour l'instant je balaye à cet effet la totalité du BitMap au lieu de ne repasser que par dessus les pixels modifiés par le tracé).

    A+.
    Images attachées Images attachées   
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  7. #67
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    pour ce qui est de la lenteur du canal alpha...au risque de me répéter (si si reprend le début de la conversation) le Canal Alpha est ici équivalent à un tableau de boolean

    c'est à dire qu'au lieu de tester l'Alpha tu peux tester ce tableau pour [x,y]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if Table[x + Width * y] = False then
      begin
        pixel^ := pixel^ xor color;
        Table[x + Width * y] := True;
      end;
    quel avantage ? c'est qu'un tableau de boolean se vide d'un coup avec un FillChar() ... d'où l'usage d'un tableau à 1 seule dimension et non un Table[x,y] qui ne pourrait être effacé par un FillChar global
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  8. #68
    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,

    Paul TOTH : pour ce qui est de la lenteur du canal alpha...au risque de me répéter (si si reprend le début de la conversation) le Canal Alpha est ici équivalent à un tableau de boolean

    c'est à dire qu'au lieu de tester l'Alpha tu peux tester ce tableau pour [x,y]

    Code :

    if Table[x + Width * y] = False then
    begin
    pixel^ := pixel^ xor color;
    Table[x + Width * y] := True;
    end;
    ... là je n'y comprends rien du fait que tu utilises des noms de variables différents de ceux que j'utilise dans mon code ????
    ... est-ce-que pixel^ correspond à PRGBQuad(scan)^ ???
    ... et color c'est CoulPen ???
    ... et Table[] qui semble âtre un array of boolean je le raccroche comment au PRGBQuad(scan)^.rgbReserved:=0 ou $FF qui est du byte ???

    Par contre entre-temps j'ai modifié le code de DrawLine5 qui devient DrawLine6 comme suit et j'ai déjà gagné en vitesse en ajoutant le paramètre d'appel Alpha et en ne balayant plus la totalité du BitMap mais si ton astuce ci-dessus est plus rapide je veux bien l'essayer
    (DrawLine6 remplace DrawLine5 et BmpAlpha) :
    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    type tTraceMode = (tmAffiche,tmEfface,tmXOR,tmCopy);
    procedure DrawLine6( BMP : TBitMap; xo,yo,xe,ye, epTrait : integer; CoulPen : TColor; TraceMode : tTraceMode; Alpha : integer; BoutsRonds : boolean);
    //        avec Alpha négatif on trace ou on efface et avec Alpha = 0 ou $FF on bascule simplement le canal Alphatype      PCardinal = ^Cardinal;
    var       Theta,miEp,si,co,mis,mic,
              ep,x,y,dx,dy,xo1,yo1,xe1,ye1,xo2,yo2,xe2,ye2,xorMin,xerMax,yorMin,yerMax,rr,d,u : Extended;
              ap,bp,ad,bds,bdi,bdg,bdd : Extended;
              iy,ix,iyp,ixp,yoMin,yeMax,xoMin,xeMax,r,i,j,xoc,xec,yoc,yec : integer;
              // Le BitMap :
              W,H     : integer;
              Scan0   : Integer;       //Valeur du pointeur d'entrée dans le Bitmap.
              Scan    : Integer;       //Pointeur temporaire destiné à être incrémenté.
              MLS     : Integer;       //Memory Line Size (en bytes) du Bitmap.
              Bpp     : Integer;       //Byte per pixel du Bitmap.
              PixMin,PixMax : Integer; //Bornes de l'intervalle d'appartenance du pointeur au BitMap
              pCoulPen: TRGBQuad;      //Pointe sur la couleur du crayon
              ymin1,ymax1,ymin2,ymax2,ymin,ymax : integer;
              lignes    : array of record xmin, xmax: Integer; end; // Le contour
              Q         : byte;        // Les quadrants
    
              procedure GSPixel;
              begin     Scan := Scan0;
                        Inc(Scan, iy*MLS + ix*Bpp);
                        if not ((Scan>=PixMin) and (Scan<=PixMax)) then EXIT; // Si on se trouve en-dehors de la mem du BMP
                        if not ((ix>=0) and (iy>=0) and (ix<=W-1) and (iy<=H-1)) then EXIT; // Si la droite dépasse les bords du Bmp
                        if Alpha>=0 then begin PRGBQuad(scan)^.rgbReserved:=Alpha; EXIT; end; //<< ici on bascule uniquement le canal Alpha                    case TraceMode of
                             tmAffiche : if PRGBQuad(scan)^.rgbReserved = 0 then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmEfface  : if PRGBQuad(scan)^.rgbReserved = $FF then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmXOR     : PCardinal(scan)^ :=  PCardinal(scan)^ XOR coulPen;
                             else PRGBQuad(Scan)^:=pCoulPen; //<- pmCopy (utilisé uniquement lors d'un appel pour un tracé de finition)
                        end;
              end; // GSPixel
    
              procedure Rond(xc,yc,R : integer); // Embouts arrondis
              var       x,y : integer; e,u : Extended;
              begin     for y:=yc-R to yc+R do begin
                            e:=y-(yc-R); u:=sqrt(sqr(R)-sqr(R-e)); iy:=y;
                            for x:=xc-floor(u) to xc+floor(u) do begin ix:=x; GSPixel; end;
                        end;
              end;
    
    begin     // INITIALISATION DES VARIABLES :
              BMP.PixelFormat:=pf32bit; Bpp:=4; //<- vu que le code est du 32 bit pour le canal Alpha (si pf24bit alors Bpp:=3)
              with pCoulPen do begin
                   pCoulPen.rgbBlue :=GetBValue(CoulPen);
                   pCoulPen.rgbGreen:=GetGValue(CoulPen);
                   pCoulPen.rgbRed  :=GetRValue(CoulPen);
              end;
              case TraceMode of
                   tmAffiche, tmEfface : CoulPen:=RGB(GetBValue(CoulPen),GetGValue(CoulPen),GetRValue(CoulPen)); //<- on passe de RGB à BGR
              end;
    
              Scan0 := Integer(BMP.ScanLine[0]);
              MLS   := Integer(BMP.ScanLine[1]) - Scan0; //Memory Line Size
              W     := BMP.Width ;
              H     := BMP.Height;
              Bpp   := Abs(MLS div W);
              if Integer(BMP.ScanLine[H-1]) < Scan0 then begin  //Si c'est un  Bottom-Up DIB...
    	     PixMin := Integer(BMP.ScanLine[H-1]);
      	     PixMax := Scan0 + Bpp*W - Bpp;
              end else begin //sinon c'est un Top-Down DIB...
      	      PixMin := Scan0;
                  PixMax :=Integer(BMP.ScanLine[H-1]) + Bpp*W - Bpp;
              end;
    
              dx:=xe-xo; dy:=ye-yo;
              miep:=epTrait/2; rr:=miEp; ep:=0;
              if dx=0 then // Verticale
              begin if epTrait=1 then miep:=0;
                    xo1:=xo - miep; xo2:=xo + miep; yo1:=min(yo,ye); ye1:=max(yo,ye);
                    for ix:=trunc(xo1) to trunc(xo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        yoMin:=trunc(yo1-u); yeMax:=trunc(ye1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for iy:=yoMin to yeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              if ye=yo then // Horizontale
              begin if epTrait=1 then miep:=0;
                    yo1:=yo - miep; yo2:=yo + miep; xo1:=min(xo,xe); xe1:=max(xo,xe);
                    for iy:=trunc(yo1) to trunc(yo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        xoMin:=trunc(xo1-u); xeMax:=trunc(xe1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for ix:=xoMin to xeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              // Droites inclinées
     try
              Theta:=arcTan2(ye-yo,xe-xo);      ad:=tan(Theta); // Pente de l'axe de la droite
              si:=sin(Theta);   co:=cos(Theta); mis:=miep*si;  mic:=miep*co;
              xo1:=xo + mis;    yo1:=yo - mic;  xo2:=xo - mis; yo2:=yo + mic;
              xe1:=xe + mis;    ye1:=ye - mic;  xe2:=xe - mis; ye2:=ye + mic;
              dy:=abs(ye-yo);   dx:=abs(xe-xo);
              Q:=0;
              if (xe>xo) and (ye<yo) then Q:=1 else // Quadrants
              if (xe<xo) and (ye<yo) then Q:=2 else
              if (xe<xo) and (ye>yo) then Q:=3 else
              if (xe>xo) and (ye>yo) then Q:=4;
              bds:=yo1 - ad*xo1;   // Ordonnée à l'origine du bord supérieur
              bdi:=yo2 - ad*xo2;   // Ordonnée à l'origine du bord inférieur
              ap:=-1/ad;           // Pente des petits côtés perpendiculaires
              bdg:=-ap*xo1 + yo1;  // Ordonnée à l'origine du bord gauche
              bdd:=-ap*xe1 + ye1;  // Ordonnée à l'origine du bord droit
              ymin1:=min(round(ye1),round(yo2)); ymax1:=max(round(ye1),round(yo2));
              ymin2:=min(round(ye2),round(yo1)); ymax2:=max(round(ye2),round(yo1));
              ymin :=min(ymin1,ymin2);           ymax :=max(ymax1,ymax2);
              if epTrait>1 then begin
                 SetLength(lignes,ymax-ymin+2); // +2 sinon VA
                 for iy:=Low(lignes) to High(lignes) do begin
                     lignes[iy].xmin:=0; lignes[iy].xmax:=0;
                 end;
                 if BoutsRonds then begin // Embouts arrondis
                    Rond(xo,yo,round(miep)); Rond(xe,ye,round(miep));
                 end;
              end;
              if dy>=dx then // Droites très inclinées par rapport à l'horizontale
              begin // Les xmin et xmax :
                    yoMin:=round(min(yo1,ye1)); yeMax:=round(max(yo1,ye1));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bds)/ad; ix:=round(x);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    xoMin:=round(min(xo1,xo2)); xeMax:=round(max(xo1,xo2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:=ap*ix + bdg; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    yoMin:=round(min(yo2,ye2)); yeMax:=round(max(yo2,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdi)/ad; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    xoMin:=round(min(xe1,xe2)); xeMax:=round(max(xe1,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ap*ix + bdd; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do  for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
                    EXIT;
              end else // Droites inclinées à moins de 45° par rapport à l'horizontale
              begin // Les xmin et xmax :
                    xoMin:=round(min(xo1,xe1)); xeMax:=round(max(xo1,xe1));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bds; iy:=round(y);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    yoMin:=round(min(yo1,yo2)); yeMax:=round(max(yo1,yo2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdg)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    xoMin:=round(min(xo2,xe2)); xeMax:=round(max(xo2,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bdi; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    yoMin:=round(min(ye1,ye2)); yeMax:=round(max(ye1,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdd)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
              end;
      except
      end;
    end; // DrawLine6
    ... en tous cas on avance.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  9. #69
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    ... est-ce-que pixel^ correspond à PRGBQuad(scan)^ ???
    ... et color c'est CoulPen ???
    ... et Table[] qui semble âtre un array of boolean je le raccroche comment au PRGBQuad(scan)^.rgbReserved:=0 ou $FF qui est du byte ???
    oui c'est ça, pixel^ pointeur vers le pixel
    color CoulPen

    et Table est un Array of Boolean qui remplace les rgbReserved vu que de toute façon on ne fait que tester s'il est égal à $00 ou à $FF...ce qui correspond à un Boolean
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  10. #70
    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,

    Paul TOTH : oui c'est ça, pixel^ pointeur vers le pixel
    color CoulPen

    et Table est un Array of Boolean qui remplace les rgbReserved vu que de toute façon on ne fait que tester s'il est égal à $00 ou à $FF...ce qui correspond à un Boolean
    ... Ok, merci je vais tester.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  11. #71
    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,

    J'ai modifié le code comme ceci : voir les parties en couleur, mais cela ne fonctionne pas

    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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    type tTraceMode = (tmAffiche,tmEfface,tmXOR,tmCopy);
    procedure DrawLine6( BMP : TBitMap; xo,yo,xe,ye, epTrait : integer; CoulPen : TColor; TraceMode : tTraceMode; Alpha : integer; BoutsRonds : boolean);
    //        avec Alpha négatif on trace ou on efface et avec Alpha = 0 ou $FF on bascule simplement le canal Alpha
    type      PCardinal = ^Cardinal;
    var       Theta,miEp,si,co,mis,mic,
              ep,x,y,dx,dy,xo1,yo1,xe1,ye1,xo2,yo2,xe2,ye2,xorMin,xerMax,yorMin,yerMax,rr,d,u : Extended;
              ap,bp,ad,bds,bdi,bdg,bdd : Extended;
              iy,ix,iyp,ixp,yoMin,yeMax,xoMin,xeMax,r,i,j,xoc,xec,yoc,yec : integer;
              // Le BitMap :
              W,H     : integer;
              Scan0   : Integer;       //Valeur du pointeur d'entrée dans le Bitmap.
              Scan    : Integer;       //Pointeur temporaire destiné à être incrémenté.
              MLS     : Integer;       //Memory Line Size (en bytes) du Bitmap.
              Bpp     : Integer;       //Byte per pixel du Bitmap.
              PixMin,PixMax : Integer; //Bornes de l'intervalle d'appartenance du pointeur au BitMap
              pCoulPen: TRGBQuad;      //Pointe sur la couleur du crayon
              ymin1,ymax1,ymin2,ymax2,ymin,ymax : integer;
              lignes    : array of record xmin, xmax: Integer; end; // Le contour
              Q         : byte;        // Les quadrants
              Table     : array of Boolean;
    
              procedure GSPixel;
              begin     Scan := Scan0;
                        Inc(Scan, iy*MLS + ix*Bpp);
                        if not ((Scan>=PixMin) and (Scan<=PixMax)) then EXIT; // Si on se trouve en-dehors de la mem du BMP
                        if not ((ix>=0) and (iy>=0) and (ix<=W-1) and (iy<=H-1)) then EXIT; // Si la droite dépasse les bords du Bmp
                        if Alpha>=0 then begin PRGBQuad(scan)^.rgbReserved:=Alpha; EXIT; end; //<< ici on bascule uniquement le canal Alpha
                        case TraceMode of
                             tmAffiche : if PRGBQuad(scan)^.rgbReserved = 0 then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmEfface  : if PRGBQuad(scan)^.rgbReserved = $FF then begin
                                            PCardinal(scan)^ := not (PCardinal(scan)^ XOR coulPen);
                                         end;
                             tmXOR     : PCardinal(scan)^ :=  PCardinal(scan)^ XOR coulPen;
                             else PRGBQuad(Scan)^:=pCoulPen; //<- pmCopy (utilisé uniquement lors d'un appel pour un tracé de finition)
                        end;
              end; // GSPixel
    
              procedure Rond(xc,yc,R : integer); // Embouts arrondis
              var       x,y : integer; e,u : Extended;
              begin     for y:=yc-R to yc+R do begin
                            e:=y-(yc-R); u:=sqrt(sqr(R)-sqr(R-e)); iy:=y;
                            for x:=xc-floor(u) to xc+floor(u) do begin ix:=x; GSPixel; end;
                        end;
              end;
    
    begin     // INITIALISATION DES VARIABLES :
              BMP.PixelFormat:=pf32bit; Bpp:=4; //<- vu que le code est du 32 bit pour le canal Alpha (si pf24bit alors Bpp:=3)
              with pCoulPen do begin
                   pCoulPen.rgbBlue :=GetBValue(CoulPen);
                   pCoulPen.rgbGreen:=GetGValue(CoulPen);
                   pCoulPen.rgbRed  :=GetRValue(CoulPen);
              end;
              case TraceMode of
                   tmAffiche, tmEfface : CoulPen:=RGB(GetBValue(CoulPen),GetGValue(CoulPen),GetRValue(CoulPen)); //<- on passe de RGB à BGR
              end;
    
              Scan0 := Integer(BMP.ScanLine[0]);
              MLS   := Integer(BMP.ScanLine[1]) - Scan0; //Memory Line Size
              W     := BMP.Width ;
              H     := BMP.Height;
              Bpp   := Abs(MLS div W);
              if Integer(BMP.ScanLine[H-1]) < Scan0 then begin  //Si c'est un  Bottom-Up DIB...
    	     PixMin := Integer(BMP.ScanLine[H-1]);
      	     PixMax := Scan0 + Bpp*W - Bpp;
              end else begin //sinon c'est un Top-Down DIB...
      	      PixMin := Scan0;
                  PixMax :=Integer(BMP.ScanLine[H-1]) + Bpp*W - Bpp;
              end;
    
              if Alpha>=0 then begin
                 SetLength(Table,W*H);
                 for iy:=0 to H-1 do begin
                     for ix:=0 to W-1 do begin
                         if Table[ix + W * iy] = False then
                         begin Scan := Scan0; Inc(Scan, iy*MLS + ix*Bpp);
                               //PRGBQuad(scan)^ := PRGBQuad(scan)^ xor CoulPen; //<-[Erreur] uManipBMP.pas(2843): Opérateur non applicable à ce type d'opérande
                               //PRGBQuad(scan)^ := PRGBQuad(scan)^ xor pCoulPen;  // idem pas accepté par le compilo
                               PRGBQuad(scan)^.rgbReserved := PRGBQuad(scan)^.rgbReserved xor CoulPen; //<- accepté par le compilo mais ça ne fonctionne pas.                           
                              Table[ix + W * iy] := True;
                         end;
                      end;
                 end;
                 EXIT;
              end;
              dx:=xe-xo; dy:=ye-yo;
              miep:=epTrait/2; rr:=miEp; ep:=0;
              if dx=0 then // Verticale
              begin if epTrait=1 then miep:=0;
                    xo1:=xo - miep; xo2:=xo + miep; yo1:=min(yo,ye); ye1:=max(yo,ye);
                    for ix:=trunc(xo1) to trunc(xo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        yoMin:=trunc(yo1-u); yeMax:=trunc(ye1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for iy:=yoMin to yeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              if ye=yo then // Horizontale
              begin if epTrait=1 then miep:=0;
                    yo1:=yo - miep; yo2:=yo + miep; xo1:=min(xo,xe); xe1:=max(xo,xe);
                    for iy:=trunc(yo1) to trunc(yo2) do begin
                        // Embouts arrondis :
                        if (epTrait>1) and BoutsRonds then begin
                           d:=abs(rr-ep); if rr>d then u:=sqrt(sqr(rr)-sqr(d)) else u:=0;
                        end else u:=0;
                        xoMin:=trunc(xo1-u); xeMax:=trunc(xe1+u);
                        // Tracé du segment incluant les prolongements pour embouts arrondis :
                        for ix:=xoMin to xeMax do GSPixel;
                        ep:=ep+1;
                    end;
                    EXIT;
              end;
              // Droites inclinées
     try
              Theta:=arcTan2(ye-yo,xe-xo);      ad:=tan(Theta); // Pente de l'axe de la droite
              si:=sin(Theta);   co:=cos(Theta); mis:=miep*si;  mic:=miep*co;
              xo1:=xo + mis;    yo1:=yo - mic;  xo2:=xo - mis; yo2:=yo + mic;
              xe1:=xe + mis;    ye1:=ye - mic;  xe2:=xe - mis; ye2:=ye + mic;
              dy:=abs(ye-yo);   dx:=abs(xe-xo);
              Q:=0;
              if (xe>xo) and (ye<yo) then Q:=1 else // Quadrants
              if (xe<xo) and (ye<yo) then Q:=2 else
              if (xe<xo) and (ye>yo) then Q:=3 else
              if (xe>xo) and (ye>yo) then Q:=4;
              bds:=yo1 - ad*xo1;   // Ordonnée à l'origine du bord supérieur
              bdi:=yo2 - ad*xo2;   // Ordonnée à l'origine du bord inférieur
              ap:=-1/ad;           // Pente des petits côtés perpendiculaires
              bdg:=-ap*xo1 + yo1;  // Ordonnée à l'origine du bord gauche
              bdd:=-ap*xe1 + ye1;  // Ordonnée à l'origine du bord droit
              ymin1:=min(round(ye1),round(yo2)); ymax1:=max(round(ye1),round(yo2));
              ymin2:=min(round(ye2),round(yo1)); ymax2:=max(round(ye2),round(yo1));
              ymin :=min(ymin1,ymin2);           ymax :=max(ymax1,ymax2);
              if epTrait>1 then begin
                 SetLength(lignes,ymax-ymin+2); // +2 sinon VA
                 for iy:=Low(lignes) to High(lignes) do begin
                     lignes[iy].xmin:=0; lignes[iy].xmax:=0;
                 end;
                 if BoutsRonds then begin // Embouts arrondis
                    Rond(xo,yo,round(miep)); Rond(xe,ye,round(miep));
                 end;
              end;
              if dy>=dx then // Droites très inclinées par rapport à l'horizontale
              begin // Les xmin et xmax :
                    yoMin:=round(min(yo1,ye1)); yeMax:=round(max(yo1,ye1));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bds)/ad; ix:=round(x);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    xoMin:=round(min(xo1,xo2)); xeMax:=round(max(xo1,xo2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:=ap*ix + bdg; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    yoMin:=round(min(yo2,ye2)); yeMax:=round(max(yo2,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdi)/ad; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    xoMin:=round(min(xe1,xe2)); xeMax:=round(max(xe1,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ap*ix + bdd; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do  for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
                    EXIT;
              end else // Droites inclinées à moins de 45° par rapport à l'horizontale
              begin // Les xmin et xmax :
                    xoMin:=round(min(xo1,xe1)); xeMax:=round(max(xo1,xe1));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bds; iy:=round(y);
                          if epTrait=1 then GSPixel else begin
                             if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                             case Q of
                                  1,2 : lignes[iy-ymin].xmin:=ix;
                                  3,4 : lignes[iy-ymin].xmax:=ix;
                             end;
                          end;
                    end;
                    if epTrait=1 then EXIT;
                    yoMin:=round(min(yo1,yo2)); yeMax:=round(max(yo1,yo2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdg)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmin:=ix;
                               2,3 : lignes[iy-ymin].xmax:=ix;
                          end;
                    end;
                    xoMin:=round(min(xo2,xe2)); xeMax:=round(max(xo2,xe2));
                    for ix:=xoMin to xeMax do // y = a.x + b
                    begin y:= ad*ix + bdi; iy:=round(y);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,2 : lignes[iy-ymin].xmax:=ix;
                               3,4 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    yoMin:=round(min(ye1,ye2)); yeMax:=round(max(ye1,ye2));
                    for iy:=yoMin to yeMax do // x:= (y - b)/a
                    begin x:= (iy - bdd)/ap; ix:=round(x);
                          if (iy-ymin>=0) and (iy-ymin<=High(lignes)) then
                          case Q of
                               1,4 : lignes[iy-ymin].xmax:=ix;
                               2,3 : lignes[iy-ymin].xmin:=ix;
                          end;
                    end;
                    // Eviter les xmin et xmax restés à 0 :
                    for iy:=1 to High(lignes) do begin
                        if lignes[iy].xmin=0 then lignes[iy].xmin:=lignes[iy-1].xmin;
                        if lignes[iy].xmax=0 then lignes[iy].xmax:=lignes[iy-1].xmax;
                    end;
                    if lignes[0].xmin=0 then lignes[0].xmin:=lignes[1].xmin;
                    if lignes[0].xmax=0 then lignes[0].xmax:=lignes[1].xmax;
                    // Tracé final :
                    for iy := ymin to ymax
                    do for ix:=lignes[iy-ymin].xmin to lignes[iy-ymin].xmax do GSPixel;
                    SetLength(lignes,1);
              end;
      except
      end;
    end; // DrawLine6
    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  12. #72
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    tu ne dessine rien

    on reprend...

    un bitmap 32 bits c'est un tableau de Cardinal

    chaque Cardinal correspond à un Pixel sur 32 Bits au format AARRGGBB

    ton PRGBQuad(scan)^ décompose ce Cardinal en un RECORD de Byte, du coup tu ne peux pas faire un XOR dessus !

    utilise PCardinal(scan)^ ou met à jour chaque composante (Red, Green, Blue) là dans ton code tu ne touches qu'au canal alpha...ce qui ne sert à rien
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  13. #73
    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,

    Paul TOTH :tu ne dessine rien

    un bitmap 32 bits c'est un tableau de Cardinal
    chaque Cardinal correspond à un Pixel sur 32 Bits au format AARRGGBB
    ton PRGBQuad(scan)^ décompose ce Cardinal en un RECORD de Byte, du coup tu ne peux pas faire un XOR dessus !

    utilise PCardinal(scan)^ ou met à jour chaque composante (Red, Green, Blue) là dans ton code tu ne touches qu'au canal alpha...ce qui ne sert à rien
    ... Ok, je vais utiliser PCardinal(scan)^
    ... par contre dans la version précédente de DrawLine6 je ne touchais également qu'au canal Alpha et pourtant cela marchait !!!???

    Bon, comme je suis scotché à ma bécane depuis ce matin, je ferai la modif demain.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

  14. #74
    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,

    J'ai beau essayer diverses hypothèses mais je tourne en rond : dans le meilleur des cas j'arrive à éviter que le déplacement d'un dessin n'altère pas les couleurs de l'arrière-plan mais lorsque il passe par-dessus un deuxième dessin déplacable il en modifie les couleurs ce qui fait qu'en déplaçant ce deuxième dessin le NotXor fonctionne avec des fausses couleurs ce qui produit des traces telles des empreintes de pas laissées par ce déplacement.

    Donc, je laisse tomber cette piste et je vais tout bonnement me contenter des améliorations apportées par l'utilisation de polyline qui résoud le problème initialement posé et je me passerai du deuxième objectif qui visait à obtenir une sorte de polyline polychrome donc je me passerai des contours en couleurs dégradées.

    Par contre je vais quand-même conserver une copie des deux codes (couleurs décalées et canal Alpha) pour le cas où il me viendrai une idée).

    En tous cas merci pour l'aide.

    A+.
    N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi

+ Répondre à la discussion
Cette discussion est résolue.
Page 4 sur 4 PremièrePremière 1234

Discussions similaires

  1. Réponses: 0
    Dernier message: 03/10/2007, 13h11
  2. form en mode continu et detail couleur
    Par lolothom dans le forum VBA Access
    Réponses: 5
    Dernier message: 20/07/2007, 10h31
  3. Problème "ON_CONTROL_RANGE" mode release
    Par BoyzInDaProject dans le forum MFC
    Réponses: 5
    Dernier message: 11/05/2007, 17h24
  4. Problèmes en mode Debug
    Par pracede2005 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 03/05/2007, 16h29
  5. problème en mode release
    Par Polux95 dans le forum Qt
    Réponses: 20
    Dernier message: 25/04/2007, 09h58

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