Index: apps/recorder/resize.c =================================================================== --- apps/recorder/resize.c (revision 0) +++ apps/recorder/resize.c (revision 0) @@ -0,0 +1,374 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: resize.c 16168 2008-01-26 00:16:06Z nicolasp $ + * + * Copyright (C) 2006 by Antoine Cellerier + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "resize.h" + +#include "lcd.h" +#include "file.h" +#include "system.h" + +#ifndef HAVE_LCD_COLOR +/** + Very simple image scale from src to dst (nearest neighbour). + Source and destination dimensions are read from the struct bitmap. +*/ +void resize_bitmap(struct bitmap *src, struct bitmap *dst) +{ + const int srcw = src->width; + const int srch = src->height; + const int dstw = dst->width; + const int dsth = dst->height; + const fb_data *srcd = (fb_data*)(src->data); + const fb_data *dstd = (fb_data*)(dst->data); + + const long xrstep = ((srcw-1) << 8) / (dstw-1); + const long yrstep = ((srch-1) << 8) / (dsth-1); + fb_data *src_row, *dst_row; + long xr, yr = 0; + int src_x, src_y, dst_x, dst_y; + for (dst_y=0; dst_y < dsth; dst_y++) + { + src_y = (yr >> 8); + src_row = (fb_data*)&srcd[src_y * srcw]; + dst_row = (fb_data*)&dstd[dst_y * dstw]; + for (xr=0,dst_x=0; dst_x < dstw; dst_x++) + { + src_x = (xr >> 8); + dst_row[dst_x] = src_row[src_x]; + xr += xrstep; + } + yr += yrstep; + } +} +#else + +/* + * Code for the scaling algorithm: + * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code + * is by Willem Monsuwe . Additional modifications are by + * (C) Daniel M. Duley. + * + * Port to Rockbox + * Copyright (C) 2007 Jonas Hurrelmann (j@outpo.st) + * Copyright (C) 2008 Akio Idehara + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/* + * Copyright (C) 2004, 2005 Daniel M. Duley + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* OTHER CREDITS: + * + * This is the normal smoothscale method, based on Imlib2's smoothscale. + * + * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow + * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's + * C algorithm and it ran at about the same speed as my MMX optimized one... + * Finally I ported Imlib's MMX version and it ran in less than half the + * time as my MMX algorithm, (taking only a quarter of the time Qt does). + * After further optimization it seems to run at around 1/6th. + * + * Changes include formatting, namespaces and other C++'ings, removal of old + * #ifdef'ed code, and removal of unneeded border calculation code. + * + * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code + * is by Willem Monsuwe . All other modifications are + * (C) Daniel M. Duley. + */ + + +/** + Advanced image scale from src to dst (bilinear) based on imlib2. + Source and destination dimensions are read from the struct bitmap. + */ + +#if (LCD_PIXELFORMAT == RGB565SWAPPED) +/* RGB3553 */ +#define _UNSWAP(fb) (swap16(fb)) +#else /* LCD_PIXELFORMAT == RGB565 */ +/* RGB565 */ +#define _UNSWAP(fb) (fb) +#endif /* RGB565 */ + +static int rgb_unpack_red(fb_data fb) __attribute__ ((noinline)); +static int rgb_unpack_green(fb_data fb) __attribute__ ((noinline)); +static int rgb_unpack_blue(fb_data fb) __attribute__ ((noinline)); + +static int rgb_unpack_red(fb_data fb) +{ + fb_data tmp = _UNSWAP(fb); + return _RGB_UNPACK_RED(tmp); +} + +static int rgb_unpack_green(fb_data fb) +{ + fb_data tmp = _UNSWAP(fb); + return _RGB_UNPACK_GREEN(tmp); +} + +static int rgb_unpack_blue(fb_data fb) +{ + fb_data tmp = _UNSWAP(fb); + return _RGB_UNPACK_BLUE(tmp); +} + +struct tmp_rgb { + int r; + int g; + int b; +}; + +static void downscale_help(fb_data *pix, int xap, int Cx, int Cy, + struct tmp_rgb *rgb) __attribute__ ((noinline)); + +static void downscale_help(fb_data *pix, int xap, int Cx, int Cy, + struct tmp_rgb *rgb) +{ + int rx = (rgb_unpack_red(*pix) * xap) >> 9; + int gx = (rgb_unpack_green(*pix) * xap) >> 9; + int bx = (rgb_unpack_blue(*pix) * xap) >> 9; + int i; + pix++; + for (i = (1 << 14) - xap; i > Cx; i -= Cx) { + rx += (rgb_unpack_red(*pix) * Cx) >> 9; + gx += (rgb_unpack_green(*pix) * Cx) >> 9; + bx += (rgb_unpack_blue(*pix) * Cx) >> 9; + pix++; + } + if (i > 0) { + rx += (rgb_unpack_red(*pix) * i) >> 9; + gx += (rgb_unpack_green(*pix) * i) >> 9; + bx += (rgb_unpack_blue(*pix) * i) >> 9; + } + + rgb->r = (rx * Cy) >> 14; + rgb->g = (gx * Cy) >> 14; + rgb->b = (bx * Cy) >> 14; +} + +void resize_bitmap(struct bitmap *src_bmp, struct bitmap *dest_bmp) +{ + fb_data *sptr, *dptr; + int x, y, end; + int val_y = 0, val_x; + const int sw = src_bmp->width; + const int sh = src_bmp->height; + const int dw = dest_bmp->width; + const int dh = dest_bmp->height; + const int inc_x = (sw << 16) / dw; + const int inc_y = (sh << 16) / dh; + const int Cp_x = ((dw << 14) / sw) + 1; + const int Cp_y = ((dh << 14) / sh) + 1; + const int xup_yup = (dw >= sw) + ((dh >= sh) << 1); + const int dow = dw; + const int sow = sw; + fb_data *src = (fb_data*)src_bmp->data; + fb_data *dest = (fb_data*)dest_bmp->data; + int XAP, YAP, INV_YAP, INV_XAP; + int xpoint; + fb_data *ypoint; + + end = dw; + /* scaling up both ways */ + if (xup_yup == 3) { + /* go through every scanline in the output buffer */ + for (y = 0; y < dh; y++) { + /* calculate the source line we'll scan from */ + ypoint = src + ((val_y >> 16) * sw); + YAP = ((val_y >> 16) >= (sh - 1)) ? 0 : (val_y >> 8) - ((val_y >> 8) & 0xffffff00); + INV_YAP = 256 - YAP; + + val_y += inc_y; + val_x = 0; + + dptr = dest + (y * dow); + sptr = ypoint; + if (YAP > 0) { + for (x = 0; x < end; x++) { + int r = 0, g = 0, b = 0; + int rr = 0, gg = 0, bb = 0; + fb_data *pix; + + xpoint = (val_x >> 16); + XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00); + INV_XAP = 256 - XAP; + val_x += inc_x; + + if (XAP > 0) { + pix = ypoint + xpoint; + r = rgb_unpack_red(*pix) * INV_XAP; + g = rgb_unpack_green(*pix) * INV_XAP; + b = rgb_unpack_blue(*pix) * INV_XAP; + pix++; + r += rgb_unpack_red(*pix) * XAP; + g += rgb_unpack_green(*pix) * XAP; + b += rgb_unpack_blue(*pix) * XAP; + pix += sow; + rr = rgb_unpack_red(*pix) * XAP; + gg = rgb_unpack_green(*pix) * XAP; + bb = rgb_unpack_blue(*pix) * XAP; + pix--; + rr += rgb_unpack_red(*pix) * INV_XAP; + gg += rgb_unpack_green(*pix) * INV_XAP; + bb += rgb_unpack_blue(*pix) * INV_XAP; + r = ((rr * YAP) + (r * INV_YAP)) >> 16; + g = ((gg * YAP) + (g * INV_YAP)) >> 16; + b = ((bb * YAP) + (b * INV_YAP)) >> 16; + *dptr++ = LCD_RGBPACK(r, g, b); + } else { + pix = ypoint + xpoint; + r = rgb_unpack_red(*pix) * INV_YAP; + g = rgb_unpack_green(*pix) * INV_YAP; + b = rgb_unpack_blue(*pix) * INV_YAP; + pix += sow; + r += rgb_unpack_red(*pix) * YAP; + g += rgb_unpack_green(*pix) * YAP; + b += rgb_unpack_blue(*pix) * YAP; + r >>= 8; + g >>= 8; + b >>= 8; + *dptr++ = LCD_RGBPACK(r, g, b); + } + } + } else { + for (x = 0; x < end; x++) { + int r = 0, g = 0, b = 0; + fb_data *pix; + + xpoint = (val_x >> 16); + XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00); + INV_XAP = 256 - XAP; + val_x += inc_x; + + if (XAP > 0) { + pix = ypoint + xpoint; + r = rgb_unpack_red(*pix) * INV_XAP; + g = rgb_unpack_green(*pix) * INV_XAP; + b = rgb_unpack_blue(*pix) * INV_XAP; + pix++; + r += rgb_unpack_red(*pix) * XAP; + g += rgb_unpack_green(*pix) * XAP; + b += rgb_unpack_blue(*pix) * XAP; + r >>= 8; + g >>= 8; + b >>= 8; + *dptr++ = LCD_RGBPACK(r, g, b); + } else + *dptr++ = sptr[xpoint]; + } + } + } + } + /* fully optimized (i think) - only change of algorithm can help */ + /* if we're scaling down horizontally & vertically */ + else { + /*\ 'Correct' version, with math units prepared for MMXification \ */ + int Cx, Cy, j; + fb_data *pix; + int r, g, b; + int xap, yap; + + for (y = 0; y < dh; y++) { + ypoint = src + ((val_y >> 16) * sw); + YAP = (((0x100 - ((val_y >> 8) & 0xff)) * Cp_y) >> 8) | (Cp_y << 16); + INV_YAP = 256 - YAP; + val_y += inc_y; + val_x = 0; + + Cy = YAP >> 16; + yap = YAP & 0xffff; + + dptr = dest + (y * dow); + for (x = 0; x < end; x++) { + struct tmp_rgb tmp_rgb; + xpoint = (val_x >> 16); + XAP = (((0x100 - ((val_x >> 8) & 0xff)) * Cp_x) >> 8) | (Cp_x << 16); + INV_XAP = 256 - XAP; + val_x += inc_x; + + Cx = XAP >> 16; + xap = XAP & 0xffff; + + sptr = ypoint + xpoint; + + pix = sptr; + sptr += sow; + + downscale_help(pix, xap, Cx, yap, &tmp_rgb); + r = tmp_rgb.r; + g = tmp_rgb.g; + b = tmp_rgb.b; + + for (j = (1 << 14) - yap; j > Cy; j -= Cy) { + pix = sptr; + sptr += sow; + + downscale_help(pix, xap, Cx, Cy, &tmp_rgb); + r += tmp_rgb.r; + g += tmp_rgb.g; + b += tmp_rgb.b; + } + if (j > 0) { + pix = sptr; + sptr += sow; + + downscale_help(pix, xap, Cx, j, &tmp_rgb); + r += tmp_rgb.r; + g += tmp_rgb.g; + b += tmp_rgb.b; + } + + *dptr = LCD_RGBPACK(r >> 5, g >> 5, b >> 5); + dptr++; + } + } + } +} +#endif /* HAVE_LCD_COLOR */ Index: apps/recorder/resize.h =================================================================== --- apps/recorder/resize.h (revision 0) +++ apps/recorder/resize.h (revision 0) @@ -0,0 +1,30 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: resize.h 17001 2008-04-06 22:30:50Z nicolasp $ + * + * Copyright (C) 2006 by Antoine Cellerier + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _RESIZE_H_ +#define _RESIZE_H_ + +#include "lcd.h" +#include "plugin.h" + +#ifdef HAVE_BMP_RESIZE +void resize_bitmap(struct bitmap *src, struct bitmap *dst); +#endif /* HAVE_BMP_RESIZE */ +#endif /* _RESIZE_H_ */ Index: apps/plugins/test_resize.c =================================================================== --- apps/plugins/test_resize.c (revision 18166) +++ apps/plugins/test_resize.c (working copy) @@ -43,13 +43,13 @@ const struct button_mapping *plugin_cont #define SIZE_DECREASE PLA_DOWN #define SIZE_DECREASE_REPEAT PLA_DOWN_REPEAT -#define WIDTH_INCREASE PLA_RIGHT -#define WIDTH_INCREASE_REPEAT PLA_RIGHT_REPEAT -#define WIDTH_DECREASE PLA_LEFT -#define WIDTH_DECREASE_REPEAT PLA_LEFT_REPEAT +#define SINGLE_INCREASE PLA_RIGHT +#define SINGLE_INCREASE_REPEAT PLA_RIGHT_REPEAT +#define SINGLE_DECREASE PLA_LEFT +#define SINGLE_DECREASE_REPEAT PLA_LEFT_REPEAT #define BUTTON_QUIT PLA_QUIT -#define CHANGE_MODE PLA_MENU +#define CHANGE_DIRECTION PLA_MENU #define MAX_OUTPUT_WIDTH LCD_WIDTH #define MAX_OUTPUT_HEIGHT LCD_HEIGHT @@ -92,23 +92,18 @@ enum plugin_status plugin_start(const st DEBUGF("input_bmp_data starts at %p\n", input_bmp_data); DEBUGF("output_bmp_data starts at %p\n", output_bmp_data); - int scale_algorithm = 0; + unsigned short direction = 0; while(1) { rb->lcd_clear_display(); rb->lcd_bitmap(input_bmp_data, 0, 0, input_bmp.width, input_bmp.height); - switch ( scale_algorithm ) { - case 0: - smooth_resize_bitmap(&input_bmp, &output_bmp); - rb->lcd_putsxy(0,0,"smooth_resize_bitmap"); - break; - case 1: - simple_resize_bitmap(&input_bmp, &output_bmp); - rb->lcd_putsxy(0,0,"simple_resize_bitmap"); - break; - } - + rb->resize_bitmap(&input_bmp, &output_bmp); +#ifdef HAVE_LCD_COLOR + rb->lcd_putsxy(0,0, "smooth resize (LCD_COLOR)"); +#else + rb->lcd_putsxy(0,0,"simple resize !(LCD_COLOR)"); +#endif rb->lcd_bitmap(output_bmp_data, 0, 100, output_bmp.width, output_bmp.height); @@ -132,19 +127,34 @@ enum plugin_status plugin_start(const st if (output_bmp.height > 2) output_bmp.height -= 2; break; - case WIDTH_INCREASE: - case WIDTH_INCREASE_REPEAT: - if (output_bmp.width < MAX_OUTPUT_WIDTH - 2) - output_bmp.width += 2; - break; - - case WIDTH_DECREASE: - case WIDTH_DECREASE_REPEAT: - if (output_bmp.width > 2) output_bmp.width -= 2; + case SINGLE_INCREASE: + case SINGLE_INCREASE_REPEAT: + if (direction == 0) + { + if (output_bmp.width < MAX_OUTPUT_WIDTH - 2) + output_bmp.width += 2; + } + else + { + if (output_bmp.height < MAX_OUTPUT_HEIGHT - 2) + output_bmp.height += 2; + } + break; + case SINGLE_DECREASE: + case SINGLE_DECREASE_REPEAT: + if (direction == 0) + { + if (output_bmp.width > 2) + output_bmp.width -= 2; + } + else + { + if (output_bmp.height > 2) + output_bmp.height -= 2; + } break; - case CHANGE_MODE: - scale_algorithm = (scale_algorithm+1)%2; + direction = (direction+1)%2; break; } } Index: apps/plugins/sliding_puzzle.c =================================================================== --- apps/plugins/sliding_puzzle.c (revision 18166) +++ apps/plugins/sliding_puzzle.c (working copy) @@ -324,11 +324,7 @@ static bool load_resize_bitmap(void) FORMAT_NATIVE ); if( rc > 0 ) { -#ifdef HAVE_LCD_COLOR - smooth_resize_bitmap( &temp_bitmap, &main_bitmap ); -#else - simple_resize_bitmap( &temp_bitmap, &main_bitmap ); -#endif + rb->resize_bitmap( &temp_bitmap, &main_bitmap ); puzzle_bmp_ptr = (const fb_data *)img_buf; rb->strcpy( img_buf_path, filename ); return true; Index: apps/plugins/ppmviewer.c =================================================================== --- apps/plugins/ppmviewer.c (revision 18166) +++ apps/plugins/ppmviewer.c (working copy) @@ -320,7 +320,7 @@ enum plugin_status plugin_start(const st } small_bitmap.data = (char*)lcd_buf; - smooth_resize_bitmap( &orig_bitmap, &small_bitmap ); + rb->resize_bitmap( &orig_bitmap, &small_bitmap ); rb->lcd_bitmap((fb_data*)small_bitmap.data, 0, 0, small_bitmap.width, small_bitmap.height); Index: apps/plugins/pictureflow.c =================================================================== --- apps/plugins/pictureflow.c (revision 18166) +++ apps/plugins/pictureflow.c (working copy) @@ -913,7 +913,7 @@ bool create_bmp(struct bitmap *input_bmp /* resize image */ output_bmp.width = config.avg_album_width; output_bmp.height = config.avg_album_width; - simple_resize_bitmap(input_bmp, &output_bmp); + rb->resize_bitmap(input_bmp, &output_bmp); /* Resized bitmap is now in the output buffer, copy it back to the input buffer */ Index: apps/plugins/lib/SOURCES =================================================================== --- apps/plugins/lib/SOURCES (revision 18166) +++ apps/plugins/lib/SOURCES (working copy) @@ -33,9 +33,6 @@ xlcd_scroll.c #if LCD_DEPTH>1 bmp.c #endif -#ifdef HAVE_LCD_COLOR -bmp_smooth_scale.c -#endif #endif pluginlib_actions.c helper.c Index: apps/plugins/lib/bmp.c =================================================================== --- apps/plugins/lib/bmp.c (revision 18166) +++ apps/plugins/lib/bmp.c (working copy) @@ -86,36 +86,3 @@ int save_bmp_file( char* filename, struc return 1; } #endif - -/** - Very simple image scale from src to dst (nearest neighbour). - Source and destination dimensions are read from the struct bitmap. -*/ -void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst) -{ - const int srcw = src->width; - const int srch = src->height; - const int dstw = dst->width; - const int dsth = dst->height; - const fb_data *srcd = (fb_data*)(src->data); - const fb_data *dstd = (fb_data*)(dst->data); - - const long xrstep = ((srcw-1) << 8) / (dstw-1); - const long yrstep = ((srch-1) << 8) / (dsth-1); - fb_data *src_row, *dst_row; - long xr, yr = 0; - int src_x, src_y, dst_x, dst_y; - for (dst_y=0; dst_y < dsth; dst_y++) - { - src_y = (yr >> 8); - src_row = (fb_data*)&srcd[src_y * srcw]; - dst_row = (fb_data*)&dstd[dst_y * dstw]; - for (xr=0,dst_x=0; dst_x < dstw; dst_x++) - { - src_x = (xr >> 8); - dst_row[dst_x] = src_row[src_x]; - xr += xrstep; - } - yr += yrstep; - } -} Index: apps/plugins/lib/bmp_smooth_scale.c =================================================================== --- apps/plugins/lib/bmp_smooth_scale.c (revision 18166) +++ apps/plugins/lib/bmp_smooth_scale.c (working copy) @@ -1,446 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Code for the scaling algorithm: - * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code - * is by Willem Monsuwe . Additional modifications are by - * (C) Daniel M. Duley. - * - * Port to Rockbox - * Copyright (C) 2007 Jonas Hurrelmann (j@outpo.st) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * Copyright (C) 2004, 2005 Daniel M. Duley - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* OTHER CREDITS: - * - * This is the normal smoothscale method, based on Imlib2's smoothscale. - * - * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow - * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's - * C algorithm and it ran at about the same speed as my MMX optimized one... - * Finally I ported Imlib's MMX version and it ran in less than half the - * time as my MMX algorithm, (taking only a quarter of the time Qt does). - * After further optimization it seems to run at around 1/6th. - * - * Changes include formatting, namespaces and other C++'ings, removal of old - * #ifdef'ed code, and removal of unneeded border calculation code. - * - * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code - * is by Willem Monsuwe . All other modifications are - * (C) Daniel M. Duley. - */ - -#include "bmp.h" -#include "lcd.h" - -void smooth_resize_bitmap(struct bitmap *src_bmp, struct bitmap *dest_bmp) -{ - fb_data *sptr, *dptr; - int x, y, end; - int val_y = 0, val_x; - const int sw = src_bmp->width; - const int sh = src_bmp->height; - const int dw = dest_bmp->width; - const int dh = dest_bmp->height; - const int inc_x = (sw << 16) / dw; - const int inc_y = (sh << 16) / dh; - const int Cp_x = ((dw << 14) / sw) + 1; - const int Cp_y = ((dh << 14) / sh) + 1; - const int xup_yup = (dw >= sw) + ((dh >= sh) << 1); - const int dow = dw; - const int sow = sw; - fb_data *src = (fb_data*)src_bmp->data; - fb_data *dest = (fb_data*)dest_bmp->data; - int XAP, YAP, INV_YAP, INV_XAP; - int xpoint; - fb_data *ypoint; - - end = dw; - /* scaling up both ways */ - if (xup_yup == 3) { - /* go through every scanline in the output buffer */ - for (y = 0; y < dh; y++) { - /* calculate the source line we'll scan from */ - ypoint = src + ((val_y >> 16) * sw); - YAP = ((val_y >> 16) >= (sh - 1)) ? 0 : (val_y >> 8) - ((val_y >> 8) & 0xffffff00); - INV_YAP = 256 - YAP; - - val_y += inc_y; - val_x = 0; - - dptr = dest + (y * dow); - sptr = ypoint; - if (YAP > 0) { - for (x = 0; x < end; x++) { - int r = 0, g = 0, b = 0; - int rr = 0, gg = 0, bb = 0; - fb_data *pix; - - xpoint = (val_x >> 16); - XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00); - INV_XAP = 256 - XAP; - val_x += inc_x; - - if (XAP > 0) { - pix = ypoint + xpoint; - r = RGB_UNPACK_RED(*pix) * INV_XAP; - g = RGB_UNPACK_GREEN(*pix) * INV_XAP; - b = RGB_UNPACK_BLUE(*pix) * INV_XAP; - pix++; - r += RGB_UNPACK_RED(*pix) * XAP; - g += RGB_UNPACK_GREEN(*pix) * XAP; - b += RGB_UNPACK_BLUE(*pix) * XAP; - pix += sow; - rr = RGB_UNPACK_RED(*pix) * XAP; - gg = RGB_UNPACK_GREEN(*pix) * XAP; - bb = RGB_UNPACK_BLUE(*pix) * XAP; - pix--; - rr += RGB_UNPACK_RED(*pix) * INV_XAP; - gg += RGB_UNPACK_GREEN(*pix) * INV_XAP; - bb += RGB_UNPACK_BLUE(*pix) * INV_XAP; - r = ((rr * YAP) + (r * INV_YAP)) >> 16; - g = ((gg * YAP) + (g * INV_YAP)) >> 16; - b = ((bb * YAP) + (b * INV_YAP)) >> 16; - *dptr++ = LCD_RGBPACK(r, g, b); - } else { - pix = ypoint + xpoint; - r = RGB_UNPACK_RED(*pix) * INV_YAP; - g = RGB_UNPACK_GREEN(*pix) * INV_YAP; - b = RGB_UNPACK_BLUE(*pix) * INV_YAP; - pix += sow; - r += RGB_UNPACK_RED(*pix) * YAP; - g += RGB_UNPACK_GREEN(*pix) * YAP; - b += RGB_UNPACK_BLUE(*pix) * YAP; - r >>= 8; - g >>= 8; - b >>= 8; - *dptr++ = LCD_RGBPACK(r, g, b); - } - } - } else { - for (x = 0; x < end; x++) { - int r = 0, g = 0, b = 0; - fb_data *pix; - - xpoint = (val_x >> 16); - XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00); - INV_XAP = 256 - XAP; - val_x += inc_x; - - if (XAP > 0) { - pix = ypoint + xpoint; - r = RGB_UNPACK_RED(*pix) * INV_XAP; - g = RGB_UNPACK_GREEN(*pix) * INV_XAP; - b = RGB_UNPACK_BLUE(*pix) * INV_XAP; - pix++; - r += RGB_UNPACK_RED(*pix) * XAP; - g += RGB_UNPACK_GREEN(*pix) * XAP; - b += RGB_UNPACK_BLUE(*pix) * XAP; - r >>= 8; - g >>= 8; - b >>= 8; - *dptr++ = LCD_RGBPACK(r, g, b); - } else - *dptr++ = sptr[xpoint]; - } - } - } - } - /* if we're scaling down vertically */ - else if (xup_yup == 1) { - /*\ 'Correct' version, with math units prepared for MMXification \ */ - int Cy, j; - fb_data *pix; - int r, g, b, rr, gg, bb; - int yap; - - /* go through every scanline in the output buffer */ - for (y = 0; y < dh; y++) { - ypoint = src + ((val_y >> 16) * sw); - YAP = (((0x100 - ((val_y >> 8) & 0xff)) * Cp_y) >> 8) | (Cp_y << 16); - INV_YAP = 256 - YAP; - val_y += inc_y; - val_x = 0; - - Cy = YAP >> 16; - yap = YAP & 0xffff; - - - dptr = dest + (y * dow); - for (x = 0; x < end; x++) { - xpoint = (val_x >> 16); - XAP = ((val_x >> 16) >= (sw - 1)) ? 0 : (val_x >> 8) - ((val_x >> 8) & 0xffffff00); - INV_XAP = 256 - XAP; - val_x += inc_x; - - pix = ypoint + xpoint; - r = (RGB_UNPACK_RED(*pix) * yap) >> 10; - g = (RGB_UNPACK_GREEN(*pix) * yap) >> 10; - b = (RGB_UNPACK_BLUE(*pix) * yap) >> 10; - pix += sow; - for (j = (1 << 14) - yap; j > Cy; j -= Cy) { - r += (RGB_UNPACK_RED(*pix) * Cy) >> 10; - g += (RGB_UNPACK_GREEN(*pix) * Cy) >> 10; - b += (RGB_UNPACK_BLUE(*pix) * Cy) >> 10; - pix += sow; - } - if (j > 0) { - r += (RGB_UNPACK_RED(*pix) * j) >> 10; - g += (RGB_UNPACK_GREEN(*pix) * j) >> 10; - b += (RGB_UNPACK_BLUE(*pix) * j) >> 10; - } - if (XAP > 0) { - pix = ypoint + xpoint + 1; - rr = (RGB_UNPACK_RED(*pix) * yap) >> 10; - gg = (RGB_UNPACK_GREEN(*pix) * yap) >> 10; - bb = (RGB_UNPACK_BLUE(*pix) * yap) >> 10; - pix += sow; - for (j = (1 << 14) - yap; j > Cy; j -= Cy) { - rr += (RGB_UNPACK_RED(*pix) * Cy) >> 10; - gg += (RGB_UNPACK_GREEN(*pix) * Cy) >> 10; - bb += (RGB_UNPACK_BLUE(*pix) * Cy) >> 10; - pix += sow; - } - if (j > 0) { - rr += (RGB_UNPACK_RED(*pix) * j) >> 10; - gg += (RGB_UNPACK_GREEN(*pix) * j) >> 10; - bb += (RGB_UNPACK_BLUE(*pix) * j) >> 10; - } - r = r * INV_XAP; - g = g * INV_XAP; - b = b * INV_XAP; - r = (r + ((rr * XAP))) >> 12; - g = (g + ((gg * XAP))) >> 12; - b = (b + ((bb * XAP))) >> 12; - } else { - r >>= 4; - g >>= 4; - b >>= 4; - } - *dptr = LCD_RGBPACK(r, g, b); - dptr++; - } - } - } - /* if we're scaling down horizontally */ - else if (xup_yup == 2) { - /*\ 'Correct' version, with math units prepared for MMXification \ */ - int Cx, j; - fb_data *pix; - int r, g, b, rr, gg, bb; - int xap; - - /* go through every scanline in the output buffer */ - for (y = 0; y < dh; y++) { - ypoint = src + ((val_y >> 16) * sw); - YAP = ((val_y >> 16) >= (sh - 1)) ? 0 : (val_y >> 8) - ((val_y >> 8) & 0xffffff00); - INV_YAP = 256 - YAP; - val_y += inc_y; - val_x = 0; - - dptr = dest + (y * dow); - for (x = 0; x < end; x++) { - xpoint = (val_x >> 16); - XAP = (((0x100 - ((val_x >> 8) & 0xff)) * Cp_x) >> 8) | (Cp_x << 16); - INV_XAP = 256 - XAP; - - val_x += inc_x; - - Cx = XAP >> 16; - xap = XAP & 0xffff; - - pix = ypoint + xpoint; - r = (RGB_UNPACK_RED(*pix) * xap) >> 10; - g = (RGB_UNPACK_GREEN(*pix) * xap) >> 10; - b = (RGB_UNPACK_BLUE(*pix) * xap) >> 10; - pix++; - for (j = (1 << 14) - xap; j > Cx; j -= Cx) { - r += (RGB_UNPACK_RED(*pix) * Cx) >> 10; - g += (RGB_UNPACK_GREEN(*pix) * Cx) >> 10; - b += (RGB_UNPACK_BLUE(*pix) * Cx) >> 10; - pix++; - } - if (j > 0) { - r += (RGB_UNPACK_RED(*pix) * j) >> 10; - g += (RGB_UNPACK_GREEN(*pix) * j) >> 10; - b += (RGB_UNPACK_BLUE(*pix) * j) >> 10; - } - if (YAP > 0) { - pix = ypoint + xpoint + sow; - rr = (RGB_UNPACK_RED(*pix) * xap) >> 10; - gg = (RGB_UNPACK_GREEN(*pix) * xap) >> 10; - bb = (RGB_UNPACK_BLUE(*pix) * xap) >> 10; - pix++; - for (j = (1 << 14) - xap; j > Cx; j -= Cx) { - rr += (RGB_UNPACK_RED(*pix) * Cx) >> 10; - gg += (RGB_UNPACK_GREEN(*pix) * Cx) >> 10; - bb += (RGB_UNPACK_BLUE(*pix) * Cx) >> 10; - pix++; - } - if (j > 0) { - rr += (RGB_UNPACK_RED(*pix) * j) >> 10; - gg += (RGB_UNPACK_GREEN(*pix) * j) >> 10; - bb += (RGB_UNPACK_BLUE(*pix) * j) >> 10; - } - r = r * INV_YAP; - g = g * INV_YAP; - b = b * INV_YAP; - r = (r + ((rr * YAP))) >> 12; - g = (g + ((gg * YAP))) >> 12; - b = (b + ((bb * YAP))) >> 12; - } else { - r >>= 4; - g >>= 4; - b >>= 4; - } - *dptr = LCD_RGBPACK(r, g, b); - dptr++; - } - } - } - /* fully optimized (i think) - only change of algorithm can help */ - /* if we're scaling down horizontally & vertically */ - else { - /*\ 'Correct' version, with math units prepared for MMXification \ */ - int Cx, Cy, i, j; - fb_data *pix; - int r, g, b, rx, gx, bx; - int xap, yap; - - for (y = 0; y < dh; y++) { - ypoint = src + ((val_y >> 16) * sw); - YAP = (((0x100 - ((val_y >> 8) & 0xff)) * Cp_y) >> 8) | (Cp_y << 16); - INV_YAP = 256 - YAP; - val_y += inc_y; - val_x = 0; - - Cy = YAP >> 16; - yap = YAP & 0xffff; - - dptr = dest + (y * dow); - for (x = 0; x < end; x++) { - xpoint = (val_x >> 16); - XAP = (((0x100 - ((val_x >> 8) & 0xff)) * Cp_x) >> 8) | (Cp_x << 16); - INV_XAP = 256 - XAP; - val_x += inc_x; - - Cx = XAP >> 16; - xap = XAP & 0xffff; - - sptr = ypoint + xpoint; - - pix = sptr; - sptr += sow; - rx = (RGB_UNPACK_RED(*pix) * xap) >> 9; - gx = (RGB_UNPACK_GREEN(*pix) * xap) >> 9; - bx = (RGB_UNPACK_BLUE(*pix) * xap) >> 9; - pix++; - for (i = (1 << 14) - xap; i > Cx; i -= Cx) { - rx += (RGB_UNPACK_RED(*pix) * Cx) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * Cx) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * Cx) >> 9; - pix++; - } - if (i > 0) { - rx += (RGB_UNPACK_RED(*pix) * i) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * i) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * i) >> 9; - } - - r = (rx * yap) >> 14; - g = (gx * yap) >> 14; - b = (bx * yap) >> 14; - - for (j = (1 << 14) - yap; j > Cy; j -= Cy) { - pix = sptr; - sptr += sow; - rx = (RGB_UNPACK_RED(*pix) * xap) >> 9; - gx = (RGB_UNPACK_GREEN(*pix) * xap) >> 9; - bx = (RGB_UNPACK_BLUE(*pix) * xap) >> 9; - pix++; - for (i = (1 << 14) - xap; i > Cx; i -= Cx) { - rx += (RGB_UNPACK_RED(*pix) * Cx) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * Cx) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * Cx) >> 9; - pix++; - } - if (i > 0) { - rx += (RGB_UNPACK_RED(*pix) * i) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * i) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * i) >> 9; - } - - r += (rx * Cy) >> 14; - g += (gx * Cy) >> 14; - b += (bx * Cy) >> 14; - } - if (j > 0) { - pix = sptr; - sptr += sow; - rx = (RGB_UNPACK_RED(*pix) * xap) >> 9; - gx = (RGB_UNPACK_GREEN(*pix) * xap) >> 9; - bx = (RGB_UNPACK_BLUE(*pix) * xap) >> 9; - pix++; - for (i = (1 << 14) - xap; i > Cx; i -= Cx) { - rx += (RGB_UNPACK_RED(*pix) * Cx) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * Cx) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * Cx) >> 9; - pix++; - } - if (i > 0) { - rx += (RGB_UNPACK_RED(*pix) * i) >> 9; - gx += (RGB_UNPACK_GREEN(*pix) * i) >> 9; - bx += (RGB_UNPACK_BLUE(*pix) * i) >> 9; - } - - r += (rx * j) >> 14; - g += (gx * j) >> 14; - b += (bx * j) >> 14; - } - - *dptr = LCD_RGBPACK(r >> 5, g >> 5, b >> 5); - dptr++; - } - } - } -} Index: apps/plugins/lib/bmp.h =================================================================== --- apps/plugins/lib/bmp.h (revision 18166) +++ apps/plugins/lib/bmp.h (working copy) @@ -31,16 +31,4 @@ int save_bmp_file( char* filename, struct bitmap *bm, const struct plugin_api* rb ); #endif -/** - Very simple image scale from src to dst (nearest neighbour). - Source and destination dimensions are read from the struct bitmap. -*/ -void simple_resize_bitmap(struct bitmap *src, struct bitmap *dst); - -/** - Advanced image scale from src to dst (bilinear) based on imlib2. - Source and destination dimensions are read from the struct bitmap. - */ -void smooth_resize_bitmap(struct bitmap *src, struct bitmap *dst); - #endif Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 18166) +++ apps/plugin.c (working copy) @@ -49,6 +49,10 @@ #include "bidi.h" #endif +#ifdef HAVE_BMP_RESIZE +#include "resize.h" +#endif + #ifdef SIMULATOR static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; void *sim_plugin_load(char *plugin, void **pd); @@ -600,6 +604,10 @@ static const struct plugin_api rockbox_a search_albumart_files, #endif +#ifdef HAVE_BMP_RESIZE + resize_bitmap, +#endif + /* new stuff at the end, sort into place next time the API gets incompatible */ #ifdef HAVE_TAGCACHE Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 18166) +++ apps/SOURCES (working copy) @@ -89,6 +89,9 @@ recorder/bmp.c recorder/icons.c recorder/keyboard.c recorder/peakmeter.c +#ifdef HAVE_BMP_RESIZE +recorder/resize.c +#endif #ifdef HAVE_ALBUMART recorder/albumart.c #endif Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 18166) +++ apps/plugin.h (working copy) @@ -752,6 +752,9 @@ struct plugin_api { bool (*search_albumart_files)(const struct mp3entry *id3, const char *size_string, char *buf, int buflen); #endif +#ifdef HAVE_BMP_RESIZE + void (*resize_bitmap)(struct bitmap *src, struct bitmap *dst); +#endif /* new stuff at the end, sort into place next time the API gets incompatible */ Index: firmware/export/config_caps.h =================================================================== --- firmware/export/config_caps.h (revision 18166) +++ firmware/export/config_caps.h (working copy) @@ -116,3 +116,8 @@ #endif #endif /* HAVE_RECORDING */ + + +#if LCD_DEPTH > 1 +#define HAVE_BMP_RESIZE +#endif