I’ve found this thread on StackOverflow but my python understanding isn’t that good to properly translate it to C, I’m trying to add that gradient feature to this line drawing algorithm:
JavaScript
x
34
34
1
#define sign(x) ((x > 0)? 1 : ((x < 0)? -1: 0))
2
3
x = x1;
4
y = y1;
5
dx = abs(x2 - x1);
6
dy = abs(y2 - y1);
7
s1 = sign(x2 - x1);
8
s2 = sign(y2 - y1);
9
swap = 0;
10
11
if (dy > dx) {
12
temp = dx;
13
dx = dy;
14
dy = temp;
15
swap = 1;
16
}
17
18
D = 2*dy - dx;
19
for (i = 0; i < dx; i++) {
20
display_pixel (x, y);
21
while (D >= 0) {
22
D = D - 2*dx;
23
if (swap)
24
x += s1;
25
else
26
y += s2;
27
}
28
D = D + 2*dy;
29
if (swap)
30
y += s2;
31
else
32
x += s1;
33
}
34
I feel bad for asking such a trivial task but I really can’t understand what is going on on the python side nor how the colours are represented (mine are int(0xttrrggbb))
Advertisement
Answer
Figured it out:
JavaScript
1
183
183
1
#define GAMMA 0.43
2
3
//Returns a linear value in the range [0,1]
4
//for sRGB input in [0,255].
5
double ChannelInvCompanding(int c)
6
{
7
double y;
8
9
c = c & 0xFF;
10
y = (double) c;
11
y = y / 255.0;
12
if (c <= 0.04045)
13
y = y / 12.92;
14
else
15
y = pow(((y + 0.055) / 1.055), 2.4);
16
return (y);
17
}
18
19
//Convert color from 0..255 to 0..1
20
//Inverse Srgb Companding for
21
//Red, Green, and Blue
22
double *InverseSrgbCompanding(int c)
23
{
24
double *r = malloc(4 * sizeof(double));
25
26
r[0] = (double) get_t(c);
27
r[1] = ChannelInvCompanding(get_r(c));
28
r[2] = ChannelInvCompanding(get_g(c));
29
r[3] = ChannelInvCompanding(get_b(c));
30
31
return (r);
32
}
33
34
//Apply companding to Red, Green, and Blue
35
double ChannelCompanding(double c)
36
{
37
double x;
38
39
if (c <= 0.0031308)
40
x = 12.92 * c;
41
else
42
x = (1.055 * pow(c, (1/2.4))) - 0.055;
43
return (x);
44
}
45
46
//return new color. Convert 0..1 back into 0..255
47
//Srgb Companding for Red, Green, and Blue
48
int SrgbCompanding(double *c)
49
{
50
int t;
51
int r;
52
int g;
53
int b;
54
55
t = (int)c[0];
56
r = (int)(ChannelCompanding(c[1]) * 255);
57
g = (int)(ChannelCompanding(c[2]) * 255);
58
b = (int)(ChannelCompanding(c[3]) * 255);
59
free(c);
60
return (create_trgb(t, r, g, b));
61
}
62
63
//sums channels
64
//does not include transperancy
65
double sumChannels(double *c)
66
{
67
double x = c[1] + c[2] + c[3];
68
return (x);
69
}
70
71
//Lerping see
72
//https://en.wikipedia.org/wiki/Linear_interpolation
73
//#Programming_language_support
74
double lerp_int(double c1, double c2, double t)
75
{
76
return (c1 * (1 - t) + c2 * t);
77
//return ((1 - t) * c1 + t * c2);
78
}
79
80
double *lerp(double *c1, double *c2, double t)
81
{
82
double *r = malloc(4 * sizeof(double));
83
84
//r[1] = ((1 - t) * c1[1] + t * c2[1]);
85
//r[2] = ((1 - t) * c1[2] + t * c2[2]);
86
//r[3] = ((1 - t) * c1[3] + t * c2[3]);
87
r[1] = (c1[1] * (1 - t)) + c2[1] * t;
88
r[2] = (c1[2] * (1 - t)) + c2[2] * t;
89
r[3] = (c1[3] * (1 - t)) + c2[3] * t;
90
return (r);
91
}
92
93
typedef struct s_bresvars {
94
int x;
95
int y;
96
int dx;
97
int dy;
98
int s1;
99
int s2;
100
int swap;
101
int temp;
102
int d;
103
int i;
104
} t_bresvars;
105
106
107
108
int sign(int x)
109
{
110
if (x > 0)
111
return (1);
112
else if (x < 0)
113
return (-1);
114
else
115
return (0);
116
}
117
118
119
void bresenhams_alg(int x1, int y1, int x2, int y2, int scolor, int ecolor, t_vars *vars)
120
{
121
double step;
122
double *color;
123
double intensity;
124
double total;
125
int temp;
126
int d;
127
int clr;
128
129
double *color1_lin = InverseSrgbCompanding(scolor);
130
double bright1 = pow(sumChannels(c.color1_lin), GAMMA);
131
double *color2_lin = InverseSrgbCompanding(ecolor);
132
double bright2 = pow(sumChannels(c.color2_lin), GAMMA);
133
134
int x = x1;
135
int y = y1;
136
int dx = abs(x2 - x1);
137
int dy = abs(y2 - y1);
138
int s1 = sign(x2 - x1);
139
int s2 = sign(y2 - y1);
140
int swap = 0;
141
int i = 0;
142
double step_c = 0;
143
144
if (dy > dx) {
145
temp = dx;
146
dx = dy;
147
dy = temp;
148
swap = 1;
149
}
150
151
d = 2*dy - dx;
152
step = (1.0 / dx);
153
while (i < dx)
154
{
155
step_c += step;
156
intensity = pow(lerp_int(bright1, bright2, step), (1 / GAMMA));
157
color = lerp(color1_lin, color2_lin, step);
158
total = sumChannels(color);
159
if (total != 0)
160
c[1] = (c[1] * intensity / total);
161
c[2] = (c[2] * intensity / total);
162
c[3] = (c[3] * intensity / total);
163
clr = SrgbCompanding(color);
164
pixel_put(x, y, clr);
165
while (v.d >= 0)
166
{
167
v.d = v.d - 2 * v.dx;
168
if (v.swap)
169
v.x += v.s1;
170
else
171
v.y += v.s2;
172
}
173
v.d = v.d + 2 * v.dy;
174
if (v.swap)
175
v.y += v.s2;
176
else
177
v.x += v.s1;
178
v.i++;
179
}
180
free(color1_lin);
181
free(color2_lin);
182
}
183