Qt 4.8
qimagescale.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 
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 
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 {
117  int *xpoints;
118  unsigned int **ypoints;
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);
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 
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 
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 */
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 {
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 {
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 
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 
QImageScaleInfo * qimageFreeScaleInfo(QImageScaleInfo *isi)
double d
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define B_VAL(p)
#define A_VAL(p)
qt_qimageScaleFunc qt_qimageScaleArgb
Definition: qimagescale.cpp:65
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
void qInitDrawhelperAsm()
#define INV_YAP
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
#define G_VAL(p)
long ASN1_INTEGER_get ASN1_INTEGER * a
qt_qimageScaleFunc qt_qimageScaleRgb
Definition: qimagescale.cpp:66
int * qimageCalcXPoints(int sw, int dw)
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
#define INV_XAP
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
Definition: qrgb.h:72
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
#define YAP
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
int * qimageCalcApoints(int s, int d, int up)
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)
Definition: qimagescale.cpp:53
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
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)
unsigned int ** qimageCalcYPoints(unsigned int *src, int sw, int sh, int dh)
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
QImageScaleInfo * qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa)
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)
static const KeyPair *const end
qint64 qlonglong
Definition: qglobal.h:951
#define XAP
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
#define R_VAL(p)