summaryrefslogtreecommitdiff
path: root/util.c
blob: 76d8e699ade5790ba33e9dbda987889fd04fcc6f (plain)
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
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "util.h"

/*
 * derived from http://www.gnu.org/software/guile-gnome/docs/gdk/html/The-GdkPixbuf-Structure.html
 */
guchar *pixbuf_point(GdkPixbuf *pixbuf, point_t point)
{
#if 0
	g_assert(point.x >= 0 && point.x < gdk_pixbuf_get_width (pixbuf));
	g_assert(point.y >= 0 && point.y < gdk_pixbuf_get_height(pixbuf));
	g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
#endif

	return gdk_pixbuf_get_pixels(pixbuf) 
		+ point.y * gdk_pixbuf_get_rowstride (pixbuf)
		+ point.x * gdk_pixbuf_get_n_channels(pixbuf);
}

void put_pixel(GdkPixbuf *pixbuf, point_t point, color_t color)
{
	//const gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
#if 0
	g_assert(n_channels == 4 || n_channels == 3);
	g_assert(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
	g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
#endif

	guchar *p = pixbuf_point(pixbuf, point);

	p[0] = color.r;
	p[1] = color.g;
	p[2] = color.b;
#if 0
	if (n_channels == 4)
		p[3] = color.a;
#endif
}

color_t get_pixel(GdkPixbuf *pixbuf, point_t point)
{
	//const gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
#if 0
	g_assert(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
	g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
	g_assert(n_channels == 4 || n_channels == 3);
#endif

	guchar *p = pixbuf_point(pixbuf, point);

	return COLOR(p[0], p[1], p[2], 0 /*n_channels == 4 ? p[3] : COL_MAX*/);
}

void color_to_yiq(color_t color, guint8 *y, guint8 *i, guint8 *q)
{
	if (y)
		*y = 0.299    * color.r + 0.587    * color.g + 0.115    * color.b;
	if (i)
		*i = 0.595716 * color.r - 0.274453 * color.g - 0.321263 * color.b;
	if (q)
		*q = 0.211456 * color.r - 0.522591 * color.g + 0.311135 * color.b;
}

/*
 * http://en.wikipedia.org/wiki/Digital_compositing
 */
color_t tint(color_t src, color_t tint_color)
{
	return COLOR(
		(tint_color.a * tint_color.r + (255 - tint_color.a) * src.r) / 255,
		(tint_color.a * tint_color.g + (255 - tint_color.a) * src.g) / 255,
		(tint_color.a * tint_color.b + (255 - tint_color.a) * src.b) / 255,
		src.a);
}


color32_t color32_add(color32_t a, color32_t b)
{
	return COLOR32(
			a.r + b.r,
			a.g + b.g,
			a.b + b.b
	);
}

color32_t color32_mult(color32_t a, gint multiplier)
{
	return COLOR32(
			multiplier * a.r,
			multiplier * a.g,
			multiplier * a.b
	);
}
color32_t to_color32(color_t a)
{
	return COLOR32(a.r, a.g, a.b);
}

colord_t colord_add(colord_t a, colord_t b)
{
	return COLORD(
			a.r + b.r,
			a.g + b.g,
			a.b + b.b,
			a.a + b.a
	);
}
colord_t colord_mult(colord_t a, gdouble multiplier)
{
	return COLORD(
			multiplier * a.r,
			multiplier * a.g,
			multiplier * a.b,
			multiplier * a.a
	);
}
colord_t to_colord(color_t a)
{
	return COLORD(a.r, a.g, a.b, a.a);
}


void ring_shift(void *_pntr, gint num, size_t size)
{
	g_assert(num >= 2);

	guint8 *pntr = (guint8*) _pntr;

	char *tmp = g_malloc(size);
	g_memmove(tmp, pntr, size);

	for (gint i = 0; i < (num-1)*size; i+=size)
		g_memmove(pntr+i, pntr+i+size, size);

	g_memmove(pntr + (num-1)*size, tmp, size);
	g_free(tmp);
}