Rename GP_Context -> GP_Pixmap
[gfxprim.git] / libs / filters / GP_ResizeCubic.gen.c.t
blob3f358d4fe5fa73dbf36914b69336c5b1d3605373
1 @ include source.t
2 /*
3  * Cubic resampling
4  *
5  * Copyright (C) 2009-2014 Cyril Hrubis <metan@ucw.cz>
6  */
8 #include <errno.h>
9 #include <math.h>
11 #include "core/GP_Pixmap.h"
12 #include "core/GP_GetPutPixel.h"
13 #include "core/GP_Gamma.h"
14 #include "core/GP_Clamp.h"
15 #include "core/GP_Debug.h"
17 #include "GP_Cubic.h"
19 #include "GP_Resize.h"
21 #define MUL 1024
23 #define MUL_I(a, b) ({ \
24         a[0] *= b[0]; \
25         a[1] *= b[1]; \
26         a[2] *= b[2]; \
27         a[3] *= b[3]; \
30 #define SUM_I(a) \
31         ((a)[0] + (a)[1] + (a)[2] + (a)[3])
33 @ for pt in pixeltypes:
34 @     if not pt.is_unknown() and not pt.is_palette():
35 static int resize_cubic_{{ pt.name }}(const GP_Pixmap *src,
36         GP_Pixmap *dst, GP_ProgressCallback *callback)
38 @         for c in pt.chanslist:
39         int32_t col_{{ c.name }}[src->w];
40 @         end
42         uint32_t i, j;
44         GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
45                     src->w, src->h, dst->w, dst->h,
46                     1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
48         {@ fetch_gamma_tables(pt, "src") @}
50         /* pre-generate x mapping and constants */
51         int32_t xmap[dst->w][4];
52         int32_t xmap_c[dst->w][4];
54         for (i = 0; i < dst->w; i++) {
55                 float x = (1.00 * i / (dst->w - 1)) * (src->w - 1);
57                 xmap[i][0] = floor(x - 1);
58                 xmap[i][1] = x;
59                 xmap[i][2] = x + 1;
60                 xmap[i][3] = x + 2;
62                 xmap_c[i][0] = cubic_int((xmap[i][0] - x) * MUL + 0.5);
63                 xmap_c[i][1] = cubic_int((xmap[i][1] - x) * MUL + 0.5);
64                 xmap_c[i][2] = cubic_int((xmap[i][2] - x) * MUL + 0.5);
65                 xmap_c[i][3] = cubic_int((xmap[i][3] - x) * MUL + 0.5);
67                 xmap[i][0] = GP_MAX(xmap[i][0], 0);
68                 xmap[i][2] = GP_MIN(xmap[i][2], (int)src->w - 1);
69                 xmap[i][3] = GP_MIN(xmap[i][3], (int)src->w - 1);
70         }
72         /* cubic resampling */
73         for (i = 0; i < dst->h; i++) {
74                 float y = (1.00 * i / (dst->h - 1)) * (src->h - 1);
75                 int32_t cvy[4];
76                 int yi[4];
78                 yi[0] = floor(y - 1);
79                 yi[1] = y;
80                 yi[2] = y + 1;
81                 yi[3] = y + 2;
83                 cvy[0] = cubic_int((yi[0] - y) * MUL + 0.5);
84                 cvy[1] = cubic_int((yi[1] - y) * MUL + 0.5);
85                 cvy[2] = cubic_int((yi[2] - y) * MUL + 0.5);
86                 cvy[3] = cubic_int((yi[3] - y) * MUL + 0.5);
88                 yi[0] = GP_MAX(yi[0], 0);
89                 yi[2] = GP_MIN(yi[2], (int)src->h - 1);
90                 yi[3] = GP_MIN(yi[3], (int)src->h - 1); 
92                 /* Generate interpolated row */
93                 for (j = 0; j < src->w; j++) {
94 @         for c in pt.chanslist:
95                         int32_t {{ c.name }}v[4];
96 @         end
97                         GP_Pixel pix[4];
99                         pix[0] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[0]);
100                         pix[1] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[1]);
101                         pix[2] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[2]);
102                         pix[3] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[3]);
104 @         for c in pt.chanslist:
105                         {{ c.name }}v[0] = GP_Pixel_GET_{{ c.name }}_{{ pt.name }}(pix[0]);
106                         {{ c.name }}v[1] = GP_Pixel_GET_{{ c.name }}_{{ pt.name }}(pix[1]);
107                         {{ c.name }}v[2] = GP_Pixel_GET_{{ c.name }}_{{ pt.name }}(pix[2]);
108                         {{ c.name }}v[3] = GP_Pixel_GET_{{ c.name }}_{{ pt.name }}(pix[3]);
109 @         end
111                         if (src->gamma) {
112 @         for c in pt.chanslist:
113                                 {{ c.name }}v[0] = {{ c.name }}_2_LIN[{{ c.name }}v[0]];
114                                 {{ c.name }}v[1] = {{ c.name }}_2_LIN[{{ c.name }}v[1]];
115                                 {{ c.name }}v[2] = {{ c.name }}_2_LIN[{{ c.name }}v[2]];
116                                 {{ c.name }}v[3] = {{ c.name }}_2_LIN[{{ c.name }}v[3]];
117 @         end
118                         }
120 @         for c in pt.chanslist:
121                         MUL_I({{ c.name }}v, cvy);
122 @         end
124 @         for c in pt.chanslist:
125                         col_{{ c.name }}[j] = SUM_I({{ c.name }}v);
126 @         end
127                 }
129                 /* now interpolate column for new image */
130                 for (j = 0; j < dst->w; j++) {
131 @         for c in pt.chanslist:
132                         int32_t {{ c.name }}v[4];
133                         int32_t {{ c.name }};
134 @         end
136 @         for c in pt.chanslist:
137                         {{ c.name }}v[0] = col_{{ c.name }}[xmap[j][0]];
138                         {{ c.name }}v[1] = col_{{ c.name }}[xmap[j][1]];
139                         {{ c.name }}v[2] = col_{{ c.name }}[xmap[j][2]];
140                         {{ c.name }}v[3] = col_{{ c.name }}[xmap[j][3]];
141 @         end
143 @         for c in pt.chanslist:
144                         MUL_I({{ c.name }}v, xmap_c[j]);
145 @         end
147 @         for c in pt.chanslist:
148                         {{ c.name }} = (SUM_I({{ c.name }}v) + MUL*MUL/2) / MUL / MUL;
149 @         end
151                         if (src->gamma) {
152 @         for c in pt.chanslist:
153                                 {{ c.name }} = GP_CLAMP_GENERIC({{ c.name }}, 0, {{ 2 ** (c[2] + 2) - 1 }});
154 @         end
155 @         for c in pt.chanslist:
156                                 {{ c.name }} = {{ c.name }}_2_GAMMA[{{ c.name }}];
157 @         end
158                         } else {
159 @         for c in pt.chanslist:
160                                 {{ c.name }} = GP_CLAMP_GENERIC({{ c.name }}, 0, {{ 2 ** c[2] - 1 }});
161 @         end
162                         }
164                         GP_Pixel pix = GP_Pixel_CREATE_{{ pt.name }}({{ arr_to_params(pt.chan_names, "(uint8_t)") }});
165                         GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, j, i, pix);
166                 }
168                 if (GP_ProgressCallbackReport(callback, i, dst->h, dst->w))
169                         return 1;
170         }
172         GP_ProgressCallbackDone(callback);
173         return 0;
176 @ end
178 static int resize_cubic(const GP_Pixmap *src, GP_Pixmap *dst,
179                         GP_ProgressCallback *callback)
181         switch (src->pixel_type) {
182 @ for pt in pixeltypes:
183 @     if not pt.is_unknown() and not pt.is_palette():
184         case GP_PIXEL_{{ pt.name }}:
185                 return resize_cubic_{{ pt.name }}(src, dst, callback);
186         break;
187 @ end
188         default:
189                 errno = EINVAL;
190                 return -1;
191         }
194 int GP_FilterResizeCubicInt(const GP_Pixmap *src, GP_Pixmap *dst,
195                             GP_ProgressCallback *callback)
197         if (src->pixel_type != dst->pixel_type) {
198                 GP_WARN("The src and dst pixel types must match");
199                 errno = EINVAL;
200                 return 1;
201         }
203         return resize_cubic(src, dst, callback);