6 #define CACHE_LINE_FACTOR 1
8 void myreadline(char *buf)
12 if (fgets(buf, 256, stdin) == NULL) {
13 fprintf(stderr, "Premuture EOF\n");
17 if (strlen(buf) == 0) {
21 ptr = &buf[strlen(buf) - 1];
32 // This is bad for very small x, should use power series instead.
39 double lanczos_tap(double x)
41 if (x < -3.0 || x > 3.0)
44 return sinc(-x*M_PI) * sinc(-x*M_PI / 3.0);
46 return sinc(x*M_PI) * sinc(x*M_PI / 3.0);
55 void hscale(unsigned char *pix, float *npix, unsigned w, unsigned h, unsigned nw)
57 struct pix_desc *pd = (struct pix_desc *)malloc(nw * sizeof(struct pix_desc));
59 float *coeffs = (float *)malloc(size_coeffs * sizeof(float));
62 double sf = (double)w / (double)nw;
63 double support = 3.0 * sf;
65 /* calculate the filter */
66 for (x = 0; x < nw; ++x) {
67 int start = ceil(x * sf - support);
68 int end = floor(x * sf + support);
80 pd[x].startcoeff = num_coeffs;
82 for (sx = start; sx <= end; ++sx) {
83 double nd = sx/sf - x;
84 double f = lanczos_tap(nd);
85 if (num_coeffs == size_coeffs) {
87 coeffs = (float *)realloc(coeffs, size_coeffs * sizeof(float));
90 coeffs[num_coeffs++] = f;
94 for (sx = start; sx <= end; ++sx) {
95 coeffs[pd[x].startcoeff + sx - start] /= sum;
99 for (y = 0; y < h; ++y) {
100 unsigned char *sptr = pix + y*w;
101 float *dptr = npix + y*nw;
102 for (x = 0; x < nw; ++x) {
104 float *cf = &coeffs[pd[x].startcoeff];
107 for (sx = pd[x].start; sx <= pd[x].end; ++sx) {
108 acc += sptr[sx] * *cf++;
115 void vscale(float *pix, unsigned char *npix, unsigned w, unsigned h, unsigned nh)
117 struct pix_desc *pd = (struct pix_desc *)malloc(nh * sizeof(struct pix_desc));
119 float *coeffs = (float *)malloc(size_coeffs * sizeof(float));
122 double sf = (double)h / (double)nh;
123 double support = 3.0 * sf;
125 /* calculate the filter */
126 for (y = 0; y < nh; ++y) {
127 int start = ceil(y * sf - support);
128 int end = floor(y * sf + support);
140 pd[y].startcoeff = num_coeffs;
142 for (sy = start; sy <= end; ++sy) {
143 double nd = sy/sf - y;
144 double f = lanczos_tap(nd);
145 if (num_coeffs == size_coeffs) {
147 coeffs = (float *)realloc(coeffs, size_coeffs * sizeof(float));
150 coeffs[num_coeffs++] = f;
154 for (sy = start; sy <= end; ++sy) {
155 coeffs[pd[y].startcoeff + sy - start] /= sum;
158 #if CACHE_LINE_FACTOR > 1
159 for (x = 0; x < w; x += CACHE_LINE_FACTOR) {
160 float *sptr = pix + x;
161 unsigned char *dptr = npix + x;
162 for (y = 0; y < nh; ++y) {
164 float acc[CACHE_LINE_FACTOR];
165 for (i = 0; i < CACHE_LINE_FACTOR; ++i)
167 float *cf = &coeffs[pd[y].startcoeff];
171 for (sy = pd[y].start; sy <= pd[y].end; ++sy) {
172 for (i = 0; i < CACHE_LINE_FACTOR; ++i) {
173 acc[i] += sptr[sy * w + i] * *cf;
178 for (i = 0; i < CACHE_LINE_FACTOR; ++i) {
181 else if (acc[i] > 255.0)
184 ch = (unsigned char)acc[i];
191 for (x = (x/CACHE_LINE_FACTOR)*CACHE_LINE_FACTOR; x < w; ++x) {
192 float *sptr = pix + x;
193 unsigned char *dptr = npix + x;
194 for (y = 0; y < nh; ++y) {
196 float *cf = &coeffs[pd[y].startcoeff];
200 for (sy = pd[y].start; sy <= pd[y].end; ++sy) {
201 acc += sptr[sy * w] * *cf++;
206 else if (acc > 255.0)
209 ch = (unsigned char)acc;
220 unsigned nw = 600, nh = 400;
224 unsigned char *npix2;
227 if (strcmp(buf, "P5") != 0) {
228 fprintf(stderr, "Error: Not a PGM file\n");
231 myreadline(buf); /* comment */
234 if (sscanf(buf, "%u %u", &w, &h) != 2) {
235 fprintf(stderr, "Error: Expected width/height\n");
240 if (strcmp(buf, "255") != 0) {
241 fprintf(stderr, "Error: Expected 8-bit\n");
245 pix = (unsigned char *)malloc(w * h);
251 if (fread(pix, w*h, 1, stdin) != 1) {
252 fprintf(stderr, "Error: Short read\n");
256 npix = (float *)malloc(sizeof(float) * nw * h);
261 npix2 = (unsigned char *)malloc(nw * nh);
267 hscale(pix, npix, w, h, nw);
268 vscale(npix, npix2, nw, h, nh);
270 printf("P5\n# COMMENT: Made by qscale\n%u %u\n255\n", nw, nh);
273 for (y = 0; y < nh; ++y) {
274 for (x = 0; x < nw; ++x) {
275 putchar(npix2[y * nw + x]);