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+.
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
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
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
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 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
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
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.
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;
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+.
N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi
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]
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
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;
Re-bonjour,
... 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 ????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;
... 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) :
... en tous cas on avance.
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
A+.
N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi
Re-bonjour,
... Ok, merci je vais tester.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
A+.
N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi
Re-bonjour,
J'ai modifié le code comme ceci : voir les parties en couleur, mais cela ne fonctionne pas
A+.
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
N'oubliez pas de consulter les FAQ Delphi et les cours et tutoriels Delphi
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
Re-bonjour,
... Ok, je vais utiliser PCardinal(scan)^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
... 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
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
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager