Gradient line
ngiacomelli

I'm looking to render a line with a gradient from one colour to the other. I'm looking to use vanilla Allegro. I assume the best way would be to use do_line and calculate the colour value each iteration but I'm not so sure from there.

Anyone have any nice solutions?

kentl

Bresenhams's line drawing algorithm where you paint each pixel yourself in the gradient colors.

Sirocco

I've done it before using do_line, then stepping through the supplied coords and painting them accordingly. That's about as "Allegro friendly" as you can get.

Makes for some very nice effects.

Mae Mutts

This is how I did it. Looks fine.

1Notes: Color is a typedef of int
2 : GradientType indicates a horizontal or vertical gradient
3void fillGradient( BITMAP * bmp, int x1, int y1, int x2, int y2, Color startColor, Color endColor, GradientType direction)
4{
5 int numOfRedDivisions = getr( startColor ) - getr( endColor );
6 int numOfGreenDivisions = getg( startColor ) - getg( endColor );
7 int numOfBlueDivisions = getb( startColor ) - getb( endColor );
8
9 int divisions = 0;
10 switch( direction )
11 {
12 case HORIZONTAL_GRADIENT: divisions = x2-x1 ; break;
13 case VERTICAL_GRADIENT: divisions = y2-y1 ; break;
14 }
15
16 for(int i = 0; i < divisions; i++ )
17 {
18 int r = getr( startColor ) - (int)floor( i * numOfRedDivisions / divisions );
19 int g = getg( startColor ) - (int)floor( i * numOfGreenDivisions / divisions );
20 int b = getb( startColor ) - (int)floor( i * numOfBlueDivisions / divisions );
21
22
23 switch( direction )
24 {
25 case HORIZONTAL_GRADIENT: drawLine( bmp, x1+i, y1, x1+i, y2, makecol(r, g, b) ); break;
26 case VERTICAL_GRADIENT: drawLine( bmp, x1, y1+i, x2, y1+i, makecol(r, g, b) ); break;
27 }
28 }
29}
30 
31void drawLine( BITMAP * bmp, int x1, int y1, int x2, int y2, Color color)
32{
33 if( x1 == x2 )
34 vline( bmp, x1, y1, y2, color );
35 else
36 line( bmp, x1, y1, x2, y2, color );
37}

Johan Halmén

http://edu.loviisa.fi/~jhalmen/projects/mapgen/spectrline.gif
A line drawn using a class of mine
Basicly it's just my own version of do_line(), without a callback. You initiate an object with a start coordinate and an end coordinate or a start coordinate and a direction. Then you call a step function, which updates members x and y, which you can read.

Neil Walker

I'm still waiting for the OpenLayer plug ;)

Peter Hanratty

Greetings,

Heres a definable gradient class I did in Delphi a couple of years ago (you shouldnt have any problem understanding it since its not too different from C++). It lets you add points at a given position and define the colours.

------------------------------------------------------

1unit ColGrad;
2 
3interface
4 
5Uses Graphics;
6 
7Type
8 TColArray = Record
9 Bytes : Array [0..3] Of Byte;
10 End;
11 
12 TGradientPoint = Class (TObject)
13 Protected
14 IColour : TColor;
15 IPosition : Single;
16 INext : TGradientPoint;
17 
18 Procedure ISetPosition (Pos : Single);
19 
20 Public
21 Constructor Create; Overload; Virtual;
22 Constructor Create (Col : TColor; Pos : Single); Overload; Virtual;
23 Destructor Destroy; Override;
24 
25 Property Colour : TColor Read IColour Write IColour;
26 Property Position : Single Read IPosition Write ISetPosition;
27 Property Next : TGradientPoint Read INext Write INext;
28 
29 End;
30 
31 TGradientPoints = Class (TObject)
32 Protected
33 IPoints : TGradientPoint;
34 ICount : LongInt;
35 
36 Function IGetPoint (PointIndex : LongInt) : TGradientPoint;
37 
38 Public
39 Constructor Create; Virtual;
40 Destructor Destroy; Override;
41 
42 Property Count : LongInt Read ICount;
43 Property Points [PointIndex : LongInt] : TGradientPoint Read IGetPoint; Default;
44 
45 Procedure Add (NewPoint : TGradientPoint); Virtual;
46 Procedure Delete (Point : TGradientPoint); Virtual;
47 Procedure Clear; Virtual;
48 
49 End;
50 
51 TColourGradient = Class (TObject)
52 Protected
53 IHighColour, ILowColour : TColor;
54 IPoints : TGradientPoints;
55 
56 Public
57 Constructor Create; Overload; Virtual;
58 Constructor Create (HiCol, LoCol : TColor); Overload; Virtual;
59 Destructor Destroy; Override;
60 
61 Property HighColour : TColor Read IHighColour Write IHighColour;
62 Property LowColour : TColor Read ILowColour Write ILowColour;
63 Property Points : TGradientPoints Read IPoints;
64 
65 Function ColourAtPosition (Pos : Single) : TColor; Virtual;
66 Procedure Copy (ToGrad : TColourGradient); Virtual;
67 
68 End;
69 
70implementation
71 
72Procedure TGradientPoint.ISetPosition (Pos : Single);
73Begin
74 If Pos < 0 Then
75 IPosition := 0
76 Else
77 If Pos > 1 Then
78 IPosition := 1
79 Else
80 IPosition := Pos;
81End;
82 
83Constructor TGradientPoint.Create;
84Begin
85 Inherited Create;
86 IColour := clGray;
87 IPosition := 0.5;
88 INext := NIL;
89End;
90 
91Constructor TGradientPoint.Create (Col : TColor; Pos : Single);
92Begin
93 Inherited Create;
94 IColour := Col;
95 IPosition := Pos;
96 INext := NIL;
97End;
98 
99Destructor TGradientPoint.Destroy;
100Begin
101 Inherited;
102End;
103 
104Function TGradientPoints.IGetPoint (PointIndex : LongInt) : TGradientPoint;
105Var
106 Count : LongInt;
107 Current : TGradientPoint;
108Begin
109 If PointIndex >= ICount Then
110 Result := NIL
111 Else
112 Begin
113 Current := IPoints;
114 For Count := 1 To PointIndex Do
115 Current := Current.Next;
116 Result := Current;
117 End;
118End;
119 
120Constructor TGradientPoints.Create;
121Begin
122 Inherited Create;
123 IPoints := NIL;
124 ICount := 0;
125End;
126 
127Destructor TGradientPoints.Destroy;
128Begin
129 Self.Clear;
130 Inherited;
131End;
132 
133Procedure TGradientPoints.Add (NewPoint : TGradientPoint);
134Var
135 Current : TGradientPoint;
136Begin
137 If IPoints = NIL Then
138 IPoints := NewPoint
139 Else
140 Begin
141 Current := IPoints;
142 While Current.Next <> NIL Do
143 Current := Current.Next;
144 Current.Next := NewPoint;
145 End;
146 ICount := ICount + 1;
147End;
148 
149Procedure TGradientPoints.Delete (Point : TGradientPoint);
150Var
151 Current, Previous : TGradientPoint;
152 Found : Boolean;
153Begin
154 If IPoints = Point Then
155 Begin
156 Previous := IPoints;
157 IPoints := IPoints.Next;
158 Previous.Free;
159 ICount := ICount - 1;
160 End
161 Else
162 Begin
163 Current := IPoints;
164 Found := False;
165 While (Current.Next <> NIL) And (Not (Found)) Do
166 Begin
167 If Current.Next = Point Then
168 Begin
169 Previous := Current.Next;
170 Current.Next := Current.Next.Next;
171 Previous.Free;
172 Found := True;
173 ICount := ICount - 1;
174 End
175 Else
176 Current := Current.Next;
177 End;
178 End;
179End;
180 
181Procedure TGradientPoints.Clear;
182Var
183 Current, Previous : TGradientPoint;
184Begin
185 Current := IPoints;
186 While Current <> NIL Do
187 Begin
188 Previous := Current;
189 Current := Current.Next;
190 Previous.Free;
191 End;
192 ICount := 0;
193 IPoints := NIL;
194End;
195 
196Constructor TColourGradient.Create;
197Begin
198 Inherited Create;
199 ILowColour := clGray;
200 IHighColour := clGray;
201 IPoints := TGradientPoints.Create;
202End;
203 
204Constructor TColourGradient.Create (HiCol, LoCol : TColor);
205Begin
206 Inherited Create;
207 IHighColour := HiCol;
208 ILowColour := LoCol;
209 IPoints := TGradientPoints.Create;
210End;
211 
212Destructor TColourGradient.Destroy;
213Begin
214 IPoints.Free;
215 Inherited;
216End;
217 
218Function TColourGradient.ColourAtPosition (Pos : Single) : TColor;
219Var
220 CurrentPoint : TGradientPoint;
221 HiPoint, LoPoint, MidPoint : Single;
222 HiCol, LoCol, ResCol : TColArray;
223 BytePos : Byte;
224Begin
225 If Pos < 0 Then
226 Result := IHighColour
227 Else
228 If Pos > 1 Then
229 Result := ILowColour
230 Else
231 Begin
232 HiPoint := 0;
233 LoPoint := 1;
234 Move (IHighColour, HiCol, 4);
235 Move (ILowColour, LoCol, 4);
236 
237 CurrentPoint := IPoints [0];
238 While CurrentPoint <> NIL Do
239 Begin
240 If (CurrentPoint.Position <= Pos) And
241 (CurrentPoint.Position >= HiPoint) Then
242 Begin
243 HiPoint := CurrentPoint.Position;
244 Move (CurrentPoint.Colour, HiCol, 4);
245 End;
246 CurrentPoint := CurrentPoint.Next;
247 End;
248 
249 CurrentPoint := IPoints [0];
250 While CurrentPoint <> NIL Do
251 Begin
252 If (CurrentPoint.Position >= Pos) And
253 (CurrentPoint.Position <= LoPoint) Then
254 Begin
255 LoPoint := CurrentPoint.Position;
256 Move (CurrentPoint.Colour, LoCol, 4);
257 End;
258 CurrentPoint := CurrentPoint.Next;
259 End;
260 
261 If HiPoint = LoPoint Then
262 ResCol := LoCol
263 Else
264 Begin
265 MidPoint := (Pos - HiPoint) / (LoPoint - HiPoint);
266 For BytePos := 0 To 3 Do
267 Begin
268 HiPoint := HiCol.Bytes [BytePos];
269 LoPoint := LoCol.Bytes [BytePos];
270 ResCol.Bytes [BytePos] := Round (HiPoint + ((LoPoint - HiPoint) * MidPoint));
271 End;
272 End;
273 
274 Move (ResCol, Result, 4);
275 End;
276End;
277 
278Procedure TColourGradient.Copy (ToGrad : TColourGradient);
279Var
280 Current : TGradientPoint;
281Begin
282 ToGrad.LowColour := ILowColour;
283 ToGrad.HighColour := IHighColour;
284 ToGrad.Points.Clear;
285 Current := IPoints [0];
286 While Current <> NIL Do
287 Begin
288 ToGrad.Points.Add (TGradientPoint.Create (Current.Colour, Current.Position));
289 Current := Current.Next;
290 End;
291End;
292 
293end.

And Here it is in action :-

{"name":"recol2.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/9\/098e1eb81a1df741ab60947b023d8cbc.jpg","w":628,"h":489,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/9\/098e1eb81a1df741ab60947b023d8cbc"}recol2.jpg

Thread #582657. Printed from Allegro.cc