1
2 #include "libimagequant.h"
3 #include "pam.h"
4 #include "blur.h"
5
6 /*
7 Blurs image horizontally (width 2*size+1) and writes it transposed to dst (called twice gives 2d blur)
8 */
9 static void
transposing_1d_blur(unsigned char * restrict src,unsigned char * restrict dst,unsigned int width,unsigned int height,const unsigned int size)10 transposing_1d_blur (unsigned char *restrict src, unsigned char *restrict dst,
11 unsigned int width, unsigned int height, const unsigned int size)
12 {
13 for (unsigned int j = 0; j < height; j++) {
14 unsigned char *restrict row = src + j * width;
15
16 // accumulate sum for pixels outside line
17 unsigned int sum;
18 sum = row[0] * size;
19 for (unsigned int i = 0; i < size; i++) {
20 sum += row[i];
21 }
22
23 // blur with left side outside line
24 for (unsigned int i = 0; i < size; i++) {
25 sum -= row[0];
26 sum += row[i + size];
27
28 dst[i * height + j] = sum / (size * 2);
29 }
30
31 for (unsigned int i = size; i < width - size; i++) {
32 sum -= row[i - size];
33 sum += row[i + size];
34
35 dst[i * height + j] = sum / (size * 2);
36 }
37
38 // blur with right side outside line
39 for (unsigned int i = width - size; i < width; i++) {
40 sum -= row[i - size];
41 sum += row[width - 1];
42
43 dst[i * height + j] = sum / (size * 2);
44 }
45 }
46 }
47
48 /**
49 * Picks maximum of neighboring pixels (blur + lighten)
50 */
51 LIQ_PRIVATE void
liq_max3(unsigned char * src,unsigned char * dst,unsigned int width,unsigned int height)52 liq_max3 (unsigned char *src, unsigned char *dst, unsigned int width,
53 unsigned int height)
54 {
55 unsigned int i, j;
56
57 for (j = 0; j < height; j++) {
58 const unsigned char *row = src + j * width;
59 unsigned char t1, t2;
60 unsigned char prev, curr, next;
61
62 const unsigned char *prevrow = src + (j > 1 ? j - 1 : 0) * width;
63 const unsigned char *nextrow = src + MIN (height - 1, j + 1) * width;
64
65 curr = row[0];
66 next = row[0];
67
68 for (i = 0; i < width - 1; i++) {
69 prev = curr;
70 curr = next;
71 next = row[i + 1];
72
73 t1 = MAX (prev, next);
74 t2 = MAX (nextrow[i], prevrow[i]);
75 *dst++ = MAX (curr, MAX (t1, t2));
76 }
77
78 t1 = MAX (curr, next);
79 t2 = MAX (nextrow[width - 1], prevrow[width - 1]);
80 *dst++ = MAX (t1, t2);
81 }
82 }
83
84 /**
85 * Picks minimum of neighboring pixels (blur + darken)
86 */
87 LIQ_PRIVATE void
liq_min3(unsigned char * src,unsigned char * dst,unsigned int width,unsigned int height)88 liq_min3 (unsigned char *src, unsigned char *dst, unsigned int width,
89 unsigned int height)
90 {
91 unsigned int j;
92
93 for (j = 0; j < height; j++) {
94 unsigned char t1, t2;
95 const unsigned char *row = src + j * width,
96 *prevrow = src + (j > 1 ? j - 1 : 0) * width,
97 *nextrow = src + MIN (height - 1, j + 1) * width;
98
99 unsigned char prev, curr = row[0], next = row[0];
100
101 for (unsigned int i = 0; i < width - 1; i++) {
102 prev = curr;
103 curr = next;
104 next = row[i + 1];
105
106 t1 = MIN (prev, next);
107 t2 = MIN (nextrow[i], prevrow[i]);
108 *dst++ = MIN (curr, MIN (t1, t2));
109 }
110
111 t1 = MIN (curr, next);
112 t2 = MIN (nextrow[width - 1], prevrow[width - 1]);
113 *dst++ = MIN (t1, t2);
114 }
115 }
116
117 /*
118 Filters src image and saves it to dst, overwriting tmp in the process.
119 Image must be width*height pixels high. Size controls radius of box blur.
120 */
121 LIQ_PRIVATE void
liq_blur(unsigned char * src,unsigned char * tmp,unsigned char * dst,unsigned int width,unsigned int height,unsigned int size)122 liq_blur (unsigned char *src, unsigned char *tmp, unsigned char *dst,
123 unsigned int width, unsigned int height, unsigned int size)
124 {
125 assert (size > 0);
126 if (width < 2 * size + 1 || height < 2 * size + 1) {
127 return;
128 }
129 transposing_1d_blur (src, tmp, width, height, size);
130 transposing_1d_blur (tmp, dst, height, width, size);
131 }
132