• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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