rendered paste bodycommit cfe31d97ff1c4edf6f4c000ecd334de5625d81a3Author: Nicolas Pennequin <nicolas@nicolas-laptop.(none)>Date: Wed Feb 6 22:25:36 2008 +0100 Smooth scaling in the corediff --git a/apps/SOURCES b/apps/SOURCESindex c93c5bc..1f53a0d 100644--- a/apps/SOURCES+++ b/apps/SOURCES@@ -73,6 +73,7 @@ player/keyboard.c #endif #ifdef HAVE_LCD_BITMAP recorder/bmp.c+recorder/bmp_smooth_scale.c recorder/icons.c recorder/keyboard.c recorder/peakmeter.cdiff --git a/apps/plugin.c b/apps/plugin.cindex 6862ddb..2012b54 100644--- a/apps/plugin.c+++ b/apps/plugin.c@@ -592,6 +592,10 @@ static const struct plugin_api rockbox_api = { dsp_configure, dsp_process, #endif /* CONFIG_CODEC == SWCODEC */++#ifdef HAVE_LCD_BITMAP+ smooth_resize_bitmap,+#endif }; int plugin_load(const char* plugin, void* parameter)diff --git a/apps/plugin.h b/apps/plugin.hindex 164a2c9..afba1b1 100644--- a/apps/plugin.h+++ b/apps/plugin.h@@ -731,6 +731,10 @@ struct plugin_api { int (*dsp_process)(struct dsp_config *dsp, char *dest, const char *src[], int count); #endif /* CONFIG_CODEC == SWCODEC */++#ifdef HAVE_LCD_BITMAP+ void (*smooth_resize_bitmap)(struct bitmap *src, struct bitmap *dst);+#endif }; /* plugin header */diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIESindex 4b267c1..fc81614 100644--- a/apps/plugins/CATEGORIES+++ b/apps/plugins/CATEGORIES@@ -82,6 +82,7 @@ test_disk,apps test_fps,apps test_sampr,apps test_scanrate,apps+test_resize,apps test_viewports,apps text_editor,apps vbrfix,viewersdiff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCESindex 8ad7c3f..c8f269e 100644--- a/apps/plugins/SOURCES+++ b/apps/plugins/SOURCES@@ -22,6 +22,8 @@ stopwatch.c vbrfix.c viewer.c +test_resize.c+ #ifdef OLYMPUS_MROBE_500 /* remove these once the plugins before it are compileable */ jpeg.cdiff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.cindex f9a723c..03dc3e1 100644--- a/apps/plugins/sliding_puzzle.c+++ b/apps/plugins/sliding_puzzle.c@@ -239,7 +239,7 @@ static bool load_resize_bitmap(void) FORMAT_NATIVE ); if( rc > 0 ) {- simple_resize_bitmap( &temp_bitmap, &main_bitmap );+ rb->smooth_resize_bitmap( &temp_bitmap, &main_bitmap ); puzzle_bmp_ptr = (const fb_data *)img_buf; rb->strcpy( img_buf_path, filename ); return true;diff --git a/apps/plugins/test_resize.c b/apps/plugins/test_resize.cindex 8583613..109b608 100644--- a/apps/plugins/test_resize.c+++ b/apps/plugins/test_resize.c@@ -36,31 +36,28 @@ const struct button_mapping *plugin_contexts[] #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 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 200-#define MAX_OUTPUT_HEIGHT 200+#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[100*100];+static fb_data input_bmp_data[200*200]; static fb_data output_bmp_data[MAX_OUTPUT_WIDTH*MAX_OUTPUT_HEIGHT]; @@ -93,11 +90,22 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 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); - simple_resize_bitmap(&input_bmp, &output_bmp);+ switch ( scale_algorithm ) {+ case 0:+ rb->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);@@ -118,8 +126,23 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) 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;+ 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; } }diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.hindex 3d33a8c..53c4f19 100644--- a/apps/recorder/bmp.h+++ b/apps/recorder/bmp.h@@ -39,4 +39,11 @@ int read_bmp_fd(int fd, struct bitmap *bm, int maxsize, int format);++/**+ 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);+ #endifdiff --git a/apps/recorder/bmp_smooth_scale.c b/apps/recorder/bmp_smooth_scale.cnew file mode 100644index 0000000..a500bfa--- /dev/null+++ b/apps/recorder/bmp_smooth_scale.c@@ -0,0 +1,444 @@+/***************************************************************************+ * __________ __ ___.+ * 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 <willem@stack.nl>. 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 <willem@stack.nl>. 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++;+ }+ }+ }+}