• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE Support
  • Sitemap
  • Contact Us
 

qimageblitz

scale.cpp

Go to the documentation of this file.
00001 #include <config-processor.h>
00002 #include <config-externalasm.h>
00003 #include "blitzcpu.h"
00004 #include "qimageblitz.h"
00005 #include <string.h>
00006 #include <stdlib.h>
00007 
00008 /*
00009  * Copyright (C) 2004, 2005, 2007 Daniel M. Duley <daniel.duley@verizon.net>
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright
00016  *    notice, this list of conditions and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in the
00019  *    documentation and/or other materials provided with the distribution.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00022  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00023  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00024  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00026  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00027  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00028  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00030  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  *
00032  */
00033 
00034 /* OTHER CREDITS:
00035  *
00036  * This is the normal smoothscale method, based on Imlib2's smoothscale.
00037  *
00038  * Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
00039  * optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
00040  * C algorithm and it ran at about the same speed as my MMX optimized one...
00041  * Finally I ported Imlib's MMX version and it ran in less than half the
00042  * time as my MMX algorithm, (taking only a quarter of the time Qt did).
00043  * After further optimization it seems to run at around 1/6th.
00044  *
00045  * Changes include formatting, namespaces and other C++'ings, removal of old
00046  * #ifdef'ed code, and removal of unneeded border calculation code.
00047  *
00048  * Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
00049  * is by Willem Monsuwe <willem@stack.nl>. All other modifications are
00050  * (C) Daniel M. Duley.
00051  */
00052 
00053 #if defined(__i386__) && ( defined(__GNUC__) || defined(__INTEL_COMPILER) )
00054 #  if defined(HAVE_MMX) && defined(HAVE_EXTERNAL_ASM)
00055 #    define USE_MMX_INLINE_ASM
00056 #  endif
00057 #endif
00058 
00059 namespace QImageScale{
00060     typedef struct __qimage_scale_info
00061     {
00062         int *xpoints;
00063         unsigned int **ypoints;
00064         int *xapoints, *yapoints;
00065         int xup_yup;
00066     } QImageScaleInfo;
00067 
00068     unsigned int** qimageCalcYPoints(unsigned int *src, int sw, int sh,
00069                                      int dh);
00070     int* qimageCalcXPoints(int sw, int dw);
00071     int* qimageCalcApoints(int s, int d, int up);
00072     QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
00073     QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
00074                                          int dw, int dh, char aa);
00075 }
00076 
00077 #ifdef USE_MMX_INLINE_ASM
00078 extern "C" {
00079     void __qimageScale_mmx_AARGBA(QImageScale::QImageScaleInfo *isi,
00080                                   unsigned int *dest, int dxx, int dyy,
00081                                   int dx, int dy, int dw, int dh,
00082                                   int dow, int sow);
00083 }
00084 #endif
00085 
00086 using namespace QImageScale;
00087 
00088 QImage Blitz::smoothScale(QImage &src, int w, int h,
00089                           Qt::AspectRatioMode aspectRatio)
00090 {
00091     return(smoothScale(src, QSize(w, h), aspectRatio));
00092 }
00093 
00094 QImage Blitz::smoothScale(QImage &src, const QSize &sz,
00095                           Qt::AspectRatioMode aspectRatio)
00096 {
00097 #ifdef USE_MMX_INLINE_ASM
00098 #ifdef __GNUC__
00099 #warning Using MMX smoothscaling
00100 #endif
00101     if(BlitzCPUInfo::haveExtension(BlitzCPUInfo::MMX)){
00102         QImage buffer;
00103         QSize destSize(src.size());
00104         destSize.scale(sz, aspectRatio);
00105         if(src.isNull() || !destSize.isValid())
00106             return(buffer);
00107         if(src.depth() != 32){
00108             src = src.convertToFormat(src.hasAlphaChannel() ?
00109                                       QImage::Format_ARGB32 :
00110                                       QImage::Format_RGB32);
00111         }
00112         else if(src.format() == QImage::Format_ARGB32_Premultiplied)
00113             src = src.convertToFormat(QImage::Format_ARGB32);
00114 
00115         QImageScaleInfo *scaleinfo =
00116             qimageCalcScaleInfo(src, src.width(), src.height(),
00117                                 destSize.width(), destSize.height(), true);
00118         if(!scaleinfo)
00119             return(buffer);
00120 
00121         buffer = QImage(destSize, src.format());
00122         __qimageScale_mmx_AARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
00123                                  0, 0, destSize.width(), destSize.height(),
00124                                  destSize.width(), src.width());
00125         qimageFreeScaleInfo(scaleinfo);
00126         return(buffer);
00127     }
00128     else
00129 #endif
00130     {
00131         return(src.scaled(sz, aspectRatio, Qt::SmoothTransformation));
00132     }
00133 }
00134 
00135 //
00136 // Code ported from Imlib...
00137 //
00138 
00139 // FIXME: replace with qRed, etc... These work on pointers to pixels, not
00140 // pixel values
00141 #define A_VAL(p) ((unsigned char *)(p))[3]
00142 #define R_VAL(p) ((unsigned char *)(p))[2]
00143 #define G_VAL(p) ((unsigned char *)(p))[1]
00144 #define B_VAL(p) ((unsigned char *)(p))[0]
00145 
00146 #define INV_XAP                   (256 - xapoints[x])
00147 #define XAP                       (xapoints[x])
00148 #define INV_YAP                   (256 - yapoints[dyy + y])
00149 #define YAP                       (yapoints[dyy + y])
00150 
00151 unsigned int** QImageScale::qimageCalcYPoints(unsigned int *src,
00152                                               int sw, int sh, int dh)
00153 {
00154     unsigned int **p;
00155     int i, j = 0;
00156     int val, inc, rv = 0;
00157 
00158     if(dh < 0){
00159         dh = -dh;
00160         rv = 1;
00161     }
00162     p = new unsigned int* [dh+1];
00163 
00164     val = 0;
00165     inc = (sh << 16) / dh;
00166     for(i = 0; i < dh; i++){
00167         p[j++] = src + ((val >> 16) * sw);
00168         val += inc;
00169     }
00170     if(rv){
00171         for(i = dh / 2; --i >= 0; ){
00172             unsigned int *tmp = p[i];
00173             p[i] = p[dh - i - 1];
00174             p[dh - i - 1] = tmp;
00175         }
00176     }
00177     return(p);
00178 }
00179 
00180 int* QImageScale::qimageCalcXPoints(int sw, int dw)
00181 {
00182     int *p, i, j = 0;
00183     int val, inc, rv = 0;
00184 
00185     if(dw < 0){
00186         dw = -dw;
00187         rv = 1;
00188     }
00189     p = new int[dw+1];
00190 
00191     val = 0;
00192     inc = (sw << 16) / dw;
00193     for(i = 0; i < dw; i++){
00194         p[j++] = (val >> 16);
00195         val += inc;
00196     }
00197 
00198     if(rv){
00199         for(i = dw / 2; --i >= 0; ){
00200             int tmp = p[i];
00201             p[i] = p[dw - i - 1];
00202             p[dw - i - 1] = tmp;
00203         }
00204     }
00205    return(p);
00206 }
00207 
00208 int* QImageScale::qimageCalcApoints(int s, int d, int up)
00209 {
00210     int *p, i, j = 0, rv = 0;
00211 
00212     if(d < 0){
00213         rv = 1;
00214         d = -d;
00215     }
00216     p = new int[d];
00217 
00218     /* scaling up */
00219     if(up){
00220         int val, inc;
00221 
00222         val = 0;
00223         inc = (s << 16) / d;
00224         for(i = 0; i < d; i++){
00225             p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
00226             if((val >> 16) >= (s - 1))
00227                 p[j - 1] = 0;
00228             val += inc;
00229         }
00230     }
00231     /* scaling down */
00232     else{
00233         int val, inc, ap, Cp;
00234         val = 0;
00235         inc = (s << 16) / d;
00236         Cp = ((d << 14) / s) + 1;
00237         for(i = 0; i < d; i++){
00238             ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
00239             p[j] = ap | (Cp << 16);
00240             j++;
00241             val += inc;
00242         }
00243     }
00244     if(rv){
00245         int tmp;
00246         for(i = d / 2; --i >= 0; ){
00247             tmp = p[i];
00248             p[i] = p[d - i - 1];
00249             p[d - i - 1] = tmp;
00250         }
00251     }
00252     return(p);
00253 }
00254 
00255 QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
00256 {
00257     if(isi){
00258         delete[] isi->xpoints;
00259         delete[] isi->ypoints;
00260         delete[] isi->xapoints;
00261         delete[] isi->yapoints;
00262         delete isi;
00263     }
00264     return(NULL);
00265 }
00266 
00267 QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
00268                                                   int sw, int sh,
00269                                                   int dw, int dh, char aa)
00270 {
00271     QImageScaleInfo *isi;
00272     int scw, sch;
00273 
00274     scw = dw * img.width() / sw;
00275     sch = dh * img.height() / sh;
00276 
00277     isi = new QImageScaleInfo;
00278     if(!isi)
00279         return(NULL);
00280     memset(isi, 0, sizeof(QImageScaleInfo));
00281 
00282     isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
00283 
00284     isi->xpoints = qimageCalcXPoints(img.width(), scw);
00285     if(!isi->xpoints)
00286         return(qimageFreeScaleInfo(isi));
00287     isi->ypoints = qimageCalcYPoints((unsigned int *)img.scanLine(0),
00288                                      img.width(), img.height(), sch);
00289     if (!isi->ypoints)
00290         return(qimageFreeScaleInfo(isi));
00291     if(aa){
00292         isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
00293         if(!isi->xapoints)
00294             return(qimageFreeScaleInfo(isi));
00295         isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
00296         if(!isi->yapoints)
00297             return(qimageFreeScaleInfo(isi));
00298     }
00299     return(isi);
00300 }
00301 

qimageblitz

Skip menu "qimageblitz"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

KDE Support

Skip menu "KDE Support"
  • akonadi
  • Decibel
  • grantlee
  • kdewin
  • phonon
  •     Backend
  • polkit-qt
  • qca
  • qimageblitz
  • soprano
  • strigi
  •     searchclient
  •     streamanalyzer
  •     streams
Generated for KDE Support by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal