1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Code for the scaling algorithm:
11 * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
12 * is by Willem Monsuwe <willem@stack.nl>. Additional modifications are by
13 * (C) Daniel M. Duley.
16 * Copyright (C) 2007 Jonas Hurrelmann (j@outpo.st)
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
24 ****************************************************************************/
27 * Copyright (C) 2004, 2005 Daniel M. Duley
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
40 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
43 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 * This is the normal smoothscale method, based on Imlib2's smoothscale.
56 * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
57 * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
58 * C algorithm and it ran at about the same speed as my MMX optimized one...
59 * Finally I ported Imlib's MMX version and it ran in less than half the
60 * time as my MMX algorithm, (taking only a quarter of the time Qt does).
61 * After further optimization it seems to run at around 1/6th.
63 * Changes include formatting, namespaces and other C++'ings, removal of old
64 * #ifdef'ed code, and removal of unneeded border calculation code.
66 * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
67 * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
68 * (C) Daniel M. Duley.
74 void smooth_resize_bitmap(struct bitmap
*src_bmp
, struct bitmap
*dest_bmp
)
79 const int sw
= src_bmp
->width
;
80 const int sh
= src_bmp
->height
;
81 const int dw
= dest_bmp
->width
;
82 const int dh
= dest_bmp
->height
;
83 const int inc_x
= (sw
<< 16) / dw
;
84 const int inc_y
= (sh
<< 16) / dh
;
85 const int Cp_x
= ((dw
<< 14) / sw
) + 1;
86 const int Cp_y
= ((dh
<< 14) / sh
) + 1;
87 const int xup_yup
= (dw
>= sw
) + ((dh
>= sh
) << 1);
90 fb_data
*src
= (fb_data
*)src_bmp
->data
;
91 fb_data
*dest
= (fb_data
*)dest_bmp
->data
;
92 int XAP
, YAP
, INV_YAP
, INV_XAP
;
97 /* scaling up both ways */
99 /* go through every scanline in the output buffer */
100 for (y
= 0; y
< dh
; y
++) {
101 /* calculate the source line we'll scan from */
102 ypoint
= src
+ ((val_y
>> 16) * sw
);
103 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
109 dptr
= dest
+ (y
* dow
);
112 for (x
= 0; x
< end
; x
++) {
113 int r
= 0, g
= 0, b
= 0;
114 int rr
= 0, gg
= 0, bb
= 0;
117 xpoint
= (val_x
>> 16);
118 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
123 pix
= ypoint
+ xpoint
;
124 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
125 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
126 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
128 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
129 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
130 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
132 rr
= RGB_UNPACK_RED(*pix
) * XAP
;
133 gg
= RGB_UNPACK_GREEN(*pix
) * XAP
;
134 bb
= RGB_UNPACK_BLUE(*pix
) * XAP
;
136 rr
+= RGB_UNPACK_RED(*pix
) * INV_XAP
;
137 gg
+= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
138 bb
+= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
139 r
= ((rr
* YAP
) + (r
* INV_YAP
)) >> 16;
140 g
= ((gg
* YAP
) + (g
* INV_YAP
)) >> 16;
141 b
= ((bb
* YAP
) + (b
* INV_YAP
)) >> 16;
142 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
144 pix
= ypoint
+ xpoint
;
145 r
= RGB_UNPACK_RED(*pix
) * INV_YAP
;
146 g
= RGB_UNPACK_GREEN(*pix
) * INV_YAP
;
147 b
= RGB_UNPACK_BLUE(*pix
) * INV_YAP
;
149 r
+= RGB_UNPACK_RED(*pix
) * YAP
;
150 g
+= RGB_UNPACK_GREEN(*pix
) * YAP
;
151 b
+= RGB_UNPACK_BLUE(*pix
) * YAP
;
155 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
159 for (x
= 0; x
< end
; x
++) {
160 int r
= 0, g
= 0, b
= 0;
163 xpoint
= (val_x
>> 16);
164 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
169 pix
= ypoint
+ xpoint
;
170 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
171 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
172 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
174 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
175 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
176 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
180 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
182 *dptr
++ = sptr
[xpoint
];
187 /* if we're scaling down vertically */
188 else if (xup_yup
== 1) {
189 /*\ 'Correct' version, with math units prepared for MMXification \ */
192 int r
, g
, b
, rr
, gg
, bb
;
195 /* go through every scanline in the output buffer */
196 for (y
= 0; y
< dh
; y
++) {
197 ypoint
= src
+ ((val_y
>> 16) * sw
);
198 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
207 dptr
= dest
+ (y
* dow
);
208 for (x
= 0; x
< end
; x
++) {
209 xpoint
= (val_x
>> 16);
210 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
214 pix
= ypoint
+ xpoint
;
215 r
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
216 g
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
217 b
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
219 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
220 r
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
221 g
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
222 b
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
226 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
227 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
228 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
231 pix
= ypoint
+ xpoint
+ 1;
232 rr
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
233 gg
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
234 bb
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
236 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
237 rr
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
238 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
239 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
243 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
244 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
245 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
250 r
= (r
+ ((rr
* XAP
))) >> 12;
251 g
= (g
+ ((gg
* XAP
))) >> 12;
252 b
= (b
+ ((bb
* XAP
))) >> 12;
258 *dptr
= LCD_RGBPACK(r
, g
, b
);
263 /* if we're scaling down horizontally */
264 else if (xup_yup
== 2) {
265 /*\ 'Correct' version, with math units prepared for MMXification \ */
268 int r
, g
, b
, rr
, gg
, bb
;
271 /* go through every scanline in the output buffer */
272 for (y
= 0; y
< dh
; y
++) {
273 ypoint
= src
+ ((val_y
>> 16) * sw
);
274 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
279 dptr
= dest
+ (y
* dow
);
280 for (x
= 0; x
< end
; x
++) {
281 xpoint
= (val_x
>> 16);
282 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
290 pix
= ypoint
+ xpoint
;
291 r
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
292 g
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
293 b
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
295 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
296 r
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
297 g
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
298 b
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
302 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
303 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
304 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
307 pix
= ypoint
+ xpoint
+ sow
;
308 rr
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
309 gg
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
310 bb
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
312 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
313 rr
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
314 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
315 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
319 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
320 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
321 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
326 r
= (r
+ ((rr
* YAP
))) >> 12;
327 g
= (g
+ ((gg
* YAP
))) >> 12;
328 b
= (b
+ ((bb
* YAP
))) >> 12;
334 *dptr
= LCD_RGBPACK(r
, g
, b
);
339 /* fully optimized (i think) - only change of algorithm can help */
340 /* if we're scaling down horizontally & vertically */
342 /*\ 'Correct' version, with math units prepared for MMXification \ */
345 int r
, g
, b
, rx
, gx
, bx
;
348 for (y
= 0; y
< dh
; y
++) {
349 ypoint
= src
+ ((val_y
>> 16) * sw
);
350 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
358 dptr
= dest
+ (y
* dow
);
359 for (x
= 0; x
< end
; x
++) {
360 xpoint
= (val_x
>> 16);
361 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
368 sptr
= ypoint
+ xpoint
;
372 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
373 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
374 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
376 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
377 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
378 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
379 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
383 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
384 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
385 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
388 r
= (rx
* yap
) >> 14;
389 g
= (gx
* yap
) >> 14;
390 b
= (bx
* yap
) >> 14;
392 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
395 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
396 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
397 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
399 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
400 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
401 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
402 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
406 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
407 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
408 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
411 r
+= (rx
* Cy
) >> 14;
412 g
+= (gx
* Cy
) >> 14;
413 b
+= (bx
* Cy
) >> 14;
418 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
419 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
420 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
422 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
423 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
424 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
425 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
429 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
430 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
431 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
439 *dptr
= LCD_RGBPACK(r
>> 5, g
>> 5, b
>> 5);