A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 453 lines 18 kB view raw
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}