2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License as published
4 * by the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public
13 * License along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 /* fractional input interpolation
23 interp = nearest, bi_linear, bi_cubic
26 type **in_rows = (type**)in->get_rows();
27 type **out_rows = (type**)out->get_rows();
28 int ow = out->get_w(), oh = out->get_h();
29 type offset[4] = { 0, chroma, chroma, 0 };
30 type bkgrnd[4] = { 0, chroma, chroma, 0 };
31 INTERP_SETUP(in_rows, max, 0,0, width,height);
33 for( int oy=0; oy<oh; ++oy ) {
34 type *out_row = out_rows[y];
35 for( ox=0; ox<ow; ++ox ) {
36 float x_in = remap_x(ox,oy), y_in = remap_y(ox,oy);
37 interp##_SETUP(type, components, x_in, y_in); \
38 *out_row++ = interp##_interp(offset[i], bkgrnd[i]); \
39 for( int i=1; i<components; ++i ) {
41 *out_row++ = interp##_interp(offset[i], bkgrnd[i]); \
47 static inline float in_clip(float v, float mx)
49 return v < 0 ? 0 : v > mx ? mx : v;
52 static inline float interp_linear(float dx, float p1, float p2)
54 return p1 * (1-dx) + p2 * dx;
57 static inline float interp_cubic(float dx, float p0, float p1, float p2, float p3)
58 { /* Catmull-Rom - not bad */
59 return ((( (- p0 + 3*p1 - 3*p2 + p3) * dx +
60 ( 2*p0 - 5*p1 + 4*p2 - p3 ) ) * dx +
61 ( - p0 + p2 ) ) * dx + (p1 + p1)) / 2;
65 #define INTERP_SETUP(rows, max, x_in_min,y_in_min, x_in_max,y_in_max) \
66 void **interp_rows = (void **)(rows); float in_max = (max); \
67 int in_min_x = (x_in_min), in_max_x = (x_in_max); \
68 int in_min_y = (y_in_min), in_max_y = (y_in_max)
71 #define nearest_SETUP(typ, components, tx, ty) \
72 int itx = (tx), ity = (ty), in_comps = (components); \
73 int c0 = itx+0, r0 = ity+0; \
74 typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0
76 #define NEAREST_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : ( \
77 (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs))
79 #define nearest_interp(ofs, bg) in_clip(NEAREST_ROW(r0p, ofs, bg) + ofs, in_max)
81 #define nearest_next(s) { if(r0p) ++r0p; }
84 #define bi_linear_SETUP(typ, components, tx, ty) \
85 const int in_comps = components; \
86 float fx = (tx), fy = (ty); \
87 int c0 = floorf(fx), r0 = floorf(fy); \
88 float dx = fx-c0, dy = fy-r0; \
89 int c1 = c0+1, r1 = r0+1; \
90 typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0; \
91 typ *r1p = r1>=in_min_y && r1<in_max_y ? ((typ**)interp_rows)[r1] : 0
93 #define LINEAR_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : interp_linear(dx, \
94 (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs, \
95 (c1>=in_min_x && c1<in_max_x ? in_row[c1*in_comps] : bg) - ofs))
97 #define bi_linear_interp(ofs, bg) in_clip(interp_linear(dy, \
98 LINEAR_ROW(r0p, ofs, bg), LINEAR_ROW(r1p, ofs, bg)) + ofs, in_max)
100 #define bi_linear_next(s) { if(r0p) ++r0p; if(r1p) ++r1p; }
103 #define bi_cubic_SETUP(typ, components, tx, ty) \
104 const int in_comps = components; \
105 float fx = (tx), fy = (ty); \
106 int c0 = floorf(fx), r0 = floorf(fy); \
107 float dx = fx-c0, dy = fy-r0; \
108 int cp = c0-1, c1 = c0+1, c2 = c0+2; \
109 int rp = r0-1, r1 = r0+1, r2 = r0+2; \
110 typ *rpp = rp>=in_min_y && rp<in_max_y ? ((typ**)interp_rows)[rp] : 0; \
111 typ *r0p = r0>=in_min_y && r0<in_max_y ? ((typ**)interp_rows)[r0] : 0; \
112 typ *r1p = r1>=in_min_y && r1<in_max_y ? ((typ**)interp_rows)[r1] : 0; \
113 typ *r2p = r2>=in_min_y && r2<in_max_y ? ((typ**)interp_rows)[r2] : 0
115 #define CUBIC_ROW(in_row, ofs, bg) (!in_row ? bg - ofs : interp_cubic(dx, \
116 (cp>=in_min_x && cp<in_max_x ? in_row[cp*in_comps] : bg) - ofs, \
117 (c0>=in_min_x && c0<in_max_x ? in_row[c0*in_comps] : bg) - ofs, \
118 (c1>=in_min_x && c1<in_max_x ? in_row[c1*in_comps] : bg) - ofs, \
119 (c2>=in_min_x && c2<in_max_x ? in_row[c2*in_comps] : bg) - ofs))
121 #define bi_cubic_interp(ofs, bg) in_clip(interp_cubic(dy, \
122 CUBIC_ROW(rpp, ofs, bg), CUBIC_ROW(r0p, ofs, bg), \
123 CUBIC_ROW(r1p, ofs, bg), CUBIC_ROW(r2p, ofs, bg)) + ofs, in_max)
125 #define bi_cubic_next(s) { if(rpp) ++rpp; if(r0p) ++r0p; if(r1p) ++r1p; if(r2p) ++r2p; }