source: trunk/src/gui/painting/qimagescale.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 35.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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
47QT_BEGIN_NAMESPACE
48
49namespace QImageScale {
50 struct QImageScaleInfo;
51}
52
53typedef 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
57static 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
61static 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
65qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
66qt_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
115namespace 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
132using 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
150unsigned 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
180int* 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
209int* 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
260QImageScaleInfo* 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
272QImageScaleInfo* 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 optimize ScaleAARGBA - currently its "ok" but needs work*/
308
309/* scale by area sampling */
310static 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*/
669static 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
983static 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
991static 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
1000QImage 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
1031QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.