📄 qimagescale.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <private/qimagescale_p.h>#include <private/qdrawhelper_p.h>#include "qimage.h"#include "qcolor.h"namespace QImageScale { struct QImageScaleInfo;}typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest, int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow);static void qt_qimageScaleAARGB(QImageScale::QImageScaleInfo *isi, unsigned int *dest, int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow);static void qt_qimageScaleAARGBA(QImageScale::QImageScaleInfo *isi, unsigned int *dest, int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow);qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;qt_qimageScaleFunc qt_qimageScaleRgb = qt_qimageScaleAARGB;/* * 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. */namespace QImageScale { struct QImageScaleInfo { int *xpoints; unsigned int **ypoints; int *xapoints, *yapoints; int xup_yup; }; unsigned int** qimageCalcYPoints(unsigned int *src, int sw, int sh, int dh); int* qimageCalcXPoints(int sw, int dw); int* qimageCalcApoints(int s, int d, int up); QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi); QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa);}using namespace QImageScale;//// Code ported from Imlib...//// FIXME: replace with qRed, etc... These work on pointers to pixels, not// pixel values#define A_VAL(p) (qAlpha(*p))#define R_VAL(p) (qRed(*p))#define G_VAL(p) (qGreen(*p))#define B_VAL(p) (qBlue(*p))#define INV_XAP (256 - xapoints[x])#define XAP (xapoints[x])#define INV_YAP (256 - yapoints[dyy + y])#define YAP (yapoints[dyy + y])unsigned int** QImageScale::qimageCalcYPoints(unsigned int *src, int sw, int sh, int dh){ unsigned int **p; int i, j = 0; int val, inc, rv = 0; if(dh < 0){ dh = -dh; rv = 1; } p = new unsigned int* [dh+1]; int up = abs(dh) >= sh; val = up ? 0x8000 * sh / dh - 0x8000 : 0; inc = (sh << 16) / dh; for(i = 0; i < dh; i++){ p[j++] = src + qMax(0, val >> 16) * sw; val += inc; } if(rv){ for(i = dh / 2; --i >= 0; ){ unsigned int *tmp = p[i]; p[i] = p[dh - i - 1]; p[dh - i - 1] = tmp; } } return(p);}int* QImageScale::qimageCalcXPoints(int sw, int dw){ int *p, i, j = 0; int val, inc, rv = 0; if(dw < 0){ dw = -dw; rv = 1; } p = new int[dw+1]; int up = abs(dw) >= sw; val = up ? 0x8000 * sw / dw - 0x8000 : 0; inc = (sw << 16) / dw; for(i = 0; i < dw; i++){ p[j++] = qMax(0, val >> 16); val += inc; } if(rv){ for(i = dw / 2; --i >= 0; ){ int tmp = p[i]; p[i] = p[dw - i - 1]; p[dw - i - 1] = tmp; } } return(p);}int* QImageScale::qimageCalcApoints(int s, int d, int up){ int *p, i, j = 0, rv = 0; if(d < 0){ rv = 1; d = -d; } p = new int[d]; /* scaling up */ if(up){ int val, inc; val = 0x8000 * s / d - 0x8000; inc = (s << 16) / d; for(i = 0; i < d; i++){ int pos = val >> 16; if (pos < 0) p[j++] = 0; else if (pos >= (s - 1)) p[j++] = 0; else p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00); val += inc; } } /* scaling down */ else{ int val, inc, ap, Cp; val = 0; inc = (s << 16) / d; Cp = ((d << 14) / s) + 1; for(i = 0; i < d; i++){ ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; p[j] = ap | (Cp << 16); j++; val += inc; } } if(rv){ int tmp; for(i = d / 2; --i >= 0; ){ tmp = p[i]; p[i] = p[d - i - 1]; p[d - i - 1] = tmp; } } return(p);}QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi){ if(isi){ delete[] isi->xpoints; delete[] isi->ypoints; delete[] isi->xapoints; delete[] isi->yapoints; delete isi; } return(NULL);}QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa){ QImageScaleInfo *isi; int scw, sch; scw = dw * img.width() / sw; sch = dh * img.height() / sh; isi = new QImageScaleInfo; if(!isi) return(NULL); memset(isi, 0, sizeof(QImageScaleInfo)); isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1); isi->xpoints = qimageCalcXPoints(img.width(), scw); if(!isi->xpoints) return(qimageFreeScaleInfo(isi)); isi->ypoints = qimageCalcYPoints((unsigned int *)img.scanLine(0), img.width(), img.height(), sch); if (!isi->ypoints) return(qimageFreeScaleInfo(isi)); if(aa){ isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1); if(!isi->xapoints) return(qimageFreeScaleInfo(isi)); isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2); if(!isi->yapoints) return(qimageFreeScaleInfo(isi)); } return(isi);}/* FIXME: NEED to optimise ScaleAARGBA - currently its "ok" but needs work*//* scale by area sampling */static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, int dxx, int dyy, int dx, int dy, int dw, int dh, int dow, int sow){ unsigned int *sptr, *dptr; int x, y, end; unsigned int **ypoints = isi->ypoints; int *xpoints = isi->xpoints; int *xapoints = isi->xapoints; int *yapoints = isi->yapoints; end = dxx + dw; /* scaling up both ways */ if(isi->xup_yup == 3){ /* go through every scanline in the output buffer */ for(y = 0; y < dh; y++){ /* calculate the source line we'll scan from */ dptr = dest + dx + ((y + dy) * dow); sptr = ypoints[dyy + y]; if(YAP > 0){ for(x = dxx; x < end; x++){ int r, g, b, a; int rr, gg, bb, aa; unsigned int *pix; if(XAP > 0){ pix = ypoints[dyy + y] + xpoints[x]; r = R_VAL(pix) * INV_XAP; g = G_VAL(pix) * INV_XAP; b = B_VAL(pix) * INV_XAP; a = A_VAL(pix) * INV_XAP; pix++; r += R_VAL(pix) * XAP; g += G_VAL(pix) * XAP; b += B_VAL(pix) * XAP; a += A_VAL(pix) * XAP; pix += sow; rr = R_VAL(pix) * XAP; gg = G_VAL(pix) * XAP; bb = B_VAL(pix) * XAP; aa = A_VAL(pix) * XAP; pix--; rr += R_VAL(pix) * INV_XAP; gg += G_VAL(pix) * INV_XAP; bb += B_VAL(pix) * INV_XAP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -