Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Gradient line

This thread is locked; no one can reply to it. rss feed Print
Gradient line
Nial Giacomelli
Member #5,114
October 2004
avatar

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
Member #2,905
November 2002

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

Sirocco
Member #88
April 2000
avatar

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.

-->
Red hot tentacle love.

Mae Mutts
Member #3,766
August 2003
avatar

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
Member #1,550
September 2001

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.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This thread is obviously about nothing so heres a bunny with a pancake on its head. -kazzmir

Neil Walker
Member #210
April 2000
avatar

I'm still waiting for the OpenLayer plug ;)

Neil.
AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Peter Hanratty
Member #7,191
May 2006

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":"http:\/\/static.allegro.cc\/image\/cache\/0\/9\/098e1eb81a1df741ab60947b023d8cbc.jpg","w":628,"h":489,"tn":"http:\/\/static.allegro.cc\/image\/cache\/0\/9\/098e1eb81a1df741ab60947b023d8cbc"}recol2.jpg

Go to: