src/gui/painting/qimagescale.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 #include <private/qimagescale_p.h>
       
    42 #include <private/qdrawhelper_p.h>
       
    43 
       
    44 #include "qimage.h"
       
    45 #include "qcolor.h"
       
    46 
       
    47 QT_BEGIN_NAMESPACE
       
    48 
       
    49 namespace QImageScale {
       
    50     struct QImageScaleInfo;
       
    51 }
       
    52 
       
    53 typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
       
    54                                    int dxx, int dyy, int dx, int dy, int dw,
       
    55                                    int dh, int dow, int sow);
       
    56 
       
    57 static void qt_qimageScaleAARGB(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
       
    58                          int dxx, int dyy, int dx, int dy, int dw,
       
    59                          int dh, int dow, int sow);
       
    60 
       
    61 static void qt_qimageScaleAARGBA(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
       
    62                           int dxx, int dyy, int dx, int dy, int dw,
       
    63                           int dh, int dow, int sow);
       
    64 
       
    65 qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
       
    66 qt_qimageScaleFunc qt_qimageScaleRgb  = qt_qimageScaleAARGB;
       
    67 
       
    68 
       
    69 /*
       
    70  * Copyright (C) 2004, 2005 Daniel M. Duley
       
    71  *
       
    72  * Redistribution and use in source and binary forms, with or without
       
    73  * modification, are permitted provided that the following conditions
       
    74  * are met:
       
    75  *
       
    76  * 1. Redistributions of source code must retain the above copyright
       
    77  *    notice, this list of conditions and the following disclaimer.
       
    78  * 2. Redistributions in binary form must reproduce the above copyright
       
    79  *    notice, this list of conditions and the following disclaimer in the
       
    80  *    documentation and/or other materials provided with the distribution.
       
    81  *
       
    82  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
       
    83  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
       
    84  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
       
    85  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
       
    86  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
       
    87  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    88  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    89  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    90  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    91  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    92  *
       
    93  */
       
    94 
       
    95 /* OTHER CREDITS:
       
    96  *
       
    97  * This is the normal smoothscale method, based on Imlib2's smoothscale.
       
    98  *
       
    99  * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
       
   100  * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
       
   101  * C algorithm and it ran at about the same speed as my MMX optimized one...
       
   102  * Finally I ported Imlib's MMX version and it ran in less than half the
       
   103  * time as my MMX algorithm, (taking only a quarter of the time Qt does).
       
   104  * After further optimization it seems to run at around 1/6th.
       
   105  *
       
   106  * Changes include formatting, namespaces and other C++'ings, removal of old
       
   107  * #ifdef'ed code, and removal of unneeded border calculation code.
       
   108  *
       
   109  * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
       
   110  * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
       
   111  * (C) Daniel M. Duley.
       
   112  */
       
   113 
       
   114 
       
   115 namespace QImageScale {
       
   116     struct QImageScaleInfo {
       
   117         int *xpoints;
       
   118         unsigned int **ypoints;
       
   119         int *xapoints, *yapoints;
       
   120         int xup_yup;
       
   121     };
       
   122 
       
   123     unsigned int** qimageCalcYPoints(unsigned int *src, int sw, int sh,
       
   124                                      int dh);
       
   125     int* qimageCalcXPoints(int sw, int dw);
       
   126     int* qimageCalcApoints(int s, int d, int up);
       
   127     QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
       
   128     QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
       
   129                                          int dw, int dh, char aa);
       
   130 }
       
   131 
       
   132 using namespace QImageScale;
       
   133 
       
   134 //
       
   135 // Code ported from Imlib...
       
   136 //
       
   137 
       
   138 // FIXME: replace with qRed, etc... These work on pointers to pixels, not
       
   139 // pixel values
       
   140 #define A_VAL(p) (qAlpha(*p))
       
   141 #define R_VAL(p) (qRed(*p))
       
   142 #define G_VAL(p) (qGreen(*p))
       
   143 #define B_VAL(p) (qBlue(*p))
       
   144 
       
   145 #define INV_XAP                   (256 - xapoints[x])
       
   146 #define XAP                       (xapoints[x])
       
   147 #define INV_YAP                   (256 - yapoints[dyy + y])
       
   148 #define YAP                       (yapoints[dyy + y])
       
   149 
       
   150 unsigned int** QImageScale::qimageCalcYPoints(unsigned int *src,
       
   151                                               int sw, int sh, int dh)
       
   152 {
       
   153     unsigned int **p;
       
   154     int i, j = 0;
       
   155     int val, inc, rv = 0;
       
   156 
       
   157     if(dh < 0){
       
   158         dh = -dh;
       
   159         rv = 1;
       
   160     }
       
   161     p = new unsigned int* [dh+1];
       
   162 
       
   163     int up = qAbs(dh) >= sh;
       
   164     val = up ? 0x8000 * sh / dh - 0x8000 : 0;
       
   165     inc = (sh << 16) / dh;
       
   166     for(i = 0; i < dh; i++){
       
   167         p[j++] = src + qMax(0, val >> 16) * sw;
       
   168         val += inc;
       
   169     }
       
   170     if(rv){
       
   171         for(i = dh / 2; --i >= 0; ){
       
   172             unsigned int *tmp = p[i];
       
   173             p[i] = p[dh - i - 1];
       
   174             p[dh - i - 1] = tmp;
       
   175         }
       
   176     }
       
   177     return(p);
       
   178 }
       
   179 
       
   180 int* QImageScale::qimageCalcXPoints(int sw, int dw)
       
   181 {
       
   182     int *p, i, j = 0;
       
   183     int val, inc, rv = 0;
       
   184 
       
   185     if(dw < 0){
       
   186         dw = -dw;
       
   187         rv = 1;
       
   188     }
       
   189     p = new int[dw+1];
       
   190 
       
   191     int up = qAbs(dw) >= sw;
       
   192     val = up ? 0x8000 * sw / dw - 0x8000 : 0;
       
   193     inc = (sw << 16) / dw;
       
   194     for(i = 0; i < dw; i++){
       
   195         p[j++] = qMax(0, val >> 16);
       
   196         val += inc;
       
   197     }
       
   198 
       
   199     if(rv){
       
   200         for(i = dw / 2; --i >= 0; ){
       
   201             int tmp = p[i];
       
   202             p[i] = p[dw - i - 1];
       
   203             p[dw - i - 1] = tmp;
       
   204         }
       
   205     }
       
   206    return(p);
       
   207 }
       
   208 
       
   209 int* QImageScale::qimageCalcApoints(int s, int d, int up)
       
   210 {
       
   211     int *p, i, j = 0, rv = 0;
       
   212 
       
   213     if(d < 0){
       
   214         rv = 1;
       
   215         d = -d;
       
   216     }
       
   217     p = new int[d];
       
   218 
       
   219     /* scaling up */
       
   220     if(up){
       
   221         int val, inc;
       
   222 
       
   223         val = 0x8000 * s / d - 0x8000;
       
   224         inc = (s << 16) / d;
       
   225         for(i = 0; i < d; i++){
       
   226             int pos = val >> 16;
       
   227             if (pos < 0)
       
   228                 p[j++] = 0;
       
   229             else if (pos >= (s - 1))
       
   230                 p[j++] = 0;
       
   231             else
       
   232                 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
       
   233             val += inc;
       
   234         }
       
   235     }
       
   236     /* scaling down */
       
   237     else{
       
   238         int val, inc, ap, Cp;
       
   239         val = 0;
       
   240         inc = (s << 16) / d;
       
   241         Cp = ((d << 14) / s) + 1;
       
   242         for(i = 0; i < d; i++){
       
   243             ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
       
   244             p[j] = ap | (Cp << 16);
       
   245             j++;
       
   246             val += inc;
       
   247         }
       
   248     }
       
   249     if(rv){
       
   250         int tmp;
       
   251         for(i = d / 2; --i >= 0; ){
       
   252             tmp = p[i];
       
   253             p[i] = p[d - i - 1];
       
   254             p[d - i - 1] = tmp;
       
   255         }
       
   256     }
       
   257     return(p);
       
   258 }
       
   259 
       
   260 QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
       
   261 {
       
   262     if(isi){
       
   263         delete[] isi->xpoints;
       
   264         delete[] isi->ypoints;
       
   265         delete[] isi->xapoints;
       
   266         delete[] isi->yapoints;
       
   267         delete isi;
       
   268     }
       
   269     return 0;
       
   270 }
       
   271 
       
   272 QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
       
   273                                                   int sw, int sh,
       
   274                                                   int dw, int dh, char aa)
       
   275 {
       
   276     QImageScaleInfo *isi;
       
   277     int scw, sch;
       
   278 
       
   279     scw = dw * qlonglong(img.width()) / sw;
       
   280     sch = dh * qlonglong(img.height()) / sh;
       
   281 
       
   282     isi = new QImageScaleInfo;
       
   283     if(!isi)
       
   284         return 0;
       
   285     memset(isi, 0, sizeof(QImageScaleInfo));
       
   286 
       
   287     isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
       
   288 
       
   289     isi->xpoints = qimageCalcXPoints(img.width(), scw);
       
   290     if(!isi->xpoints)
       
   291         return(qimageFreeScaleInfo(isi));
       
   292     isi->ypoints = qimageCalcYPoints((unsigned int *)img.scanLine(0),
       
   293                                      img.bytesPerLine() / 4, img.height(), sch);
       
   294     if (!isi->ypoints)
       
   295         return(qimageFreeScaleInfo(isi));
       
   296     if(aa) {
       
   297         isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
       
   298         if(!isi->xapoints)
       
   299             return(qimageFreeScaleInfo(isi));
       
   300         isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
       
   301         if(!isi->yapoints)
       
   302             return(qimageFreeScaleInfo(isi));
       
   303     }
       
   304     return(isi);
       
   305 }
       
   306 
       
   307 /* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*/
       
   308 
       
   309 /* scale by area sampling */
       
   310 static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
       
   311                                  int dxx, int dyy, int dx, int dy, int dw,
       
   312                                  int dh, int dow, int sow)
       
   313 {
       
   314     unsigned int *sptr, *dptr;
       
   315     int x, y, end;
       
   316     unsigned int **ypoints = isi->ypoints;
       
   317     int *xpoints = isi->xpoints;
       
   318     int *xapoints = isi->xapoints;
       
   319     int *yapoints = isi->yapoints;
       
   320 
       
   321     end = dxx + dw;
       
   322     /* scaling up both ways */
       
   323     if(isi->xup_yup == 3){
       
   324         /* go through every scanline in the output buffer */
       
   325         for(y = 0; y < dh; y++){
       
   326             /* calculate the source line we'll scan from */
       
   327             dptr = dest + dx + ((y + dy) * dow);
       
   328             sptr = ypoints[dyy + y];
       
   329             if(YAP > 0){
       
   330                 for(x = dxx; x < end; x++){
       
   331                     int r, g, b, a;
       
   332                     int rr, gg, bb, aa;
       
   333                     unsigned int *pix;
       
   334 
       
   335                     if(XAP > 0){
       
   336                         pix = ypoints[dyy + y] + xpoints[x];
       
   337                         r = R_VAL(pix) * INV_XAP;
       
   338                         g = G_VAL(pix) * INV_XAP;
       
   339                         b = B_VAL(pix) * INV_XAP;
       
   340                         a = A_VAL(pix) * INV_XAP;
       
   341                         pix++;
       
   342                         r += R_VAL(pix) * XAP;
       
   343                         g += G_VAL(pix) * XAP;
       
   344                         b += B_VAL(pix) * XAP;
       
   345                         a += A_VAL(pix) * XAP;
       
   346                         pix += sow;
       
   347                         rr = R_VAL(pix) * XAP;
       
   348                         gg = G_VAL(pix) * XAP;
       
   349                         bb = B_VAL(pix) * XAP;
       
   350                         aa = A_VAL(pix) * XAP;
       
   351                         pix--;
       
   352                         rr += R_VAL(pix) * INV_XAP;
       
   353                         gg += G_VAL(pix) * INV_XAP;
       
   354                         bb += B_VAL(pix) * INV_XAP;
       
   355                         aa += A_VAL(pix) * INV_XAP;
       
   356                         r = ((rr * YAP) + (r * INV_YAP)) >> 16;
       
   357                         g = ((gg * YAP) + (g * INV_YAP)) >> 16;
       
   358                         b = ((bb * YAP) + (b * INV_YAP)) >> 16;
       
   359                         a = ((aa * YAP) + (a * INV_YAP)) >> 16;
       
   360                         *dptr++ = qRgba(r, g, b, a);
       
   361                     }
       
   362                     else{
       
   363                         pix = ypoints[dyy + y] + xpoints[x];
       
   364                         r = R_VAL(pix) * INV_YAP;
       
   365                         g = G_VAL(pix) * INV_YAP;
       
   366                         b = B_VAL(pix) * INV_YAP;
       
   367                         a = A_VAL(pix) * INV_YAP;
       
   368                         pix += sow;
       
   369                         r += R_VAL(pix) * YAP;
       
   370                         g += G_VAL(pix) * YAP;
       
   371                         b += B_VAL(pix) * YAP;
       
   372                         a += A_VAL(pix) * YAP;
       
   373                         r >>= 8;
       
   374                         g >>= 8;
       
   375                         b >>= 8;
       
   376                         a >>= 8;
       
   377                         *dptr++ = qRgba(r, g, b, a);
       
   378                     }
       
   379                 }
       
   380             }
       
   381             else{
       
   382                 for(x = dxx; x < end; x++){
       
   383                     int r, g, b, a;
       
   384                     unsigned int *pix;
       
   385 
       
   386                     if(XAP > 0){
       
   387                         pix = ypoints[dyy + y] + xpoints[x];
       
   388                         r = R_VAL(pix) * INV_XAP;
       
   389                         g = G_VAL(pix) * INV_XAP;
       
   390                         b = B_VAL(pix) * INV_XAP;
       
   391                         a = A_VAL(pix) * INV_XAP;
       
   392                         pix++;
       
   393                         r += R_VAL(pix) * XAP;
       
   394                         g += G_VAL(pix) * XAP;
       
   395                         b += B_VAL(pix) * XAP;
       
   396                         a += A_VAL(pix) * XAP;
       
   397                         r >>= 8;
       
   398                         g >>= 8;
       
   399                         b >>= 8;
       
   400                         a >>= 8;
       
   401                         *dptr++ = qRgba(r, g, b, a);
       
   402                     }
       
   403                     else
       
   404                         *dptr++ = sptr[xpoints[x] ];
       
   405                 }
       
   406             }
       
   407         }
       
   408     }
       
   409     /* if we're scaling down vertically */
       
   410     else if(isi->xup_yup == 1){
       
   411         /*\ 'Correct' version, with math units prepared for MMXification \*/
       
   412         int Cy, j;
       
   413         unsigned int *pix;
       
   414         int r, g, b, a, rr, gg, bb, aa;
       
   415         int yap;
       
   416 
       
   417         /* go through every scanline in the output buffer */
       
   418         for(y = 0; y < dh; y++){
       
   419             Cy = YAP >> 16;
       
   420             yap = YAP & 0xffff;
       
   421 
       
   422             dptr = dest + dx + ((y + dy) * dow);
       
   423             for(x = dxx; x < end; x++){
       
   424                 pix = ypoints[dyy + y] + xpoints[x];
       
   425                 r = R_VAL(pix) * yap;
       
   426                 g = G_VAL(pix) * yap;
       
   427                 b = B_VAL(pix) * yap;
       
   428                 a = A_VAL(pix) * yap;
       
   429                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   430                     pix += sow;
       
   431                     r += R_VAL(pix) * Cy;
       
   432                     g += G_VAL(pix) * Cy;
       
   433                     b += B_VAL(pix) * Cy;
       
   434                     a += A_VAL(pix) * Cy;
       
   435                 }
       
   436                 if(j > 0){
       
   437                     pix += sow;
       
   438                     r += R_VAL(pix) * j;
       
   439                     g += G_VAL(pix) * j;
       
   440                     b += B_VAL(pix) * j;
       
   441                     a += A_VAL(pix) * j;
       
   442                 }
       
   443                 if(XAP > 0){
       
   444                     pix = ypoints[dyy + y] + xpoints[x] + 1;
       
   445                     rr = R_VAL(pix) * yap;
       
   446                     gg = G_VAL(pix) * yap;
       
   447                     bb = B_VAL(pix) * yap;
       
   448                     aa = A_VAL(pix) * yap;
       
   449                     for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   450                         pix += sow;
       
   451                         rr += R_VAL(pix) * Cy;
       
   452                         gg += G_VAL(pix) * Cy;
       
   453                         bb += B_VAL(pix) * Cy;
       
   454                         aa += A_VAL(pix) * Cy;
       
   455                     }
       
   456                     if(j > 0){
       
   457                         pix += sow;
       
   458                         rr += R_VAL(pix) * j;
       
   459                         gg += G_VAL(pix) * j;
       
   460                         bb += B_VAL(pix) * j;
       
   461                         aa += A_VAL(pix) * j;
       
   462                     }
       
   463                     r = r * INV_XAP;
       
   464                     g = g * INV_XAP;
       
   465                     b = b * INV_XAP;
       
   466                     a = a * INV_XAP;
       
   467                     r = (r + ((rr * XAP))) >> 12;
       
   468                     g = (g + ((gg * XAP))) >> 12;
       
   469                     b = (b + ((bb * XAP))) >> 12;
       
   470                     a = (a + ((aa * XAP))) >> 12;
       
   471                 }
       
   472                 else{
       
   473                     r >>= 4;
       
   474                     g >>= 4;
       
   475                     b >>= 4;
       
   476                     a >>= 4;
       
   477                 }
       
   478                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
       
   479                 dptr++;
       
   480             }
       
   481         }
       
   482     }
       
   483     /* if we're scaling down horizontally */
       
   484     else if(isi->xup_yup == 2){
       
   485         /*\ 'Correct' version, with math units prepared for MMXification \*/
       
   486         int Cx, j;
       
   487         unsigned int *pix;
       
   488         int r, g, b, a, rr, gg, bb, aa;
       
   489         int xap;
       
   490 
       
   491         /* go through every scanline in the output buffer */
       
   492         for(y = 0; y < dh; y++){
       
   493             dptr = dest + dx + ((y + dy) * dow);
       
   494             for(x = dxx; x < end; x++){
       
   495                 Cx = XAP >> 16;
       
   496                 xap = XAP & 0xffff;
       
   497 
       
   498                 pix = ypoints[dyy + y] + xpoints[x];
       
   499                 r = R_VAL(pix) * xap;
       
   500                 g = G_VAL(pix) * xap;
       
   501                 b = B_VAL(pix) * xap;
       
   502                 a = A_VAL(pix) * xap;
       
   503                 for(j = (1 << 14) - xap; j > Cx; j -= Cx){
       
   504                     pix++;
       
   505                     r += R_VAL(pix) * Cx;
       
   506                     g += G_VAL(pix) * Cx;
       
   507                     b += B_VAL(pix) * Cx;
       
   508                     a += A_VAL(pix) * Cx;
       
   509                 }
       
   510                 if(j > 0){
       
   511                     pix++;
       
   512                     r += R_VAL(pix) * j;
       
   513                     g += G_VAL(pix) * j;
       
   514                     b += B_VAL(pix) * j;
       
   515                     a += A_VAL(pix) * j;
       
   516                 }
       
   517                 if(YAP > 0){
       
   518                     pix = ypoints[dyy + y] + xpoints[x] + sow;
       
   519                     rr = R_VAL(pix) * xap;
       
   520                     gg = G_VAL(pix) * xap;
       
   521                     bb = B_VAL(pix) * xap;
       
   522                     aa = A_VAL(pix) * xap;
       
   523                     for(j = (1 << 14) - xap; j > Cx; j -= Cx){
       
   524                         pix++;
       
   525                         rr += R_VAL(pix) * Cx;
       
   526                         gg += G_VAL(pix) * Cx;
       
   527                         bb += B_VAL(pix) * Cx;
       
   528                         aa += A_VAL(pix) * Cx;
       
   529                     }
       
   530                     if(j > 0){
       
   531                         pix++;
       
   532                         rr += R_VAL(pix) * j;
       
   533                         gg += G_VAL(pix) * j;
       
   534                         bb += B_VAL(pix) * j;
       
   535                         aa += A_VAL(pix) * j;
       
   536                     }
       
   537                     r = r * INV_YAP;
       
   538                     g = g * INV_YAP;
       
   539                     b = b * INV_YAP;
       
   540                     a = a * INV_YAP;
       
   541                     r = (r + ((rr * YAP))) >> 12;
       
   542                     g = (g + ((gg * YAP))) >> 12;
       
   543                     b = (b + ((bb * YAP))) >> 12;
       
   544                     a = (a + ((aa * YAP))) >> 12;
       
   545                 }
       
   546                 else{
       
   547                     r >>= 4;
       
   548                     g >>= 4;
       
   549                     b >>= 4;
       
   550                     a >>= 4;
       
   551                 }
       
   552                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
       
   553                 dptr++;
       
   554             }
       
   555         }
       
   556     }
       
   557     /* if we're scaling down horizontally & vertically */
       
   558     else{
       
   559         /*\ 'Correct' version, with math units prepared for MMXification:
       
   560          |*|  The operation 'b = (b * c) >> 16' translates to pmulhw,
       
   561          |*|  so the operation 'b = (b * c) >> d' would translate to
       
   562          |*|  psllw (16 - d), %mmb; pmulh %mmc, %mmb
       
   563          \*/
       
   564         int Cx, Cy, i, j;
       
   565         unsigned int *pix;
       
   566         int a, r, g, b, ax, rx, gx, bx;
       
   567         int xap, yap;
       
   568 
       
   569         for(y = 0; y < dh; y++){
       
   570             Cy = YAP >> 16;
       
   571             yap = YAP & 0xffff;
       
   572 
       
   573             dptr = dest + dx + ((y + dy) * dow);
       
   574             for(x = dxx; x < end; x++){
       
   575                 Cx = XAP >> 16;
       
   576                 xap = XAP & 0xffff;
       
   577 
       
   578                 sptr = ypoints[dyy + y] + xpoints[x];
       
   579                 pix = sptr;
       
   580                 sptr += sow;
       
   581                 rx = R_VAL(pix) * xap;
       
   582                 gx = G_VAL(pix) * xap;
       
   583                 bx = B_VAL(pix) * xap;
       
   584                 ax = A_VAL(pix) * xap;
       
   585 
       
   586                 pix++;
       
   587                 for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   588                     rx += R_VAL(pix) * Cx;
       
   589                     gx += G_VAL(pix) * Cx;
       
   590                     bx += B_VAL(pix) * Cx;
       
   591                     ax += A_VAL(pix) * Cx;
       
   592                     pix++;
       
   593                 }
       
   594                 if(i > 0){
       
   595                     rx += R_VAL(pix) * i;
       
   596                     gx += G_VAL(pix) * i;
       
   597                     bx += B_VAL(pix) * i;
       
   598                     ax += A_VAL(pix) * i;
       
   599                 }
       
   600 
       
   601                 r = (rx >> 5) * yap;
       
   602                 g = (gx >> 5) * yap;
       
   603                 b = (bx >> 5) * yap;
       
   604                 a = (ax >> 5) * yap;
       
   605 
       
   606                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   607                     pix = sptr;
       
   608                     sptr += sow;
       
   609                     rx = R_VAL(pix) * xap;
       
   610                     gx = G_VAL(pix) * xap;
       
   611                     bx = B_VAL(pix) * xap;
       
   612                     ax = A_VAL(pix) * xap;
       
   613                     pix++;
       
   614                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   615                         rx += R_VAL(pix) * Cx;
       
   616                         gx += G_VAL(pix) * Cx;
       
   617                         bx += B_VAL(pix) * Cx;
       
   618                         ax += A_VAL(pix) * Cx;
       
   619                         pix++;
       
   620                     }
       
   621                     if(i > 0){
       
   622                         rx += R_VAL(pix) * i;
       
   623                         gx += G_VAL(pix) * i;
       
   624                         bx += B_VAL(pix) * i;
       
   625                         ax += A_VAL(pix) * i;
       
   626                     }
       
   627 
       
   628                     r += (rx >> 5) * Cy;
       
   629                     g += (gx >> 5) * Cy;
       
   630                     b += (bx >> 5) * Cy;
       
   631                     a += (ax >> 5) * Cy;
       
   632                 }
       
   633                 if(j > 0){
       
   634                     pix = sptr;
       
   635                     sptr += sow;
       
   636                     rx = R_VAL(pix) * xap;
       
   637                     gx = G_VAL(pix) * xap;
       
   638                     bx = B_VAL(pix) * xap;
       
   639                     ax = A_VAL(pix) * xap;
       
   640                     pix++;
       
   641                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   642                         rx += R_VAL(pix) * Cx;
       
   643                         gx += G_VAL(pix) * Cx;
       
   644                         bx += B_VAL(pix) * Cx;
       
   645                         ax += A_VAL(pix) * Cx;
       
   646                         pix++;
       
   647                     }
       
   648                     if(i > 0){
       
   649                         rx += R_VAL(pix) * i;
       
   650                         gx += G_VAL(pix) * i;
       
   651                         bx += B_VAL(pix) * i;
       
   652                         ax += A_VAL(pix) * i;
       
   653                     }
       
   654 
       
   655                     r += (rx >> 5) * j;
       
   656                     g += (gx >> 5) * j;
       
   657                     b += (bx >> 5) * j;
       
   658                     a += (ax >> 5) * j;
       
   659                 }
       
   660 
       
   661                 *dptr = qRgba(r >> 23, g >> 23, b >> 23, a >> 23);
       
   662                 dptr++;
       
   663             }
       
   664         }
       
   665     }
       
   666 }
       
   667 
       
   668 /* scale by area sampling - IGNORE the ALPHA byte*/
       
   669 static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
       
   670                                 int dxx, int dyy, int dx, int dy, int dw,
       
   671                                 int dh, int dow, int sow)
       
   672 {
       
   673     unsigned int *sptr, *dptr;
       
   674     int x, y, end;
       
   675     unsigned int **ypoints = isi->ypoints;
       
   676     int *xpoints = isi->xpoints;
       
   677     int *xapoints = isi->xapoints;
       
   678     int *yapoints = isi->yapoints;
       
   679 
       
   680     end = dxx + dw;
       
   681     /* scaling up both ways */
       
   682     if(isi->xup_yup == 3){
       
   683         /* go through every scanline in the output buffer */
       
   684         for(y = 0; y < dh; y++){
       
   685             /* calculate the source line we'll scan from */
       
   686             dptr = dest + dx + ((y + dy) * dow);
       
   687             sptr = ypoints[dyy + y];
       
   688             if(YAP > 0){
       
   689                 for(x = dxx; x < end; x++){
       
   690                     int r = 0, g = 0, b = 0;
       
   691                     int rr = 0, gg = 0, bb = 0;
       
   692                     unsigned int *pix;
       
   693 
       
   694                     if(XAP > 0){
       
   695                         pix = ypoints[dyy + y] + xpoints[x];
       
   696                         r = R_VAL(pix) * INV_XAP;
       
   697                         g = G_VAL(pix) * INV_XAP;
       
   698                         b = B_VAL(pix) * INV_XAP;
       
   699                         pix++;
       
   700                         r += R_VAL(pix) * XAP;
       
   701                         g += G_VAL(pix) * XAP;
       
   702                         b += B_VAL(pix) * XAP;
       
   703                         pix += sow;
       
   704                         rr = R_VAL(pix) * XAP;
       
   705                         gg = G_VAL(pix) * XAP;
       
   706                         bb = B_VAL(pix) * XAP;
       
   707                         pix --;
       
   708                         rr += R_VAL(pix) * INV_XAP;
       
   709                         gg += G_VAL(pix) * INV_XAP;
       
   710                         bb += B_VAL(pix) * INV_XAP;
       
   711                         r = ((rr * YAP) + (r * INV_YAP)) >> 16;
       
   712                         g = ((gg * YAP) + (g * INV_YAP)) >> 16;
       
   713                         b = ((bb * YAP) + (b * INV_YAP)) >> 16;
       
   714                         *dptr++ = qRgba(r, g, b, 0xff);
       
   715                     }
       
   716                     else{
       
   717                         pix = ypoints[dyy + y] + xpoints[x];
       
   718                         r = R_VAL(pix) * INV_YAP;
       
   719                         g = G_VAL(pix) * INV_YAP;
       
   720                         b = B_VAL(pix) * INV_YAP;
       
   721                         pix += sow;
       
   722                         r += R_VAL(pix) * YAP;
       
   723                         g += G_VAL(pix) * YAP;
       
   724                         b += B_VAL(pix) * YAP;
       
   725                         r >>= 8;
       
   726                         g >>= 8;
       
   727                         b >>= 8;
       
   728                         *dptr++ = qRgba(r, g, b, 0xff);
       
   729                     }
       
   730                 }
       
   731             }
       
   732             else{
       
   733                 for(x = dxx; x < end; x++){
       
   734                     int r = 0, g = 0, b = 0;
       
   735                     unsigned int *pix;
       
   736 
       
   737                     if(XAP > 0){
       
   738                         pix = ypoints[dyy + y] + xpoints[x];
       
   739                         r = R_VAL(pix) * INV_XAP;
       
   740                         g = G_VAL(pix) * INV_XAP;
       
   741                         b = B_VAL(pix) * INV_XAP;
       
   742                         pix++;
       
   743                         r += R_VAL(pix) * XAP;
       
   744                         g += G_VAL(pix) * XAP;
       
   745                         b += B_VAL(pix) * XAP;
       
   746                         r >>= 8;
       
   747                         g >>= 8;
       
   748                         b >>= 8;
       
   749                         *dptr++ = qRgba(r, g, b, 0xff);
       
   750                     }
       
   751                     else
       
   752                         *dptr++ = sptr[xpoints[x] ];
       
   753                 }
       
   754             }
       
   755         }
       
   756     }
       
   757     /* if we're scaling down vertically */
       
   758     else if(isi->xup_yup == 1){
       
   759         /*\ 'Correct' version, with math units prepared for MMXification \*/
       
   760         int Cy, j;
       
   761         unsigned int *pix;
       
   762         int r, g, b, rr, gg, bb;
       
   763         int yap;
       
   764 
       
   765         /* go through every scanline in the output buffer */
       
   766         for(y = 0; y < dh; y++){
       
   767             Cy = YAP >> 16;
       
   768             yap = YAP & 0xffff;
       
   769 
       
   770             dptr = dest + dx + ((y + dy) * dow);
       
   771             for(x = dxx; x < end; x++){
       
   772                 pix = ypoints[dyy + y] + xpoints[x];
       
   773                 r = R_VAL(pix) * yap;
       
   774                 g = G_VAL(pix) * yap;
       
   775                 b = B_VAL(pix) * yap;
       
   776                 pix += sow;
       
   777                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   778                     r += R_VAL(pix) * Cy;
       
   779                     g += G_VAL(pix) * Cy;
       
   780                     b += B_VAL(pix) * Cy;
       
   781                     pix += sow;
       
   782                 }
       
   783                 if(j > 0){
       
   784                     r += R_VAL(pix) * j;
       
   785                     g += G_VAL(pix) * j;
       
   786                     b += B_VAL(pix) * j;
       
   787                 }
       
   788                 if(XAP > 0){
       
   789                     pix = ypoints[dyy + y] + xpoints[x] + 1;
       
   790                     rr = R_VAL(pix) * yap;
       
   791                     gg = G_VAL(pix) * yap;
       
   792                     bb = B_VAL(pix) * yap;
       
   793                     pix += sow;
       
   794                     for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   795                         rr += R_VAL(pix) * Cy;
       
   796                         gg += G_VAL(pix) * Cy;
       
   797                         bb += B_VAL(pix) * Cy;
       
   798                         pix += sow;
       
   799                     }
       
   800                     if(j > 0){
       
   801                         rr += R_VAL(pix) * j;
       
   802                         gg += G_VAL(pix) * j;
       
   803                         bb += B_VAL(pix) * j;
       
   804                     }
       
   805                     r = r * INV_XAP;
       
   806                     g = g * INV_XAP;
       
   807                     b = b * INV_XAP;
       
   808                     r = (r + ((rr * XAP))) >> 12;
       
   809                     g = (g + ((gg * XAP))) >> 12;
       
   810                     b = (b + ((bb * XAP))) >> 12;
       
   811                 }
       
   812                 else{
       
   813                     r >>= 4;
       
   814                     g >>= 4;
       
   815                     b >>= 4;
       
   816                 }
       
   817                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
       
   818                 dptr++;
       
   819             }
       
   820         }
       
   821     }
       
   822     /* if we're scaling down horizontally */
       
   823     else if(isi->xup_yup == 2){
       
   824         /*\ 'Correct' version, with math units prepared for MMXification \*/
       
   825         int Cx, j;
       
   826         unsigned int *pix;
       
   827         int r, g, b, rr, gg, bb;
       
   828         int xap;
       
   829 
       
   830         /* go through every scanline in the output buffer */
       
   831         for(y = 0; y < dh; y++){
       
   832             dptr = dest + dx + ((y + dy) * dow);
       
   833             for(x = dxx; x < end; x++){
       
   834                 Cx = XAP >> 16;
       
   835                 xap = XAP & 0xffff;
       
   836 
       
   837                 pix = ypoints[dyy + y] + xpoints[x];
       
   838                 r = R_VAL(pix) * xap;
       
   839                 g = G_VAL(pix) * xap;
       
   840                 b = B_VAL(pix) * xap;
       
   841                 pix++;
       
   842                 for(j = (1 << 14) - xap; j > Cx; j -= Cx){
       
   843                     r += R_VAL(pix) * Cx;
       
   844                     g += G_VAL(pix) * Cx;
       
   845                     b += B_VAL(pix) * Cx;
       
   846                     pix++;
       
   847                 }
       
   848                 if(j > 0){
       
   849                     r += R_VAL(pix) * j;
       
   850                     g += G_VAL(pix) * j;
       
   851                     b += B_VAL(pix) * j;
       
   852                 }
       
   853                 if(YAP > 0){
       
   854                     pix = ypoints[dyy + y] + xpoints[x] + sow;
       
   855                     rr = R_VAL(pix) * xap;
       
   856                     gg = G_VAL(pix) * xap;
       
   857                     bb = B_VAL(pix) * xap;
       
   858                     pix++;
       
   859                     for(j = (1 << 14) - xap; j > Cx; j -= Cx){
       
   860                         rr += R_VAL(pix) * Cx;
       
   861                         gg += G_VAL(pix) * Cx;
       
   862                         bb += B_VAL(pix) * Cx;
       
   863                         pix++;
       
   864                     }
       
   865                     if(j > 0){
       
   866                         rr += R_VAL(pix) * j;
       
   867                         gg += G_VAL(pix) * j;
       
   868                         bb += B_VAL(pix) * j;
       
   869                     }
       
   870                     r = r * INV_YAP;
       
   871                     g = g * INV_YAP;
       
   872                     b = b * INV_YAP;
       
   873                     r = (r + ((rr * YAP))) >> 12;
       
   874                     g = (g + ((gg * YAP))) >> 12;
       
   875                     b = (b + ((bb * YAP))) >> 12;
       
   876                 }
       
   877                 else{
       
   878                     r >>= 4;
       
   879                     g >>= 4;
       
   880                     b >>= 4;
       
   881                 }
       
   882                 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
       
   883                 dptr++;
       
   884             }
       
   885         }
       
   886     }
       
   887     /* fully optimized (i think) - onyl change of algorithm can help */
       
   888     /* if we're scaling down horizontally & vertically */
       
   889     else{
       
   890         /*\ 'Correct' version, with math units prepared for MMXification \*/
       
   891         int Cx, Cy, i, j;
       
   892         unsigned int *pix;
       
   893         int r, g, b, rx, gx, bx;
       
   894         int xap, yap;
       
   895 
       
   896         for(y = 0; y < dh; y++){
       
   897             Cy = YAP >> 16;
       
   898             yap = YAP & 0xffff;
       
   899 
       
   900             dptr = dest + dx + ((y + dy) * dow);
       
   901             for(x = dxx; x < end; x++){
       
   902                 Cx = XAP >> 16;
       
   903                 xap = XAP & 0xffff;
       
   904 
       
   905                 sptr = ypoints[dyy + y] + xpoints[x];
       
   906                 pix = sptr;
       
   907                 sptr += sow;
       
   908                 rx = R_VAL(pix) * xap;
       
   909                 gx = G_VAL(pix) * xap;
       
   910                 bx = B_VAL(pix) * xap;
       
   911                 pix++;
       
   912                 for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   913                     rx += R_VAL(pix) * Cx;
       
   914                     gx += G_VAL(pix) * Cx;
       
   915                     bx += B_VAL(pix) * Cx;
       
   916                     pix++;
       
   917                 }
       
   918                 if(i > 0){
       
   919                     rx += R_VAL(pix) * i;
       
   920                     gx += G_VAL(pix) * i;
       
   921                     bx += B_VAL(pix) * i;
       
   922                 }
       
   923 
       
   924                 r = (rx >> 5) * yap;
       
   925                 g = (gx >> 5) * yap;
       
   926                 b = (bx >> 5) * yap;
       
   927 
       
   928                 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
       
   929                     pix = sptr;
       
   930                     sptr += sow;
       
   931                     rx = R_VAL(pix) * xap;
       
   932                     gx = G_VAL(pix) * xap;
       
   933                     bx = B_VAL(pix) * xap;
       
   934                     pix++;
       
   935                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   936                         rx += R_VAL(pix) * Cx;
       
   937                         gx += G_VAL(pix) * Cx;
       
   938                         bx += B_VAL(pix) * Cx;
       
   939                         pix++;
       
   940                     }
       
   941                     if(i > 0){
       
   942                         rx += R_VAL(pix) * i;
       
   943                         gx += G_VAL(pix) * i;
       
   944                         bx += B_VAL(pix) * i;
       
   945                     }
       
   946 
       
   947                     r += (rx >> 5) * Cy;
       
   948                     g += (gx >> 5) * Cy;
       
   949                     b += (bx >> 5) * Cy;
       
   950                 }
       
   951                 if(j > 0){
       
   952                     pix = sptr;
       
   953                     sptr += sow;
       
   954                     rx = R_VAL(pix) * xap;
       
   955                     gx = G_VAL(pix) * xap;
       
   956                     bx = B_VAL(pix) * xap;
       
   957                     pix++;
       
   958                     for(i = (1 << 14) - xap; i > Cx; i -= Cx){
       
   959                         rx += R_VAL(pix) * Cx;
       
   960                         gx += G_VAL(pix) * Cx;
       
   961                         bx += B_VAL(pix) * Cx;
       
   962                         pix++;
       
   963                     }
       
   964                     if(i > 0){
       
   965                         rx += R_VAL(pix) * i;
       
   966                         gx += G_VAL(pix) * i;
       
   967                         bx += B_VAL(pix) * i;
       
   968                     }
       
   969 
       
   970                     r += (rx >> 5) * j;
       
   971                     g += (gx >> 5) * j;
       
   972                     b += (bx >> 5) * j;
       
   973                 }
       
   974 
       
   975                 *dptr = qRgb(r >> 23, g >> 23, b >> 23);
       
   976                 dptr++;
       
   977             }
       
   978         }
       
   979     }
       
   980 }
       
   981 
       
   982 #if 0
       
   983 static void qt_qimageScaleAARGBASetup(QImageScaleInfo *isi, unsigned int *dest,
       
   984                                       int dxx, int dyy, int dx, int dy, int dw,
       
   985                                       int dh, int dow, int sow)
       
   986 {
       
   987     qInitDrawhelperAsm();
       
   988     qt_qimageScaleAARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
       
   989 }
       
   990 
       
   991 static void qt_qimageScaleAARGBSetup(QImageScaleInfo *isi, unsigned int *dest,
       
   992                                  int dxx, int dyy, int dx, int dy, int dw,
       
   993                                  int dh, int dow, int sow)
       
   994 {
       
   995     qInitDrawhelperAsm();
       
   996     qt_qimageScaleAARGB(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
       
   997 }
       
   998 #endif
       
   999 
       
  1000 QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
       
  1001 {
       
  1002     QImage buffer;
       
  1003     if (src.isNull() || dw <= 0 || dh <= 0)
       
  1004         return buffer;
       
  1005 
       
  1006     int w = src.width();
       
  1007     int h = src.height();
       
  1008     QImageScaleInfo *scaleinfo =
       
  1009         qimageCalcScaleInfo(src, w, h, dw, dh, true);
       
  1010     if (!scaleinfo)
       
  1011         return buffer;
       
  1012 
       
  1013     buffer = QImage(dw, dh, src.format());
       
  1014     if (buffer.isNull()) {
       
  1015         qWarning("QImage: out of memory, returning null");
       
  1016         qimageFreeScaleInfo(scaleinfo);
       
  1017         return QImage();
       
  1018     }
       
  1019 
       
  1020     if (src.format() == QImage::Format_ARGB32_Premultiplied)
       
  1021         qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
       
  1022                            0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
       
  1023     else
       
  1024         qt_qimageScaleRgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
       
  1025                           0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
       
  1026 
       
  1027     qimageFreeScaleInfo(scaleinfo);
       
  1028     return buffer;
       
  1029 }
       
  1030 
       
  1031 QT_END_NAMESPACE