All pastes #894333 Raw Edit

smooth_scaling_core.patch

public diff v1 · immutable
#894333 ·published 2008-02-06 21:34 UTC
rendered paste body
commit 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++;+            }+        }+    }+}