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 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
82 const int sw
= src_bmp
->height
;
83 const int sh
= src_bmp
->width
;
84 const int dw
= dest_bmp
->height
;
85 const int dh
= dest_bmp
->width
;
87 const int sw
= src_bmp
->width
;
88 const int sh
= src_bmp
->height
;
89 const int dw
= dest_bmp
->width
;
90 const int dh
= dest_bmp
->height
;
92 const int inc_x
= (sw
<< 16) / dw
;
93 const int inc_y
= (sh
<< 16) / dh
;
94 const int Cp_x
= ((dw
<< 14) / sw
) + 1;
95 const int Cp_y
= ((dh
<< 14) / sh
) + 1;
96 const int xup_yup
= (dw
>= sw
) + ((dh
>= sh
) << 1);
99 fb_data
*src
= (fb_data
*)src_bmp
->data
;
100 fb_data
*dest
= (fb_data
*)dest_bmp
->data
;
101 int XAP
, YAP
, INV_YAP
, INV_XAP
;
106 /* scaling up both ways */
108 /* go through every scanline in the output buffer */
109 for (y
= 0; y
< dh
; y
++) {
110 /* calculate the source line we'll scan from */
111 ypoint
= src
+ ((val_y
>> 16) * sw
);
112 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
118 dptr
= dest
+ (y
* dow
);
121 for (x
= 0; x
< end
; x
++) {
122 int r
= 0, g
= 0, b
= 0;
123 int rr
= 0, gg
= 0, bb
= 0;
126 xpoint
= (val_x
>> 16);
127 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
132 pix
= ypoint
+ xpoint
;
133 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
134 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
135 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
137 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
138 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
139 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
141 rr
= RGB_UNPACK_RED(*pix
) * XAP
;
142 gg
= RGB_UNPACK_GREEN(*pix
) * XAP
;
143 bb
= RGB_UNPACK_BLUE(*pix
) * XAP
;
145 rr
+= RGB_UNPACK_RED(*pix
) * INV_XAP
;
146 gg
+= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
147 bb
+= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
148 r
= ((rr
* YAP
) + (r
* INV_YAP
)) >> 16;
149 g
= ((gg
* YAP
) + (g
* INV_YAP
)) >> 16;
150 b
= ((bb
* YAP
) + (b
* INV_YAP
)) >> 16;
151 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
153 pix
= ypoint
+ xpoint
;
154 r
= RGB_UNPACK_RED(*pix
) * INV_YAP
;
155 g
= RGB_UNPACK_GREEN(*pix
) * INV_YAP
;
156 b
= RGB_UNPACK_BLUE(*pix
) * INV_YAP
;
158 r
+= RGB_UNPACK_RED(*pix
) * YAP
;
159 g
+= RGB_UNPACK_GREEN(*pix
) * YAP
;
160 b
+= RGB_UNPACK_BLUE(*pix
) * YAP
;
164 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
168 for (x
= 0; x
< end
; x
++) {
169 int r
= 0, g
= 0, b
= 0;
172 xpoint
= (val_x
>> 16);
173 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
178 pix
= ypoint
+ xpoint
;
179 r
= RGB_UNPACK_RED(*pix
) * INV_XAP
;
180 g
= RGB_UNPACK_GREEN(*pix
) * INV_XAP
;
181 b
= RGB_UNPACK_BLUE(*pix
) * INV_XAP
;
183 r
+= RGB_UNPACK_RED(*pix
) * XAP
;
184 g
+= RGB_UNPACK_GREEN(*pix
) * XAP
;
185 b
+= RGB_UNPACK_BLUE(*pix
) * XAP
;
189 *dptr
++ = LCD_RGBPACK(r
, g
, b
);
191 *dptr
++ = sptr
[xpoint
];
196 /* if we're scaling down vertically */
197 else if (xup_yup
== 1) {
198 /*\ 'Correct' version, with math units prepared for MMXification \ */
201 int r
, g
, b
, rr
, gg
, bb
;
204 /* go through every scanline in the output buffer */
205 for (y
= 0; y
< dh
; y
++) {
206 ypoint
= src
+ ((val_y
>> 16) * sw
);
207 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
216 dptr
= dest
+ (y
* dow
);
217 for (x
= 0; x
< end
; x
++) {
218 xpoint
= (val_x
>> 16);
219 XAP
= ((val_x
>> 16) >= (sw
- 1)) ? 0 : (val_x
>> 8) - ((val_x
>> 8) & 0xffffff00);
223 pix
= ypoint
+ xpoint
;
224 r
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
225 g
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
226 b
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
228 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
229 r
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
230 g
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
231 b
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
235 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
236 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
237 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
240 pix
= ypoint
+ xpoint
+ 1;
241 rr
= (RGB_UNPACK_RED(*pix
) * yap
) >> 10;
242 gg
= (RGB_UNPACK_GREEN(*pix
) * yap
) >> 10;
243 bb
= (RGB_UNPACK_BLUE(*pix
) * yap
) >> 10;
245 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
246 rr
+= (RGB_UNPACK_RED(*pix
) * Cy
) >> 10;
247 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cy
) >> 10;
248 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cy
) >> 10;
252 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
253 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
254 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
259 r
= (r
+ ((rr
* XAP
))) >> 12;
260 g
= (g
+ ((gg
* XAP
))) >> 12;
261 b
= (b
+ ((bb
* XAP
))) >> 12;
267 *dptr
= LCD_RGBPACK(r
, g
, b
);
272 /* if we're scaling down horizontally */
273 else if (xup_yup
== 2) {
274 /*\ 'Correct' version, with math units prepared for MMXification \ */
277 int r
, g
, b
, rr
, gg
, bb
;
280 /* go through every scanline in the output buffer */
281 for (y
= 0; y
< dh
; y
++) {
282 ypoint
= src
+ ((val_y
>> 16) * sw
);
283 YAP
= ((val_y
>> 16) >= (sh
- 1)) ? 0 : (val_y
>> 8) - ((val_y
>> 8) & 0xffffff00);
288 dptr
= dest
+ (y
* dow
);
289 for (x
= 0; x
< end
; x
++) {
290 xpoint
= (val_x
>> 16);
291 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
299 pix
= ypoint
+ xpoint
;
300 r
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
301 g
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
302 b
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
304 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
305 r
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
306 g
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
307 b
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
311 r
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
312 g
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
313 b
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
316 pix
= ypoint
+ xpoint
+ sow
;
317 rr
= (RGB_UNPACK_RED(*pix
) * xap
) >> 10;
318 gg
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 10;
319 bb
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 10;
321 for (j
= (1 << 14) - xap
; j
> Cx
; j
-= Cx
) {
322 rr
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 10;
323 gg
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 10;
324 bb
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 10;
328 rr
+= (RGB_UNPACK_RED(*pix
) * j
) >> 10;
329 gg
+= (RGB_UNPACK_GREEN(*pix
) * j
) >> 10;
330 bb
+= (RGB_UNPACK_BLUE(*pix
) * j
) >> 10;
335 r
= (r
+ ((rr
* YAP
))) >> 12;
336 g
= (g
+ ((gg
* YAP
))) >> 12;
337 b
= (b
+ ((bb
* YAP
))) >> 12;
343 *dptr
= LCD_RGBPACK(r
, g
, b
);
348 /* fully optimized (i think) - only change of algorithm can help */
349 /* if we're scaling down horizontally & vertically */
351 /*\ 'Correct' version, with math units prepared for MMXification \ */
354 int r
, g
, b
, rx
, gx
, bx
;
357 for (y
= 0; y
< dh
; y
++) {
358 ypoint
= src
+ ((val_y
>> 16) * sw
);
359 YAP
= (((0x100 - ((val_y
>> 8) & 0xff)) * Cp_y
) >> 8) | (Cp_y
<< 16);
367 dptr
= dest
+ (y
* dow
);
368 for (x
= 0; x
< end
; x
++) {
369 xpoint
= (val_x
>> 16);
370 XAP
= (((0x100 - ((val_x
>> 8) & 0xff)) * Cp_x
) >> 8) | (Cp_x
<< 16);
377 sptr
= ypoint
+ xpoint
;
381 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
382 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
383 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
385 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
386 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
387 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
388 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
392 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
393 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
394 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
397 r
= (rx
* yap
) >> 14;
398 g
= (gx
* yap
) >> 14;
399 b
= (bx
* yap
) >> 14;
401 for (j
= (1 << 14) - yap
; j
> Cy
; j
-= Cy
) {
404 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
405 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
406 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
408 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
409 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
410 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
411 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
415 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
416 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
417 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
420 r
+= (rx
* Cy
) >> 14;
421 g
+= (gx
* Cy
) >> 14;
422 b
+= (bx
* Cy
) >> 14;
427 rx
= (RGB_UNPACK_RED(*pix
) * xap
) >> 9;
428 gx
= (RGB_UNPACK_GREEN(*pix
) * xap
) >> 9;
429 bx
= (RGB_UNPACK_BLUE(*pix
) * xap
) >> 9;
431 for (i
= (1 << 14) - xap
; i
> Cx
; i
-= Cx
) {
432 rx
+= (RGB_UNPACK_RED(*pix
) * Cx
) >> 9;
433 gx
+= (RGB_UNPACK_GREEN(*pix
) * Cx
) >> 9;
434 bx
+= (RGB_UNPACK_BLUE(*pix
) * Cx
) >> 9;
438 rx
+= (RGB_UNPACK_RED(*pix
) * i
) >> 9;
439 gx
+= (RGB_UNPACK_GREEN(*pix
) * i
) >> 9;
440 bx
+= (RGB_UNPACK_BLUE(*pix
) * i
) >> 9;
448 *dptr
= LCD_RGBPACK(r
>> 5, g
>> 5, b
>> 5);