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 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
26 ****************************************************************************/
29 * Copyright (C) 2004, 2005 Daniel M. Duley
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
42 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
45 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
50 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 * This is the normal smoothscale method, based on Imlib2's smoothscale.
58 * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
59 * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
60 * C algorithm and it ran at about the same speed as my MMX optimized one...
61 * Finally I ported Imlib's MMX version and it ran in less than half the
62 * time as my MMX algorithm, (taking only a quarter of the time Qt does).
63 * After further optimization it seems to run at around 1/6th.
65 * Changes include formatting, namespaces and other C++'ings, removal of old
66 * #ifdef'ed code, and removal of unneeded border calculation code.
68 * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
69 * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
70 * (C) Daniel M. Duley.
73 #include "pluginlib_bmp.h"
76 void smooth_resize_bitmap(struct bitmap
*src_bmp
, struct bitmap
*dest_bmp
)
81 const int sw
= src_bmp
->width
;
82 const int sh
= src_bmp
->height
;
83 const int dw
= dest_bmp
->width
;
84 const int dh
= dest_bmp
->height
;
85 const int inc_x
= (sw
<< 16) / dw
;
86 const int inc_y
= (sh
<< 16) / dh
;
87 const int Cp_x
= ((dw
<< 14) / sw
) + 1;
88 const int Cp_y
= ((dh
<< 14) / sh
) + 1;
89 const int xup_yup
= (dw
>= sw
) + ((dh
>= sh
) << 1);
92 fb_data
*src
= (fb_data
*)src_bmp
->data
;
93 fb_data
*dest
= (fb_data
*)dest_bmp
->data
;
94 int XAP
, YAP
, INV_YAP
, INV_XAP
;
99 /* scaling up both ways */
101 /* go through every scanline in the output buffer */
102 for (y
= 0; y
< dh
; y
++) {
103 /* calculate the source line we'll scan from */
104 ypoint
= src
+ ((val_y
>> 16) * sw
);
105 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
111 dptr
= dest
+ (y
* dow
);
114 for (x
= 0; x
< end
; x
++) {
115 int r
= 0, g
= 0, b
= 0;
116 int rr
= 0, gg
= 0, bb
= 0;
119 xpoint
= (val_x
>> 16);
120 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
125 pix
= ypoint
+ xpoint
;
126 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
127 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
128 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
130 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
131 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
132 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
134 rr
= RGB_UNPACK_RED(*pix
) * XAP
;
135 gg
= RGB_UNPACK_GREEN(*pix
) * XAP
;
136 bb
= RGB_UNPACK_BLUE(*pix
) * XAP
;
138 rr
+= RGB_UNPACK_RED(*pix
) * INV_XAP
;
139 gg
+= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
140 bb
+= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
141 r
= ((rr
* YAP
) + (r
* INV_YAP
)) >> 16;
142 g
= ((gg
* YAP
) + (g
* INV_YAP
)) >> 16;
143 b
= ((bb
* YAP
) + (b
* INV_YAP
)) >> 16;
144 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
146 pix
= ypoint
+ xpoint
;
147 r
= RGB_UNPACK_RED(*pix
) * INV_YAP
;
148 g
= RGB_UNPACK_GREEN(*pix
) * INV_YAP
;
149 b
= RGB_UNPACK_BLUE(*pix
) * INV_YAP
;
151 r
+= RGB_UNPACK_RED(*pix
) * YAP
;
152 g
+= RGB_UNPACK_GREEN(*pix
) * YAP
;
153 b
+= RGB_UNPACK_BLUE(*pix
) * YAP
;
157 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
161 for (x
= 0; x
< end
; x
++) {
162 int r
= 0, g
= 0, b
= 0;
165 xpoint
= (val_x
>> 16);
166 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
171 pix
= ypoint
+ xpoint
;
172 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
173 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
174 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
176 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
177 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
178 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
182 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
184 *dptr
++ = sptr
[xpoint
];
189 /* if we're scaling down vertically */
190 else if (xup_yup
== 1) {
191 /*\ 'Correct' version, with math units prepared for MMXification \ */
194 int r
, g
, b
, rr
, gg
, bb
;
197 /* go through every scanline in the output buffer */
198 for (y
= 0; y
< dh
; y
++) {
199 ypoint
= src
+ ((val_y
>> 16) * sw
);
200 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
209 dptr
= dest
+ (y
* dow
);
210 for (x
= 0; x
< end
; x
++) {
211 xpoint
= (val_x
>> 16);
212 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
216 pix
= ypoint
+ xpoint
;
217 r
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
218 g
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
219 b
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
221 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
222 r
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
223 g
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
224 b
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
228 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
229 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
230 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
233 pix
= ypoint
+ xpoint
+ 1;
234 rr
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
235 gg
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
236 bb
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
238 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
239 rr
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
240 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
241 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
245 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
246 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
247 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
252 r
= (r
+ ((rr
* XAP
))) >> 12;
253 g
= (g
+ ((gg
* XAP
))) >> 12;
254 b
= (b
+ ((bb
* XAP
))) >> 12;
260 *dptr
= LCD_RGBPACK(r
, g
, b
);
265 /* if we're scaling down horizontally */
266 else if (xup_yup
== 2) {
267 /*\ 'Correct' version, with math units prepared for MMXification \ */
270 int r
, g
, b
, rr
, gg
, bb
;
273 /* go through every scanline in the output buffer */
274 for (y
= 0; y
< dh
; y
++) {
275 ypoint
= src
+ ((val_y
>> 16) * sw
);
276 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
281 dptr
= dest
+ (y
* dow
);
282 for (x
= 0; x
< end
; x
++) {
283 xpoint
= (val_x
>> 16);
284 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
292 pix
= ypoint
+ xpoint
;
293 r
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
294 g
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
295 b
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
297 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
298 r
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
299 g
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
300 b
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
304 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
305 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
306 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
309 pix
= ypoint
+ xpoint
+ sow
;
310 rr
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
311 gg
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
312 bb
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
314 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
315 rr
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
316 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
317 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
321 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
322 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
323 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
328 r
= (r
+ ((rr
* YAP
))) >> 12;
329 g
= (g
+ ((gg
* YAP
))) >> 12;
330 b
= (b
+ ((bb
* YAP
))) >> 12;
336 *dptr
= LCD_RGBPACK(r
, g
, b
);
341 /* fully optimized (i think) - only change of algorithm can help */
342 /* if we're scaling down horizontally & vertically */
344 /*\ 'Correct' version, with math units prepared for MMXification \ */
347 int r
, g
, b
, rx
, gx
, bx
;
350 for (y
= 0; y
< dh
; y
++) {
351 ypoint
= src
+ ((val_y
>> 16) * sw
);
352 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
360 dptr
= dest
+ (y
* dow
);
361 for (x
= 0; x
< end
; x
++) {
362 xpoint
= (val_x
>> 16);
363 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
370 sptr
= ypoint
+ xpoint
;
374 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
375 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
376 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
378 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
379 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
380 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
381 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
385 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
386 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
387 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
390 r
= (rx
* yap
) >> 14;
391 g
= (gx
* yap
) >> 14;
392 b
= (bx
* yap
) >> 14;
394 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
397 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
398 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
399 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
401 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
402 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
403 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
404 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
408 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
409 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
410 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
413 r
+= (rx
* Cy
) >> 14;
414 g
+= (gx
* Cy
) >> 14;
415 b
+= (bx
* Cy
) >> 14;
420 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
421 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
422 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
424 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
425 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
426 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
427 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
431 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
432 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
433 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
441 *dptr
= LCD_RGBPACK(r
>> 5, g
>> 5, b
>> 5);