From 8d811b5a9fc1555674cf344528261b0a40cfd58b Mon Sep 17 00:00:00 2001 From: Jonas Hurrelmann Date: Wed, 12 Dec 2007 11:01:33 +0100 Subject: [PATCH] Port of the imlib2 based smooth scaling algorithm. --- apps/plugins/CATEGORIES | 1 + apps/plugins/lib/SOURCES | 1 + apps/plugins/lib/bmp.h | 7 + apps/plugins/lib/bmp_smooth_scale.c | 500 +++++++++++++++++++++++++++++++++++ apps/plugins/resize_test.c | 127 --------- apps/plugins/test_resize.c | 150 +++++++++++ 6 files changed, 659 insertions(+), 127 deletions(-) create mode 100644 apps/plugins/lib/bmp_smooth_scale.c delete mode 100644 apps/plugins/resize_test.c create mode 100644 apps/plugins/test_resize.c diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES index 57cab53..3b6246c 100644 --- a/apps/plugins/CATEGORIES +++ b/apps/plugins/CATEGORIES @@ -79,6 +79,7 @@ stopwatch,apps test_codec,viewers test_disk,apps test_fps,apps +test_resize,apps test_sampr,apps test_scanrate,apps text_editor,apps diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index f671184..1d37018 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES @@ -27,6 +27,7 @@ xlcd_draw.c xlcd_scroll.c #ifdef HAVE_LCD_COLOR bmp.c +bmp_smooth_scale.c #endif #endif pluginlib_actions.c diff --git a/apps/plugins/lib/bmp.h b/apps/plugins/lib/bmp.h index e35c1ec..c2bbc94 100644 --- a/apps/plugins/lib/bmp.h +++ b/apps/plugins/lib/bmp.h @@ -33,4 +33,11 @@ int save_bmp_file( char* filename, struct bitmap *bm, struct plugin_api* rb ); */ 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. + The maximum destination size is LCD_WIDTH x LCD_HEIGHT. + */ +int smooth_resize_bitmap(struct bitmap *src, struct bitmap *dst); + #endif diff --git a/apps/plugins/lib/bmp_smooth_scale.c b/apps/plugins/lib/bmp_smooth_scale.c new file mode 100644 index 0000000..4b8b1d3 --- /dev/null +++ b/apps/plugins/lib/bmp_smooth_scale.c @@ -0,0 +1,500 @@ +/*************************************************************************** + * __________ __ ___. + * 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) + * + * 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. + */ + +#include "bmp.h" +#include "lcd.h" + +#define INV_XAP (256 - xapoints[x]) +#define XAP (xapoints[x]) +#define INV_YAP (256 - yapoints[y]) +#define YAP (yapoints[y]) + +struct scale_info_static { + int xpoints[LCD_WIDTH + 1]; + fb_data *ypoints[LCD_HEIGHT + 1]; + int xapoints[LCD_WIDTH], yapoints[LCD_HEIGHT]; + int xup_yup; +}; + +#if 0 +/* at some point a dynamically or user initialized lookup + table might be reasonable */ +struct scale_info { + int *xpoints; + fb_data **ypoints; + int *xapoints, *yapoints; + int xup_yup; +}; +#endif + +static void calc_xpoints(int sw, int dw, int *p) +{ + int i, j = 0; + int val, inc = 0; + + val = 0; + inc = (sw << 16) / dw; + for (i = 0; i < dw; i++) { + p[j++] = (val >> 16); + val += inc; + } +} + + +static void calc_ypoints(fb_data * src, int sw, int sh, int dh, + fb_data ** p) +{ + int i, j = 0; + int val, inc; + + val = 0; + inc = (sh << 16) / dh; + for (i = 0; i < dh; i++) { + p[j++] = src + ((val >> 16) * sw); + val += inc; + } +} + +static void calc_apoints(int s, int d, int up, int *p) +{ + int i, j = 0; + + /* scaling up */ + if (up) { + int val, inc; + + val = 0; + inc = (s << 16) / d; + for (i = 0; i < d; i++) { + p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00); + if ((val >> 16) >= (s - 1)) + p[j - 1] = 0; + val += inc; + } + } + + /* scaling down */ + else { + int val, inc, ap, Cp; + val = 0; + inc = (s << 16) / d; + Cp = ((d << 14) / s) + 1; + for (i = 0; i < d; i++) { + ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; + p[j] = ap | (Cp << 16); + j++; + val += inc; + } + } +} + +static void image_scale_rgb(struct scale_info_static *isi, fb_data * dest, + int dw, int dh, int dow, int sow) +{ + fb_data *sptr, *dptr; + int x, y, end; + fb_data **ypoints = isi->ypoints; + int *xpoints = isi->xpoints; + int *xapoints = isi->xapoints; + int *yapoints = isi->yapoints; + + end = dw; + /* scaling up both ways */ + if (isi->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 */ + dptr = dest + (y * dow); + sptr = ypoints[y]; + 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; + + if (XAP > 0) { + pix = ypoints[y] + xpoints[x]; + 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 = ypoints[y] + xpoints[x]; + 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; + + if (XAP > 0) { + pix = ypoints[y] + xpoints[x]; + 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[xpoints[x]]; + } + } + } + } + /* if we're scaling down vertically */ + else if (isi->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++) { + Cy = YAP >> 16; + yap = YAP & 0xffff; + + dptr = dest + (y * dow); + for (x = 0; x < end; x++) { + pix = ypoints[y] + xpoints[x]; + 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 = ypoints[y] + xpoints[x] + 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 (isi->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++) { + dptr = dest + (y * dow); + for (x = 0; x < end; x++) { + Cx = XAP >> 16; + xap = XAP & 0xffff; + + pix = ypoints[y] + xpoints[x]; + 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 = ypoints[y] + xpoints[x] + 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++) { + Cy = YAP >> 16; + yap = YAP & 0xffff; + + dptr = dest + (y * dow); + for (x = 0; x < end; x++) { + Cx = XAP >> 16; + xap = XAP & 0xffff; + + sptr = ypoints[y] + xpoints[x]; + + 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++; + } + } + } +} + +/* don't clutter, we don't need them anymore */ +#undef INV_XAP +#undef XAP +#undef INV_YAP +#undef YAP + +/** + Advanced image scale from src to dst (bilinear) based on imlib2. + Source and destination dimensions are read from the struct bitmap. + The maximum destination size is LCD_WIDTH x LCD_HEIGHT. + */ +int smooth_resize_bitmap(struct bitmap *src, struct bitmap *dst) +{ + int sw = src->width; + int sh = src->height; + + int dw = dst->width; + int dh = dst->height; + + if (dw > LCD_WIDTH || dh > LCD_HEIGHT) + return -1; + + static struct scale_info_static isi; + + isi.xup_yup = (dw >= sw) + ((dh >= sh) << 1); + + calc_xpoints(sw, dw, isi.xpoints); + calc_ypoints((fb_data *) src->data, sw, sh, dh, isi.ypoints); + + calc_apoints(sw, dw, (dw >= sw), isi.xapoints); + calc_apoints(sh, dh, (dh >= sh), isi.yapoints); + + image_scale_rgb(&isi, (fb_data *) dst->data, dw, dh, dw, sw); + return 1; +} diff --git a/apps/plugins/resize_test.c b/apps/plugins/resize_test.c deleted file mode 100644 index 8583613..0000000 --- a/apps/plugins/resize_test.c +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 Jonas Hurrelmann - * - * 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. - * - ****************************************************************************/ - -/* Resizing test plugin. Loads /test.bmp (max 100x100) and displays a resized - * version. Use the scrollwheel or the left/right keys to change the size of - * the resizded version. - */ - -#include "plugin.h" -#include "pluginlib_actions.h" -#include "bmp.h" - -PLUGIN_HEADER - -static struct plugin_api* rb; - -const struct button_mapping *plugin_contexts[] -= {generic_actions, generic_directions}; - -#define NB_ACTION_CONTEXTS sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) - -/* Key assignement */ -#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ - || (CONFIG_KEYPAD == IPOD_3G_PAD) \ - || (CONFIG_KEYPAD == IPOD_4G_PAD) \ - || (CONFIG_KEYPAD == SANSA_E200_PAD) -#define SIZE_INCREASE PLA_UP -#define SIZE_INCREASE_REPEAT PLA_UP_REPEAT -#define SIZE_DECREASE PLA_DOWN -#define SIZE_DECREASE_REPEAT PLA_DOWN_REPEAT -#else -#define SIZE_INCREASE PLA_RIGHT -#define SIZE_INCREASE_REPEAT PLA_RIGHT_REPEAT -#define SIZE_DECREASE PLA_LEFT -#define SIZE_DECREASE_REPEAT PLA_LEFT_REPEAT -#endif -#define BUTTON_QUIT PLA_QUIT - -#define MAX_OUTPUT_WIDTH 200 -#define MAX_OUTPUT_HEIGHT 200 - -static fb_data *b; - -static struct bitmap input_bmp; -static struct bitmap output_bmp; - -static fb_data input_bmp_data[100*100]; -static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT]; - - -/* this is the plugin entry point */ -enum plugin_status plugin_start(struct plugin_api* api, void* parameter) -{ - (void)parameter; - - rb = api; - b = rb->lcd_framebuffer; - - rb->lcd_set_background(LCD_RGBPACK(0,0,0)); - rb->lcd_clear_display(); // TODO: Optimizes this by e.g. invalidating rects - - input_bmp.data = (char*)input_bmp_data; - output_bmp.data = (char*)output_bmp_data; - - int ret = rb->read_bmp_file("/test.bmp", &input_bmp, sizeof(input_bmp_data), - FORMAT_NATIVE); - - if (ret < 0) { - rb->splash(HZ, "Could not load /test.bmp"); - return PLUGIN_ERROR; - } - - int button; - output_bmp.width = 50; - output_bmp.height = 50; - - DEBUGF("input_bmp_data starts at %p\n", input_bmp_data); - DEBUGF("output_bmp_data starts at %p\n", output_bmp_data); - - while(1) { - rb->lcd_clear_display(); - rb->lcd_bitmap(input_bmp_data, 0, 0, input_bmp.width, input_bmp.height); - - simple_resize_bitmap(&input_bmp, &output_bmp); - - rb->lcd_bitmap(output_bmp_data, 0, 100, output_bmp.width, - output_bmp.height); - - rb->lcd_update(); - button = pluginlib_getaction(rb, HZ, - plugin_contexts, NB_ACTION_CONTEXTS); - switch (button) { - case BUTTON_QUIT: - return PLUGIN_OK; - case SIZE_INCREASE: - case SIZE_INCREASE_REPEAT: - if (output_bmp.width < MAX_OUTPUT_WIDTH - 2) - output_bmp.width += 2; - if (output_bmp.height < MAX_OUTPUT_HEIGHT - 2) - output_bmp.height += 2; - break; - - case SIZE_DECREASE: - case SIZE_DECREASE_REPEAT: - if (output_bmp.width >= 2) output_bmp.width -= 2; - if (output_bmp.height >= 2) output_bmp.height -= 2; - break; - } - } - return PLUGIN_OK; -} diff --git a/apps/plugins/test_resize.c b/apps/plugins/test_resize.c new file mode 100644 index 0000000..7d3436a --- /dev/null +++ b/apps/plugins/test_resize.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Jonas Hurrelmann + * + * 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. + * + ****************************************************************************/ + +/* Resizing test plugin. Loads /test.bmp (max 100x100) and displays a resized + * version. Use the scrollwheel or the left/right keys to change the size of + * the resizded version. + */ + +#include "plugin.h" +#include "pluginlib_actions.h" +#include "bmp.h" + +PLUGIN_HEADER + +static struct plugin_api* rb; + +const struct button_mapping *plugin_contexts[] += {generic_actions, generic_directions}; + +#define NB_ACTION_CONTEXTS sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) + +/* Key assignement */ +#define SIZE_INCREASE PLA_UP +#define SIZE_INCREASE_REPEAT PLA_UP_REPEAT +#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 BUTTON_QUIT PLA_QUIT +#define CHANGE_MODE PLA_MENU + +#define MAX_OUTPUT_WIDTH LCD_WIDTH +#define MAX_OUTPUT_HEIGHT LCD_HEIGHT + +static fb_data *b; + +static struct bitmap input_bmp; +static struct bitmap output_bmp; + +static fb_data input_bmp_data[200*200]; +static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT]; + + +/* this is the plugin entry point */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + (void)parameter; + + rb = api; + b = rb->lcd_framebuffer; + + rb->lcd_set_background(LCD_RGBPACK(0,0,0)); + rb->lcd_clear_display(); // TODO: Optimizes this by e.g. invalidating rects + + input_bmp.data = (char*)input_bmp_data; + output_bmp.data = (char*)output_bmp_data; + + int ret = rb->read_bmp_file("/test.bmp", &input_bmp, sizeof(input_bmp_data), + FORMAT_NATIVE); + + if (ret < 0) { + rb->splash(HZ, "Could not load /test.bmp"); + return PLUGIN_ERROR; + } + + int button; + output_bmp.width = 50; + output_bmp.height = 50; + + 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; + + 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->lcd_bitmap(output_bmp_data, 0, 100, output_bmp.width, + output_bmp.height); + + rb->lcd_update(); + button = pluginlib_getaction(rb, HZ, + plugin_contexts, NB_ACTION_CONTEXTS); + switch (button) { + case BUTTON_QUIT: + return PLUGIN_OK; + case SIZE_INCREASE: + case SIZE_INCREASE_REPEAT: + if (output_bmp.width < MAX_OUTPUT_WIDTH - 2) + output_bmp.width += 2; + if (output_bmp.height < MAX_OUTPUT_HEIGHT - 2) + output_bmp.height += 2; + break; + + case SIZE_DECREASE: + case SIZE_DECREASE_REPEAT: + if (output_bmp.width > 2) output_bmp.width -= 2; + 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; + break; + + case CHANGE_MODE: + scale_algorithm = (scale_algorithm+1)%2; + break; + } + } + return PLUGIN_OK; +} -- 1.5.3.7