A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
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.
14 *
15 * Port to Rockbox
16 * Copyright (C) 2007 Jonas Hurrelmann (j@outpo.st)
17 *
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.
22 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
25 *
26 ****************************************************************************/
27
28/*
29 * Copyright (C) 2004, 2005 Daniel M. Duley
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 *
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.
40 *
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.
51 *
52 */
53
54/* OTHER CREDITS:
55 *
56 * This is the normal smoothscale method, based on Imlib2's smoothscale.
57 *
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.
64 *
65 * Changes include formatting, namespaces and other C++'ings, removal of old
66 * #ifdef'ed code, and removal of unneeded border calculation code.
67 *
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.
71 */
72
73#include "pluginlib_bmp.h"
74#include "lcd.h"
75
76void smooth_resize_bitmap(struct bitmap *src_bmp, struct bitmap *dest_bmp)
77{
78 fb_data *sptr, *dptr;
79 int x, y, end;
80 int val_y = 0, val_x;
81#if 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;
86#else
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;
91#endif
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);
97 const int dow = dw;
98 const int sow = sw;
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;
102 int xpoint;
103 fb_data *ypoint;
104
105 end = dw;
106 /* scaling up both ways */
107 if (xup_yup == 3) {
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);
113 INV_YAP = 256 - YAP;
114
115 val_y += inc_y;
116 val_x = 0;
117
118 dptr = dest + (y * dow);
119 sptr = ypoint;
120 if (YAP > 0) {
121 for (x = 0; x < end; x++) {
122 int r = 0, g = 0, b = 0;
123 int rr = 0, gg = 0, bb = 0;
124 fb_data *pix;
125
126 xpoint = (val_x >> 16);
127 XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00);
128 INV_XAP = 256 - XAP;
129 val_x += inc_x;
130
131 if (XAP > 0) {
132 pix = ypoint + xpoint;
133 r = FB_UNPACK_RED(*pix) * INV_XAP;
134 g = FB_UNPACK_GREEN(*pix) * INV_XAP;
135 b = FB_UNPACK_BLUE(*pix) * INV_XAP;
136 pix++;
137 r += FB_UNPACK_RED(*pix) * XAP;
138 g += FB_UNPACK_GREEN(*pix) * XAP;
139 b += FB_UNPACK_BLUE(*pix) * XAP;
140 pix += sow;
141 rr = FB_UNPACK_RED(*pix) * XAP;
142 gg = FB_UNPACK_GREEN(*pix) * XAP;
143 bb = FB_UNPACK_BLUE(*pix) * XAP;
144 pix--;
145 rr += FB_UNPACK_RED(*pix) * INV_XAP;
146 gg += FB_UNPACK_GREEN(*pix) * INV_XAP;
147 bb += FB_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++ = FB_RGBPACK(r, g, b);
152 } else {
153 pix = ypoint + xpoint;
154 r = FB_UNPACK_RED(*pix) * INV_YAP;
155 g = FB_UNPACK_GREEN(*pix) * INV_YAP;
156 b = FB_UNPACK_BLUE(*pix) * INV_YAP;
157 pix += sow;
158 r += FB_UNPACK_RED(*pix) * YAP;
159 g += FB_UNPACK_GREEN(*pix) * YAP;
160 b += FB_UNPACK_BLUE(*pix) * YAP;
161 r >>= 8;
162 g >>= 8;
163 b >>= 8;
164 *dptr++ = FB_RGBPACK(r, g, b);
165 }
166 }
167 } else {
168 for (x = 0; x < end; x++) {
169 int r = 0, g = 0, b = 0;
170 fb_data *pix;
171
172 xpoint = (val_x >> 16);
173 XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00);
174 INV_XAP = 256 - XAP;
175 val_x += inc_x;
176
177 if (XAP > 0) {
178 pix = ypoint + xpoint;
179 r = FB_UNPACK_RED(*pix) * INV_XAP;
180 g = FB_UNPACK_GREEN(*pix) * INV_XAP;
181 b = FB_UNPACK_BLUE(*pix) * INV_XAP;
182 pix++;
183 r += FB_UNPACK_RED(*pix) * XAP;
184 g += FB_UNPACK_GREEN(*pix) * XAP;
185 b += FB_UNPACK_BLUE(*pix) * XAP;
186 r >>= 8;
187 g >>= 8;
188 b >>= 8;
189 *dptr++ = FB_RGBPACK(r, g, b);
190 } else
191 *dptr++ = sptr[xpoint];
192 }
193 }
194 }
195 }
196 /* if we're scaling down vertically */
197 else if (xup_yup == 1) {
198 /*\ 'Correct' version, with math units prepared for MMXification \ */
199 int Cy, j;
200 fb_data *pix;
201 int r, g, b, rr, gg, bb;
202 int yap;
203
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);
208 INV_YAP = 256 - YAP;
209 val_y += inc_y;
210 val_x = 0;
211
212 Cy = YAP >> 16;
213 yap = YAP & 0xffff;
214
215
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);
220 INV_XAP = 256 - XAP;
221 val_x += inc_x;
222
223 pix = ypoint + xpoint;
224 r = (FB_UNPACK_RED(*pix) * yap) >> 10;
225 g = (FB_UNPACK_GREEN(*pix) * yap) >> 10;
226 b = (FB_UNPACK_BLUE(*pix) * yap) >> 10;
227 pix += sow;
228 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
229 r += (FB_UNPACK_RED(*pix) * Cy) >> 10;
230 g += (FB_UNPACK_GREEN(*pix) * Cy) >> 10;
231 b += (FB_UNPACK_BLUE(*pix) * Cy) >> 10;
232 pix += sow;
233 }
234 if (j > 0) {
235 r += (FB_UNPACK_RED(*pix) * j) >> 10;
236 g += (FB_UNPACK_GREEN(*pix) * j) >> 10;
237 b += (FB_UNPACK_BLUE(*pix) * j) >> 10;
238 }
239 if (XAP > 0) {
240 pix = ypoint + xpoint + 1;
241 rr = (FB_UNPACK_RED(*pix) * yap) >> 10;
242 gg = (FB_UNPACK_GREEN(*pix) * yap) >> 10;
243 bb = (FB_UNPACK_BLUE(*pix) * yap) >> 10;
244 pix += sow;
245 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
246 rr += (FB_UNPACK_RED(*pix) * Cy) >> 10;
247 gg += (FB_UNPACK_GREEN(*pix) * Cy) >> 10;
248 bb += (FB_UNPACK_BLUE(*pix) * Cy) >> 10;
249 pix += sow;
250 }
251 if (j > 0) {
252 rr += (FB_UNPACK_RED(*pix) * j) >> 10;
253 gg += (FB_UNPACK_GREEN(*pix) * j) >> 10;
254 bb += (FB_UNPACK_BLUE(*pix) * j) >> 10;
255 }
256 r = r * INV_XAP;
257 g = g * INV_XAP;
258 b = b * INV_XAP;
259 r = (r + ((rr * XAP))) >> 12;
260 g = (g + ((gg * XAP))) >> 12;
261 b = (b + ((bb * XAP))) >> 12;
262 } else {
263 r >>= 4;
264 g >>= 4;
265 b >>= 4;
266 }
267 *dptr = FB_RGBPACK(r, g, b);
268 dptr++;
269 }
270 }
271 }
272 /* if we're scaling down horizontally */
273 else if (xup_yup == 2) {
274 /*\ 'Correct' version, with math units prepared for MMXification \ */
275 int Cx, j;
276 fb_data *pix;
277 int r, g, b, rr, gg, bb;
278 int xap;
279
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);
284 INV_YAP = 256 - YAP;
285 val_y += inc_y;
286 val_x = 0;
287
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);
292 INV_XAP = 256 - XAP;
293
294 val_x += inc_x;
295
296 Cx = XAP >> 16;
297 xap = XAP & 0xffff;
298
299 pix = ypoint + xpoint;
300 r = (FB_UNPACK_RED(*pix) * xap) >> 10;
301 g = (FB_UNPACK_GREEN(*pix) * xap) >> 10;
302 b = (FB_UNPACK_BLUE(*pix) * xap) >> 10;
303 pix++;
304 for (j = (1 << 14) - xap; j > Cx; j -= Cx) {
305 r += (FB_UNPACK_RED(*pix) * Cx) >> 10;
306 g += (FB_UNPACK_GREEN(*pix) * Cx) >> 10;
307 b += (FB_UNPACK_BLUE(*pix) * Cx) >> 10;
308 pix++;
309 }
310 if (j > 0) {
311 r += (FB_UNPACK_RED(*pix) * j) >> 10;
312 g += (FB_UNPACK_GREEN(*pix) * j) >> 10;
313 b += (FB_UNPACK_BLUE(*pix) * j) >> 10;
314 }
315 if (YAP > 0) {
316 pix = ypoint + xpoint + sow;
317 rr = (FB_UNPACK_RED(*pix) * xap) >> 10;
318 gg = (FB_UNPACK_GREEN(*pix) * xap) >> 10;
319 bb = (FB_UNPACK_BLUE(*pix) * xap) >> 10;
320 pix++;
321 for (j = (1 << 14) - xap; j > Cx; j -= Cx) {
322 rr += (FB_UNPACK_RED(*pix) * Cx) >> 10;
323 gg += (FB_UNPACK_GREEN(*pix) * Cx) >> 10;
324 bb += (FB_UNPACK_BLUE(*pix) * Cx) >> 10;
325 pix++;
326 }
327 if (j > 0) {
328 rr += (FB_UNPACK_RED(*pix) * j) >> 10;
329 gg += (FB_UNPACK_GREEN(*pix) * j) >> 10;
330 bb += (FB_UNPACK_BLUE(*pix) * j) >> 10;
331 }
332 r = r * INV_YAP;
333 g = g * INV_YAP;
334 b = b * INV_YAP;
335 r = (r + ((rr * YAP))) >> 12;
336 g = (g + ((gg * YAP))) >> 12;
337 b = (b + ((bb * YAP))) >> 12;
338 } else {
339 r >>= 4;
340 g >>= 4;
341 b >>= 4;
342 }
343 *dptr = FB_RGBPACK(r, g, b);
344 dptr++;
345 }
346 }
347 }
348 /* fully optimized (i think) - only change of algorithm can help */
349 /* if we're scaling down horizontally & vertically */
350 else {
351 /*\ 'Correct' version, with math units prepared for MMXification \ */
352 int Cx, Cy, i, j;
353 fb_data *pix;
354 int r, g, b, rx, gx, bx;
355 int xap, yap;
356
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);
360 INV_YAP = 256 - YAP;
361 val_y += inc_y;
362 val_x = 0;
363
364 Cy = YAP >> 16;
365 yap = YAP & 0xffff;
366
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);
371 INV_XAP = 256 - XAP;
372 val_x += inc_x;
373
374 Cx = XAP >> 16;
375 xap = XAP & 0xffff;
376
377 sptr = ypoint + xpoint;
378
379 pix = sptr;
380 sptr += sow;
381 rx = (FB_UNPACK_RED(*pix) * xap) >> 9;
382 gx = (FB_UNPACK_GREEN(*pix) * xap) >> 9;
383 bx = (FB_UNPACK_BLUE(*pix) * xap) >> 9;
384 pix++;
385 for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
386 rx += (FB_UNPACK_RED(*pix) * Cx) >> 9;
387 gx += (FB_UNPACK_GREEN(*pix) * Cx) >> 9;
388 bx += (FB_UNPACK_BLUE(*pix) * Cx) >> 9;
389 pix++;
390 }
391 if (i > 0) {
392 rx += (FB_UNPACK_RED(*pix) * i) >> 9;
393 gx += (FB_UNPACK_GREEN(*pix) * i) >> 9;
394 bx += (FB_UNPACK_BLUE(*pix) * i) >> 9;
395 }
396
397 r = (rx * yap) >> 14;
398 g = (gx * yap) >> 14;
399 b = (bx * yap) >> 14;
400
401 for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
402 pix = sptr;
403 sptr += sow;
404 rx = (FB_UNPACK_RED(*pix) * xap) >> 9;
405 gx = (FB_UNPACK_GREEN(*pix) * xap) >> 9;
406 bx = (FB_UNPACK_BLUE(*pix) * xap) >> 9;
407 pix++;
408 for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
409 rx += (FB_UNPACK_RED(*pix) * Cx) >> 9;
410 gx += (FB_UNPACK_GREEN(*pix) * Cx) >> 9;
411 bx += (FB_UNPACK_BLUE(*pix) * Cx) >> 9;
412 pix++;
413 }
414 if (i > 0) {
415 rx += (FB_UNPACK_RED(*pix) * i) >> 9;
416 gx += (FB_UNPACK_GREEN(*pix) * i) >> 9;
417 bx += (FB_UNPACK_BLUE(*pix) * i) >> 9;
418 }
419
420 r += (rx * Cy) >> 14;
421 g += (gx * Cy) >> 14;
422 b += (bx * Cy) >> 14;
423 }
424 if (j > 0) {
425 pix = sptr;
426 sptr += sow;
427 rx = (FB_UNPACK_RED(*pix) * xap) >> 9;
428 gx = (FB_UNPACK_GREEN(*pix) * xap) >> 9;
429 bx = (FB_UNPACK_BLUE(*pix) * xap) >> 9;
430 pix++;
431 for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
432 rx += (FB_UNPACK_RED(*pix) * Cx) >> 9;
433 gx += (FB_UNPACK_GREEN(*pix) * Cx) >> 9;
434 bx += (FB_UNPACK_BLUE(*pix) * Cx) >> 9;
435 pix++;
436 }
437 if (i > 0) {
438 rx += (FB_UNPACK_RED(*pix) * i) >> 9;
439 gx += (FB_UNPACK_GREEN(*pix) * i) >> 9;
440 bx += (FB_UNPACK_BLUE(*pix) * i) >> 9;
441 }
442
443 r += (rx * j) >> 14;
444 g += (gx * j) >> 14;
445 b += (bx * j) >> 14;
446 }
447
448 *dptr = FB_RGBPACK(r >> 5, g >> 5, b >> 5);
449 dptr++;
450 }
451 }
452 }
453}