Skip to content

Commit 68c37fd

Browse files
committed
1.7: Gauss prefilter for downsample
1 parent af862d7 commit 68c37fd

File tree

6 files changed

+302
-13
lines changed

6 files changed

+302
-13
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ The image is scaled using interpolation:
88

99
The image is resampled using:
1010

11-
- gsample (3x3)
11+
- gsample (3x3)
12+
13+
Include prefilter:
14+
15+
- Gauss (for downsample)
16+
- "Reverse Interpolate Scale (RIS)"
1217

1318
## build
1419

@@ -53,8 +58,9 @@ The first and second parameters specify the paths to the image and the result {P
5358
- `bicubic.h` - bicubic image scaling
5459
- `biline.h` - biline image scaling
5560
- `dependencies.c` - API [stb](https://github.com/nothings/stb.git)
61+
- `gauss.h` - prefilter: Gauss
5662
- `gsample.h` - gsample image sampler
57-
- `ris.h` - Reverse Interpolate Scale (RIS): prefilter
63+
- `ris.h` - prefilter: Reverse Interpolate Scale (RIS)
5864
- `stb/` - [stb](https://github.com/nothings/stb.git)
5965
- `stbresize.c` - CLI program.
6066

man/man1/stbresize.1

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.TH "StbResize" 1 1.5 "2 Jan 2023" "User Manual"
1+
.TH "StbResize" 1 1.7 "3 Jan 2023" "User Manual"
22

33
.SH NAME
44
stbresize
@@ -12,6 +12,10 @@ The image is scaled using interpolation:
1212
The image is resampled using:
1313
- gsample (3x3)
1414

15+
Include prefilter:
16+
- Gauss (for downsample)
17+
- "Reverse Interpolate Scale (RIS)"
18+
1519
.SH SYNOPSIS
1620
stbresize [options] image_in out.png
1721

src/dependencies.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
21
#define STB_IMAGE_IMPLEMENTATION
32
#define STB_IMAGE_WRITE_IMPLEMENTATION
43
#define BIAKIMA_IMPLEMENTATION
54
#define BICUBIC_IMPLEMENTATION
65
#define BILINE_IMPLEMENTATION
76
#define GSAMPLE_IMPLEMENTATION
87
#define RIS_IMPLEMENTATION
8+
#define GAUSS_IMPLEMENTATION
99
#include "stb/stb_image.h"
1010
#include "stb/stb_image_write.h"
1111
#include "biakima.h"
1212
#include "bicubic.h"
1313
#include "biline.h"
1414
#include "gsample.h"
1515
#include "ris.h"
16+
#include "gauss.h"

src/gauss.h

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
/*
2+
https://github.com/heptagonhust/bicubic-image-resize/issues/9
3+
*/
4+
5+
#ifndef GAUSS_H_
6+
#define GAUSS_H_
7+
8+
#ifdef GAUSS_STATIC
9+
#define GAUSSAPI static
10+
#else
11+
#define GAUSSAPI extern
12+
#endif
13+
14+
#ifdef __cplusplus
15+
extern "C" {
16+
#endif
17+
GAUSSAPI float GaussBlurFilterY (unsigned char *src, int height, int width, int channels, float radius);
18+
GAUSSAPI float GaussBlurFilterX (unsigned char *src, int height, int width, int channels, float radius);
19+
GAUSSAPI float GaussBlurFilter(unsigned char *src, int height, int width, int channels, float radiusy, float radiusx);
20+
#ifdef __cplusplus
21+
}
22+
#endif
23+
24+
#ifdef GAUSS_IMPLEMENTATION
25+
26+
void GaussLineMatrix (float *cmatrix, float radius)
27+
{
28+
float std_dev;
29+
float sum, t, tt;
30+
int i, j, iradius;
31+
32+
if (radius < 0)
33+
{
34+
radius = -radius;
35+
}
36+
std_dev = radius;
37+
iradius = (int)(2.0f * radius + 0.5f) + 1;
38+
if (iradius > 1)
39+
{
40+
for (i = 0; i < iradius; i++)
41+
{
42+
sum = 0;
43+
for (j = 0; j <= 50; j++)
44+
{
45+
t = (float)i;
46+
t -= 0.5f;
47+
t += 0.02f * j;
48+
tt = -(t * t) / (2.0f * std_dev * std_dev);
49+
sum += exp (tt);
50+
}
51+
cmatrix[i] = sum / 50.0f;
52+
}
53+
sum = cmatrix[0];
54+
for (i = 1; i < iradius; i++)
55+
{
56+
sum += 2.0f * cmatrix[i];
57+
}
58+
for (i = 0; i < iradius; i++)
59+
{
60+
cmatrix[i] = cmatrix[i] / sum;
61+
}
62+
}
63+
else
64+
{
65+
cmatrix[0] = 1.0f;
66+
}
67+
}
68+
69+
GAUSSAPI float GaussBlurFilterY (unsigned char *src, int height, int width, int channels, float radius)
70+
{
71+
int iradius, y, x, yp, yn, i, dval;
72+
size_t k, kp, kn, line = width * channels;
73+
unsigned int d;
74+
float imc, sc, gaussval = 0.0f;
75+
float *gaussmat;
76+
unsigned char *temp = NULL;
77+
78+
if (radius < 0)
79+
{
80+
radius = -radius;
81+
}
82+
iradius = (int)(2.0f * radius + 0.5f) + 1;
83+
84+
if (!(gaussmat = (float*)malloc((iradius) * sizeof(float))))
85+
{
86+
return 0.0f;
87+
}
88+
if (!(temp = (unsigned char*)malloc(height * width * channels * sizeof(unsigned char))))
89+
{
90+
return 0.0f;
91+
}
92+
93+
GaussLineMatrix (gaussmat, radius);
94+
95+
if (iradius > 1)
96+
{
97+
k = 0;
98+
for (y = 0; y < height; y++)
99+
{
100+
for (x = 0; x < width; x++)
101+
{
102+
for (d = 0; d < channels; d++)
103+
{
104+
kp = k;
105+
kn = k;
106+
imc = (float)src[k + d];
107+
sc = imc * gaussmat[0];
108+
for (i = 1; i < iradius; i++)
109+
{
110+
yp = y - i;
111+
if (yp < 0)
112+
{
113+
yp = 0;
114+
}
115+
else
116+
{
117+
kp -= line;
118+
}
119+
yn = y + i;
120+
if (yn < height)
121+
{
122+
kn += line;
123+
}
124+
else
125+
{
126+
yn = 0;
127+
}
128+
imc = (float)src[kp + d];
129+
sc += imc * gaussmat[i];
130+
imc = (float)src[kn + d];
131+
sc += imc * gaussmat[i];
132+
}
133+
sc += 0.5f;
134+
sc = (sc < 0.0f) ? 0.0f : (sc < 255.0f) ? sc : 255.0f;
135+
temp[k + d] = (unsigned char)sc;
136+
}
137+
k += channels;
138+
}
139+
}
140+
k = 0;
141+
for (y = 0; y < height; y++)
142+
{
143+
for (x = 0; x < width; x++)
144+
{
145+
for (d = 0; d < channels; d++)
146+
{
147+
dval = (int)src[k] - (int)temp[k];
148+
gaussval += (dval < 0) ? -dval : dval;
149+
src[k] = temp[k];
150+
k++;
151+
}
152+
}
153+
}
154+
gaussval /= (float)k;
155+
}
156+
157+
free(temp);
158+
free(gaussmat);
159+
160+
return gaussval;
161+
}
162+
163+
GAUSSAPI float GaussBlurFilterX (unsigned char *src, int height, int width, int channels, float radius)
164+
{
165+
int iradius, y, x, xp, xn, i, dval;
166+
size_t k, kp, kn;
167+
unsigned int d;
168+
float imc, sc, gaussval = 0.0f;
169+
float *gaussmat;
170+
unsigned char *temp = NULL;
171+
172+
if (radius < 0)
173+
{
174+
radius = -radius;
175+
}
176+
iradius = (int)(2.0f * radius + 0.5f) + 1;
177+
178+
if (!(gaussmat = (float*)malloc((iradius) * sizeof(float))))
179+
{
180+
return 0.0f;
181+
}
182+
if (!(temp = (unsigned char*)malloc(height * width * channels * sizeof(unsigned char))))
183+
{
184+
return 0.0f;
185+
}
186+
187+
GaussLineMatrix (gaussmat, radius);
188+
189+
if (iradius > 1)
190+
{
191+
k = 0;
192+
for (y = 0; y < height; y++)
193+
{
194+
for (x = 0; x < width; x++)
195+
{
196+
for (d = 0; d < channels; d++)
197+
{
198+
kp = k;
199+
kn = k;
200+
imc = (float)src[k + d];
201+
sc = imc * gaussmat[0];
202+
for (i = 1; i < iradius; i++)
203+
{
204+
xp = x - i;
205+
if (xp < 0)
206+
{
207+
xp = 0;
208+
}
209+
else
210+
{
211+
kp -= channels;
212+
}
213+
xn = x + i;
214+
if (xn < width)
215+
{
216+
kn += channels;
217+
}
218+
else
219+
{
220+
xn = 0;
221+
}
222+
imc = (float)src[kp + d];
223+
sc += imc * gaussmat[i];
224+
imc = (float)src[kn + d];
225+
sc += imc * gaussmat[i];
226+
}
227+
sc += 0.5f;
228+
sc = (sc < 0.0f) ? 0.0f : (sc < 255.0f) ? sc : 255.0f;
229+
temp[k + d] = (unsigned char)sc;
230+
}
231+
k += channels;
232+
}
233+
}
234+
k = 0;
235+
for (y = 0; y < height; y++)
236+
{
237+
for (x = 0; x < width; x++)
238+
{
239+
for (d = 0; d < channels; d++)
240+
{
241+
dval = (int)src[k] - (int)temp[k];
242+
gaussval += (dval < 0) ? -dval : dval;
243+
src[k] = temp[k];
244+
k++;
245+
}
246+
}
247+
}
248+
gaussval /= (float)k;
249+
}
250+
251+
free(temp);
252+
free(gaussmat);
253+
254+
return gaussval;
255+
}
256+
257+
GAUSSAPI float GaussBlurFilter(unsigned char *src, int height, int width, int channels, float radiusy, float radiusx)
258+
{
259+
float gaussval = 0.0f;
260+
gaussval = GaussBlurFilterY(src, height, width, channels, radiusy);
261+
gaussval += GaussBlurFilterX(src, height, width, channels, radiusx);
262+
gaussval /= 255.0f;
263+
264+
return gaussval;
265+
}
266+
267+
#endif /* GAUSS_IMPLEMENTATION */
268+
269+
#endif /* GAUSS_H_ */

src/ris.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ RISAPI float ImageReFilter(unsigned char *src, unsigned char *res, int height, i
4444
}
4545
}
4646
}
47-
ims /= (float)height;
48-
ims /= (float)width;
49-
ims /= (float)channels;
47+
ims /= (float)k;
48+
ims /= 255.0f;
5049

5150
return ims;
5251
}

0 commit comments

Comments
 (0)