1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
41 #include <private/qimagescale_p.h>
42 #include <private/qdrawhelper_p.h>
49 namespace QImageScale {
50 struct QImageScaleInfo;
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);
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);
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);
65 qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
66 qt_qimageScaleFunc qt_qimageScaleRgb = qt_qimageScaleAARGB;
70 * Copyright (C) 2004, 2005 Daniel M. Duley
72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions
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.
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.
97 * This is the normal smoothscale method, based on Imlib2's smoothscale.
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.
106 * Changes include formatting, namespaces and other C++'ings, removal of old
107 * #ifdef'ed code, and removal of unneeded border calculation code.
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.
115 namespace QImageScale {
116 struct QImageScaleInfo {
118 unsigned int **ypoints;
119 int *xapoints, *yapoints;
123 unsigned int** qimageCalcYPoints(unsigned int *src, int sw, int sh,
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);
132 using namespace QImageScale;
135 // Code ported from Imlib...
138 // FIXME: replace with qRed, etc... These work on pointers to pixels, not
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))
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])
150 unsigned int** QImageScale::qimageCalcYPoints(unsigned int *src,
151 int sw, int sh, int dh)
155 int val, inc, rv = 0;
161 p = new unsigned int* [dh+1];
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;
171 for(i = dh / 2; --i >= 0; ){
172 unsigned int *tmp = p[i];
173 p[i] = p[dh - i - 1];
180 int* QImageScale::qimageCalcXPoints(int sw, int dw)
183 int val, inc, rv = 0;
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);
200 for(i = dw / 2; --i >= 0; ){
202 p[i] = p[dw - i - 1];
209 int* QImageScale::qimageCalcApoints(int s, int d, int up)
211 int *p, i, j = 0, rv = 0;
223 val = 0x8000 * s / d - 0x8000;
225 for(i = 0; i < d; i++){
229 else if (pos >= (s - 1))
232 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
238 int val, inc, ap, Cp;
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);
251 for(i = d / 2; --i >= 0; ){
260 QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
263 delete[] isi->xpoints;
264 delete[] isi->ypoints;
265 delete[] isi->xapoints;
266 delete[] isi->yapoints;
272 QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
274 int dw, int dh, char aa)
276 QImageScaleInfo *isi;
279 scw = dw * qlonglong(img.width()) / sw;
280 sch = dh * qlonglong(img.height()) / sh;
282 isi = new QImageScaleInfo;
285 memset(isi, 0, sizeof(QImageScaleInfo));
287 isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
289 isi->xpoints = qimageCalcXPoints(img.width(), scw);
291 return(qimageFreeScaleInfo(isi));
292 isi->ypoints = qimageCalcYPoints((unsigned int *)img.scanLine(0),
293 img.bytesPerLine() / 4, img.height(), sch);
295 return(qimageFreeScaleInfo(isi));
297 isi->xapoints = qimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
299 return(qimageFreeScaleInfo(isi));
300 isi->yapoints = qimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
302 return(qimageFreeScaleInfo(isi));
307 /* FIXME: NEED to optimize ScaleAARGBA - currently its "ok" but needs work*/
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)
314 unsigned int *sptr, *dptr;
316 unsigned int **ypoints = isi->ypoints;
317 int *xpoints = isi->xpoints;
318 int *xapoints = isi->xapoints;
319 int *yapoints = isi->yapoints;
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];
330 for(x = dxx; x < end; x++){
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;
342 r += R_VAL(pix) * XAP;
343 g += G_VAL(pix) * XAP;
344 b += B_VAL(pix) * XAP;
345 a += A_VAL(pix) * XAP;
347 rr = R_VAL(pix) * XAP;
348 gg = G_VAL(pix) * XAP;
349 bb = B_VAL(pix) * XAP;
350 aa = A_VAL(pix) * XAP;
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);
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;
369 r += R_VAL(pix) * YAP;
370 g += G_VAL(pix) * YAP;
371 b += B_VAL(pix) * YAP;
372 a += A_VAL(pix) * YAP;
377 *dptr++ = qRgba(r, g, b, a);
382 for(x = dxx; x < end; x++){
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;
393 r += R_VAL(pix) * XAP;
394 g += G_VAL(pix) * XAP;
395 b += B_VAL(pix) * XAP;
396 a += A_VAL(pix) * XAP;
401 *dptr++ = qRgba(r, g, b, a);
404 *dptr++ = sptr[xpoints[x] ];
409 /* if we're scaling down vertically */
410 else if(isi->xup_yup == 1){
411 /*\ 'Correct' version, with math units prepared for MMXification \*/
414 int r, g, b, a, rr, gg, bb, aa;
417 /* go through every scanline in the output buffer */
418 for(y = 0; y < dh; y++){
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){
431 r += R_VAL(pix) * Cy;
432 g += G_VAL(pix) * Cy;
433 b += B_VAL(pix) * Cy;
434 a += A_VAL(pix) * Cy;
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){
451 rr += R_VAL(pix) * Cy;
452 gg += G_VAL(pix) * Cy;
453 bb += B_VAL(pix) * Cy;
454 aa += A_VAL(pix) * Cy;
458 rr += R_VAL(pix) * j;
459 gg += G_VAL(pix) * j;
460 bb += B_VAL(pix) * j;
461 aa += A_VAL(pix) * j;
467 r = (r + ((rr * XAP))) >> 12;
468 g = (g + ((gg * XAP))) >> 12;
469 b = (b + ((bb * XAP))) >> 12;
470 a = (a + ((aa * XAP))) >> 12;
478 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
483 /* if we're scaling down horizontally */
484 else if(isi->xup_yup == 2){
485 /*\ 'Correct' version, with math units prepared for MMXification \*/
488 int r, g, b, a, rr, gg, bb, aa;
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++){
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){
505 r += R_VAL(pix) * Cx;
506 g += G_VAL(pix) * Cx;
507 b += B_VAL(pix) * Cx;
508 a += A_VAL(pix) * Cx;
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){
525 rr += R_VAL(pix) * Cx;
526 gg += G_VAL(pix) * Cx;
527 bb += B_VAL(pix) * Cx;
528 aa += A_VAL(pix) * Cx;
532 rr += R_VAL(pix) * j;
533 gg += G_VAL(pix) * j;
534 bb += B_VAL(pix) * j;
535 aa += A_VAL(pix) * j;
541 r = (r + ((rr * YAP))) >> 12;
542 g = (g + ((gg * YAP))) >> 12;
543 b = (b + ((bb * YAP))) >> 12;
544 a = (a + ((aa * YAP))) >> 12;
552 *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
557 /* if we're scaling down horizontally & vertically */
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
566 int a, r, g, b, ax, rx, gx, bx;
569 for(y = 0; y < dh; y++){
573 dptr = dest + dx + ((y + dy) * dow);
574 for(x = dxx; x < end; x++){
578 sptr = ypoints[dyy + y] + xpoints[x];
581 rx = R_VAL(pix) * xap;
582 gx = G_VAL(pix) * xap;
583 bx = B_VAL(pix) * xap;
584 ax = A_VAL(pix) * xap;
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;
595 rx += R_VAL(pix) * i;
596 gx += G_VAL(pix) * i;
597 bx += B_VAL(pix) * i;
598 ax += A_VAL(pix) * i;
606 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
609 rx = R_VAL(pix) * xap;
610 gx = G_VAL(pix) * xap;
611 bx = B_VAL(pix) * xap;
612 ax = A_VAL(pix) * xap;
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;
622 rx += R_VAL(pix) * i;
623 gx += G_VAL(pix) * i;
624 bx += B_VAL(pix) * i;
625 ax += A_VAL(pix) * i;
636 rx = R_VAL(pix) * xap;
637 gx = G_VAL(pix) * xap;
638 bx = B_VAL(pix) * xap;
639 ax = A_VAL(pix) * xap;
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;
649 rx += R_VAL(pix) * i;
650 gx += G_VAL(pix) * i;
651 bx += B_VAL(pix) * i;
652 ax += A_VAL(pix) * i;
661 *dptr = qRgba(r >> 23, g >> 23, b >> 23, a >> 23);
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)
673 unsigned int *sptr, *dptr;
675 unsigned int **ypoints = isi->ypoints;
676 int *xpoints = isi->xpoints;
677 int *xapoints = isi->xapoints;
678 int *yapoints = isi->yapoints;
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];
689 for(x = dxx; x < end; x++){
690 int r = 0, g = 0, b = 0;
691 int rr = 0, gg = 0, bb = 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;
700 r += R_VAL(pix) * XAP;
701 g += G_VAL(pix) * XAP;
702 b += B_VAL(pix) * XAP;
704 rr = R_VAL(pix) * XAP;
705 gg = G_VAL(pix) * XAP;
706 bb = B_VAL(pix) * XAP;
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);
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;
722 r += R_VAL(pix) * YAP;
723 g += G_VAL(pix) * YAP;
724 b += B_VAL(pix) * YAP;
728 *dptr++ = qRgba(r, g, b, 0xff);
733 for(x = dxx; x < end; x++){
734 int r = 0, g = 0, b = 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;
743 r += R_VAL(pix) * XAP;
744 g += G_VAL(pix) * XAP;
745 b += B_VAL(pix) * XAP;
749 *dptr++ = qRgba(r, g, b, 0xff);
752 *dptr++ = sptr[xpoints[x] ];
757 /* if we're scaling down vertically */
758 else if(isi->xup_yup == 1){
759 /*\ 'Correct' version, with math units prepared for MMXification \*/
762 int r, g, b, rr, gg, bb;
765 /* go through every scanline in the output buffer */
766 for(y = 0; y < dh; y++){
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;
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;
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;
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;
801 rr += R_VAL(pix) * j;
802 gg += G_VAL(pix) * j;
803 bb += B_VAL(pix) * j;
808 r = (r + ((rr * XAP))) >> 12;
809 g = (g + ((gg * XAP))) >> 12;
810 b = (b + ((bb * XAP))) >> 12;
817 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
822 /* if we're scaling down horizontally */
823 else if(isi->xup_yup == 2){
824 /*\ 'Correct' version, with math units prepared for MMXification \*/
827 int r, g, b, rr, gg, bb;
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++){
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;
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;
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;
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;
866 rr += R_VAL(pix) * j;
867 gg += G_VAL(pix) * j;
868 bb += B_VAL(pix) * j;
873 r = (r + ((rr * YAP))) >> 12;
874 g = (g + ((gg * YAP))) >> 12;
875 b = (b + ((bb * YAP))) >> 12;
882 *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
887 /* fully optimized (i think) - onyl change of algorithm can help */
888 /* if we're scaling down horizontally & vertically */
890 /*\ 'Correct' version, with math units prepared for MMXification \*/
893 int r, g, b, rx, gx, bx;
896 for(y = 0; y < dh; y++){
900 dptr = dest + dx + ((y + dy) * dow);
901 for(x = dxx; x < end; x++){
905 sptr = ypoints[dyy + y] + xpoints[x];
908 rx = R_VAL(pix) * xap;
909 gx = G_VAL(pix) * xap;
910 bx = B_VAL(pix) * xap;
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;
919 rx += R_VAL(pix) * i;
920 gx += G_VAL(pix) * i;
921 bx += B_VAL(pix) * i;
928 for(j = (1 << 14) - yap; j > Cy; j -= Cy){
931 rx = R_VAL(pix) * xap;
932 gx = G_VAL(pix) * xap;
933 bx = B_VAL(pix) * xap;
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;
942 rx += R_VAL(pix) * i;
943 gx += G_VAL(pix) * i;
944 bx += B_VAL(pix) * i;
954 rx = R_VAL(pix) * xap;
955 gx = G_VAL(pix) * xap;
956 bx = B_VAL(pix) * xap;
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;
965 rx += R_VAL(pix) * i;
966 gx += G_VAL(pix) * i;
967 bx += B_VAL(pix) * i;
975 *dptr = qRgb(r >> 23, g >> 23, b >> 23);
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)
987 qInitDrawhelperAsm();
988 qt_qimageScaleAARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
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)
995 qInitDrawhelperAsm();
996 qt_qimageScaleAARGB(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
1000 QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
1003 if (src.isNull() || dw <= 0 || dh <= 0)
1006 int w = src.width();
1007 int h = src.height();
1008 QImageScaleInfo *scaleinfo =
1009 qimageCalcScaleInfo(src, w, h, dw, dh, true);
1013 buffer = QImage(dw, dh, src.format());
1014 if (buffer.isNull()) {
1015 qWarning("QImage: out of memory, returning null");
1016 qimageFreeScaleInfo(scaleinfo);
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);
1024 qt_qimageScaleRgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
1025 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
1027 qimageFreeScaleInfo(scaleinfo);