1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
26 #include "core/GP_Pixmap.h"
27 #include "core/GP_GetPutPixel.h"
28 #include "core/GP_Gamma.h"
30 #include "core/GP_Debug.h"
32 #include "GP_ResizeCubic.h"
36 static float cubic(float x
)
42 return (2 - A
)*x
*x
*x
+ (A
- 3)*x
*x
+ 1;
45 return -A
*x
*x
*x
+ 5*A
*x
*x
- 8*A
*x
+ 4*A
;
50 typedef float v4sf
__attribute__ ((vector_size (sizeof(float) * 4)));
57 #define GP_USE_GCC_VECTOR
59 #ifdef GP_USE_GCC_VECTOR
60 #define MUL_V4SF(a, b) ({v4f ret; ret.v = (a).v * (b).v; ret;})
62 #define MUL_V4SF(a, b) ({v4f ret; \
63 ret.f[0] = (a).f[0] * (b).f[0]; \
64 ret.f[1] = (a).f[1] * (b).f[1]; \
65 ret.f[2] = (a).f[2] * (b).f[2]; \
66 ret.f[3] = (a).f[3] * (b).f[3]; \
68 #endif /* GP_USE_GCC_VECTOR */
70 #define SUM_V4SF(a) ((a).f[0] + (a).f[1] + (a).f[2] + (a).f[3])
72 #define CLAMP(val) do { \
79 int GP_FilterResizeCubic(const GP_Pixmap
*src
, GP_Pixmap
*dst
,
80 GP_ProgressCallback
*callback
)
82 float col_r
[src
->h
], col_g
[src
->h
], col_b
[src
->h
];
85 if (src
->pixel_type
!= GP_PIXEL_RGB888
|| dst
->pixel_type
!= GP_PIXEL_RGB888
) {
90 GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
91 src
->w
, src
->h
, dst
->w
, dst
->h
,
92 1.00 * dst
->w
/ src
->w
, 1.00 * dst
->h
/ src
->h
);
94 for (i
= 0; i
< dst
->w
; i
++) {
95 float x
= (1.00 * i
/ (dst
->w
- 1)) * (src
->w
- 1);
104 cvx
.f
[0] = cubic(xi
[0] - x
);
105 cvx
.f
[1] = cubic(xi
[1] - x
);
106 cvx
.f
[2] = cubic(xi
[2] - x
);
107 cvx
.f
[3] = cubic(xi
[3] - x
);
112 if (xi
[2] >= (int)src
->w
)
115 if (xi
[3] >= (int)src
->w
)
118 /* Generate interpolated column */
119 for (j
= 0; j
< src
->h
; j
++) {
123 pix
[0] = GP_GetPixel_Raw_24BPP(src
, xi
[0], j
);
124 pix
[1] = GP_GetPixel_Raw_24BPP(src
, xi
[1], j
);
125 pix
[2] = GP_GetPixel_Raw_24BPP(src
, xi
[2], j
);
126 pix
[3] = GP_GetPixel_Raw_24BPP(src
, xi
[3], j
);
128 rv
.f
[0] = GP_Pixel_GET_R_RGB888(pix
[0]);
129 rv
.f
[1] = GP_Pixel_GET_R_RGB888(pix
[1]);
130 rv
.f
[2] = GP_Pixel_GET_R_RGB888(pix
[2]);
131 rv
.f
[3] = GP_Pixel_GET_R_RGB888(pix
[3]);
133 gv
.f
[0] = GP_Pixel_GET_G_RGB888(pix
[0]);
134 gv
.f
[1] = GP_Pixel_GET_G_RGB888(pix
[1]);
135 gv
.f
[2] = GP_Pixel_GET_G_RGB888(pix
[2]);
136 gv
.f
[3] = GP_Pixel_GET_G_RGB888(pix
[3]);
138 bv
.f
[0] = GP_Pixel_GET_B_RGB888(pix
[0]);
139 bv
.f
[1] = GP_Pixel_GET_B_RGB888(pix
[1]);
140 bv
.f
[2] = GP_Pixel_GET_B_RGB888(pix
[2]);
141 bv
.f
[3] = GP_Pixel_GET_B_RGB888(pix
[3]);
143 rv
= MUL_V4SF(rv
, cvx
);
144 gv
= MUL_V4SF(gv
, cvx
);
145 bv
= MUL_V4SF(bv
, cvx
);
147 col_r
[j
] = SUM_V4SF(rv
);
148 col_g
[j
] = SUM_V4SF(gv
);
149 col_b
[j
] = SUM_V4SF(bv
);
152 /* now interpolate column for new image */
153 for (j
= 0; j
< dst
->h
; j
++) {
154 float y
= (1.00 * j
/ (dst
->h
- 1)) * (src
->h
- 1);
159 yi
[0] = floor(y
- 1);
164 cvy
.f
[0] = cubic(yi
[0] - y
);
165 cvy
.f
[1] = cubic(yi
[1] - y
);
166 cvy
.f
[2] = cubic(yi
[2] - y
);
167 cvy
.f
[3] = cubic(yi
[3] - y
);
172 if (yi
[2] >= (int)src
->h
)
175 if (yi
[3] >= (int)src
->h
)
178 rv
.f
[0] = col_r
[yi
[0]];
179 rv
.f
[1] = col_r
[yi
[1]];
180 rv
.f
[2] = col_r
[yi
[2]];
181 rv
.f
[3] = col_r
[yi
[3]];
183 gv
.f
[0] = col_g
[yi
[0]];
184 gv
.f
[1] = col_g
[yi
[1]];
185 gv
.f
[2] = col_g
[yi
[2]];
186 gv
.f
[3] = col_g
[yi
[3]];
188 bv
.f
[0] = col_b
[yi
[0]];
189 bv
.f
[1] = col_b
[yi
[1]];
190 bv
.f
[2] = col_b
[yi
[2]];
191 bv
.f
[3] = col_b
[yi
[3]];
193 rv
= MUL_V4SF(rv
, cvy
);
194 gv
= MUL_V4SF(gv
, cvy
);
195 bv
= MUL_V4SF(bv
, cvy
);
205 GP_Pixel pix
= GP_Pixel_CREATE_RGB888((uint8_t)r
, (uint8_t)g
, (uint8_t)b
);
206 GP_PutPixel_Raw_24BPP(dst
, i
, j
, pix
);
209 if (GP_ProgressCallbackReport(callback
, i
, dst
->w
, dst
->h
))
213 GP_ProgressCallbackDone(callback
);