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:
#define sign(x) ((x > 0)? 1 : ((x < 0)? -1: 0)) x = x1; y = y1; dx = abs(x2 - x1); dy = abs(y2 - y1); s1 = sign(x2 - x1); s2 = sign(y2 - y1); swap = 0; if (dy > dx) { temp = dx; dx = dy; dy = temp; swap = 1; } D = 2*dy - dx; for (i = 0; i < dx; i++) { display_pixel (x, y); while (D >= 0) { D = D - 2*dx; if (swap) x += s1; else y += s2; } D = D + 2*dy; if (swap) y += s2; else x += s1; }
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:
#define GAMMA 0.43 //Returns a linear value in the range [0,1] //for sRGB input in [0,255]. double ChannelInvCompanding(int c) { double y; c = c & 0xFF; y = (double) c; y = y / 255.0; if (c <= 0.04045) y = y / 12.92; else y = pow(((y + 0.055) / 1.055), 2.4); return (y); } //Convert color from 0..255 to 0..1 //Inverse Srgb Companding for //Red, Green, and Blue double *InverseSrgbCompanding(int c) { double *r = malloc(4 * sizeof(double)); r[0] = (double) get_t(c); r[1] = ChannelInvCompanding(get_r(c)); r[2] = ChannelInvCompanding(get_g(c)); r[3] = ChannelInvCompanding(get_b(c)); return (r); } //Apply companding to Red, Green, and Blue double ChannelCompanding(double c) { double x; if (c <= 0.0031308) x = 12.92 * c; else x = (1.055 * pow(c, (1/2.4))) - 0.055; return (x); } //return new color. Convert 0..1 back into 0..255 //Srgb Companding for Red, Green, and Blue int SrgbCompanding(double *c) { int t; int r; int g; int b; t = (int)c[0]; r = (int)(ChannelCompanding(c[1]) * 255); g = (int)(ChannelCompanding(c[2]) * 255); b = (int)(ChannelCompanding(c[3]) * 255); free(c); return (create_trgb(t, r, g, b)); } //sums channels //does not include transperancy double sumChannels(double *c) { double x = c[1] + c[2] + c[3]; return (x); } //Lerping see //https://en.wikipedia.org/wiki/Linear_interpolation //#Programming_language_support double lerp_int(double c1, double c2, double t) { return (c1 * (1 - t) + c2 * t); //return ((1 - t) * c1 + t * c2); } double *lerp(double *c1, double *c2, double t) { double *r = malloc(4 * sizeof(double)); //r[1] = ((1 - t) * c1[1] + t * c2[1]); //r[2] = ((1 - t) * c1[2] + t * c2[2]); //r[3] = ((1 - t) * c1[3] + t * c2[3]); r[1] = (c1[1] * (1 - t)) + c2[1] * t; r[2] = (c1[2] * (1 - t)) + c2[2] * t; r[3] = (c1[3] * (1 - t)) + c2[3] * t; return (r); } typedef struct s_bresvars { int x; int y; int dx; int dy; int s1; int s2; int swap; int temp; int d; int i; } t_bresvars; int sign(int x) { if (x > 0) return (1); else if (x < 0) return (-1); else return (0); } void bresenhams_alg(int x1, int y1, int x2, int y2, int scolor, int ecolor, t_vars *vars) { double step; double *color; double intensity; double total; int temp; int d; int clr; double *color1_lin = InverseSrgbCompanding(scolor); double bright1 = pow(sumChannels(c.color1_lin), GAMMA); double *color2_lin = InverseSrgbCompanding(ecolor); double bright2 = pow(sumChannels(c.color2_lin), GAMMA); int x = x1; int y = y1; int dx = abs(x2 - x1); int dy = abs(y2 - y1); int s1 = sign(x2 - x1); int s2 = sign(y2 - y1); int swap = 0; int i = 0; double step_c = 0; if (dy > dx) { temp = dx; dx = dy; dy = temp; swap = 1; } d = 2*dy - dx; step = (1.0 / dx); while (i < dx) { step_c += step; intensity = pow(lerp_int(bright1, bright2, step), (1 / GAMMA)); color = lerp(color1_lin, color2_lin, step); total = sumChannels(color); if (total != 0) c[1] = (c[1] * intensity / total); c[2] = (c[2] * intensity / total); c[3] = (c[3] * intensity / total); clr = SrgbCompanding(color); pixel_put(x, y, clr); while (v.d >= 0) { v.d = v.d - 2 * v.dx; if (v.swap) v.x += v.s1; else v.y += v.s2; } v.d = v.d + 2 * v.dy; if (v.swap) v.y += v.s2; else v.x += v.s1; v.i++; } free(color1_lin); free(color2_lin); }