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(float *pix, unsigned char *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 = (w > nw) ? (3.0 * sf) : (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 = (w > nw) ? (sx/sf - x) : (sx - x*sf);
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 float *sptr = pix + y*w;
101 unsigned char *dptr = npix + y*nw;
102 for (x = 0; x < nw; ++x) {
104 float *cf = &coeffs[pd[x].startcoeff];
108 for (sx = pd[x].start; sx <= pd[x].end; ++sx) {
109 acc += sptr[sx] * *cf++;
114 else if (acc > 255.0)
117 ch = (unsigned char)acc;
123 void vscale(unsigned char *pix, float *npix, unsigned w, unsigned h, unsigned nh)
125 struct pix_desc *pd = (struct pix_desc *)malloc(nh * sizeof(struct pix_desc));
127 float *coeffs = (float *)malloc(size_coeffs * sizeof(float));
130 double sf = (double)h / (double)nh;
131 double support = (h > nh) ? (3.0 * sf) : (3.0 / sf);
133 /* calculate the filter */
134 for (y = 0; y < nh; ++y) {
135 int start = ceil(y * sf - support);
136 int end = floor(y * sf + support);
148 pd[y].startcoeff = num_coeffs;
150 for (sy = start; sy <= end; ++sy) {
151 double nd = (h > nh) ? (sy/sf - y) : (sy - y*sf);
152 double f = lanczos_tap(nd);
153 if (num_coeffs == size_coeffs) {
155 coeffs = (float *)realloc(coeffs, size_coeffs * sizeof(float));
158 coeffs[num_coeffs++] = f;
162 for (sy = start; sy <= end; ++sy) {
163 coeffs[pd[y].startcoeff + sy - start] /= sum;
167 #if CACHE_LINE_FACTOR > 1
168 for (x = 0; x < w; x += CACHE_LINE_FACTOR) {
169 unsigned char *sptr = pix + x;
170 float *dptr = npix + x;
171 for (y = 0; y < nh; ++y) {
173 float acc[CACHE_LINE_FACTOR];
174 for (i = 0; i < CACHE_LINE_FACTOR; ++i)
176 float *cf = &coeffs[pd[y].startcoeff];
179 for (sy = pd[y].start; sy <= pd[y].end; ++sy) {
180 for (i = 0; i < CACHE_LINE_FACTOR; ++i) {
181 acc[i] += sptr[sy * w + i] * *cf;
186 for (i = 0; i < CACHE_LINE_FACTOR; ++i) {
192 for (x = (x/CACHE_LINE_FACTOR)*CACHE_LINE_FACTOR; x < w; ++x) {
194 for (x = 0; x < w; ++x) {
196 unsigned char *sptr = pix + x;
197 float *dptr = npix + x;
198 for (y = 0; y < nh; ++y) {
200 float *cf = &coeffs[pd[y].startcoeff];
203 for (sy = pd[y].start; sy <= pd[y].end; ++sy) {
204 acc += sptr[sy * w] * *cf++;
216 unsigned nw = 600, nh = 400;
217 //unsigned nw = 3504, nh = 2336;
221 unsigned char *npix2;
224 if (strcmp(buf, "P5") != 0) {
225 fprintf(stderr, "Error: Not a PGM file\n");
228 myreadline(buf); /* comment */
231 if (sscanf(buf, "%u %u", &w, &h) != 2) {
232 fprintf(stderr, "Error: Expected width/height\n");
237 if (strcmp(buf, "255") != 0) {
238 fprintf(stderr, "Error: Expected 8-bit\n");
242 pix = (unsigned char *)malloc(w * h);
248 if (fread(pix, w*h, 1, stdin) != 1) {
249 fprintf(stderr, "Error: Short read\n");
253 npix = (float *)malloc(sizeof(float) * nw * h);
258 npix2 = (unsigned char *)malloc(nw * nh);
264 vscale(pix, npix, w, h, nh);
265 hscale(npix, npix2, w, nh, nw);
267 printf("P5\n# COMMENT: Made by qscale\n%u %u\n255\n", nw, nh);
270 for (y = 0; y < nh; ++y) {
271 for (x = 0; x < nw; ++x) {
272 putchar(npix2[y * nw + x]);