1
// This code is Imlib2 code, additionally modified by Mosfet, and with few small
2
// modifications for Gwenview. The MMX scaling code also belongs to it.
4
// The original license texts follow.
7
* This is the normal smoothscale method, based on Imlib2's smoothscale.
9
* Originally I took the algorithm used in NetPBM and Qt and added MMX/3dnow
10
* optimizations. It ran in about 1/2 the time as Qt. Then I ported Imlib's
11
* C algorithm and it ran at about the same speed as my MMX optimized one...
12
* Finally I ported Imlib's MMX version and it ran in less than half the
13
* time as my MMX algorithm, (taking only a quarter of the time Qt does).
15
* Changes include formatting, namespaces and other C++'ings, removal of old
16
* #ifdef'ed code, and removal of unneeded border calculation code.
18
* Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
19
* is by Willem Monsuwe <willem@stack.nl>. All other modifications are
20
* (C) Daniel M. Duley.
24
Copyright (C) 2004 Daniel M. Duley <dan.duley@verizon.net>
26
Redistribution and use in source and binary forms, with or without
27
modification, are permitted provided that the following conditions
30
1. Redistributions of source code must retain the above copyright
31
notice, this list of conditions and the following disclaimer.
32
2. Redistributions in binary form must reproduce the above copyright
33
notice, this list of conditions and the following disclaimer in the
34
documentation and/or other materials provided with the distribution.
36
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
37
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
40
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
45
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50
Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
52
Permission is hereby granted, free of charge, to any person obtaining a copy
53
of this software and associated documentation files (the "Software"), to
54
deal in the Software without restriction, including without limitation the
55
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
56
sell copies of the Software, and to permit persons to whom the Software is
57
furnished to do so, subject to the following conditions:
59
The above copyright notice and this permission notice shall be included in
60
all copies of the Software and its Copyright notices. In addition publicly
61
documented acknowledgment must be given that this software has been used if no
62
source code of this software is made available publicly. This includes
63
acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
64
documents or any documentation provided with any product containing this
65
software. This License does not apply to any software that links to the
66
libraries provided by this software (statically or dynamically), but only to
67
the software provided.
69
Please see the COPYING.PLAIN for a plain-english explanation of this notice
72
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
75
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
76
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
77
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80
#include <config-workspace.h>
89
namespace MImageScale{
90
typedef struct __mimage_scale_info
93
unsigned int **ypoints;
94
int *xapoints, *yapoints;
98
unsigned int** mimageCalcYPoints(unsigned int *src, int sw, int sh,
100
int* mimageCalcXPoints(int sw, int dw);
101
int* mimageCalcApoints(int s, int d, int up);
102
MImageScaleInfo* mimageFreeScaleInfo(MImageScaleInfo *isi);
103
MImageScaleInfo *mimageCalcScaleInfo(QImage &img, int sw, int sh,
104
int dw, int dh, char aa);
105
void mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
106
int dyy, int dx, int dy, int dw, int dh, int dow);
107
void mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest, int dxx,
108
int dyy, int dx, int dy, int dw, int dh, int dow,
110
void mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest, int dxx,
111
int dyy, int dx, int dy, int dw, int dh, int dow, int
113
QImage smoothScale(const QImage& img, int dw, int dh);
118
void __mimageScale_mmx_AARGBA(MImageScale::MImageScaleInfo *isi,
119
unsigned int *dest, int dxx, int dyy,
120
int dx, int dy, int dw, int dh,
125
using namespace MImageScale;
127
QImage MImageScale::smoothScale(const QImage& image, int dw, int dh)
129
QImage img = image.depth() < 32 ? image.convertDepth( 32 ) : image;
131
int h = img.height();
133
MImageScaleInfo *scaleinfo =
134
mimageCalcScaleInfo(img, w, h, dw, dh, true);
138
QImage buffer(dw, dh, 32);
139
buffer.setAlphaBuffer(img.hasAlphaBuffer());
142
//#warning Using MMX Smoothscale
143
bool haveMMX = KCPUInfo::haveExtension( KCPUInfo::IntelMMX );
145
__mimageScale_mmx_AARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
146
0, 0, 0, 0, dw, dh, dw, w);
151
if(img.hasAlphaBuffer())
152
mimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
153
0, 0, dw, dh, dw, w);
155
mimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
156
0, 0, dw, dh, dw, w);
158
mimageFreeScaleInfo(scaleinfo);
163
// Code ported from Imlib...
166
// FIXME: replace with mRed, etc... These work on pointers to pixels, not
168
#if BYTE_ORDER == BIG_ENDIAN
169
#define A_VAL(p) ((unsigned char *)(p))[0]
170
#define R_VAL(p) ((unsigned char *)(p))[1]
171
#define G_VAL(p) ((unsigned char *)(p))[2]
172
#define B_VAL(p) ((unsigned char *)(p))[3]
173
#elif BYTE_ORDER == LITTLE_ENDIAN
174
#define A_VAL(p) ((unsigned char *)(p))[3]
175
#define R_VAL(p) ((unsigned char *)(p))[2]
176
#define G_VAL(p) ((unsigned char *)(p))[1]
177
#define B_VAL(p) ((unsigned char *)(p))[0]
179
#error "BYTE_ORDER is not defined"
182
#define INV_XAP (256 - xapoints[x])
183
#define XAP (xapoints[x])
184
#define INV_YAP (256 - yapoints[dyy + y])
185
#define YAP (yapoints[dyy + y])
187
unsigned int** MImageScale::mimageCalcYPoints(unsigned int *src,
188
int sw, int sh, int dh)
192
int val, inc, rv = 0;
198
p = new unsigned int* [dh+1];
201
inc = (sh << 16) / dh;
202
for(i = 0; i < dh; i++){
203
p[j++] = src + ((val >> 16) * sw);
207
for(i = dh / 2; --i >= 0; ){
208
unsigned int *tmp = p[i];
209
p[i] = p[dh - i - 1];
216
int* MImageScale::mimageCalcXPoints(int sw, int dw)
219
int val, inc, rv = 0;
228
inc = (sw << 16) / dw;
229
for(i = 0; i < dw; i++){
230
p[j++] = (val >> 16);
235
for(i = dw / 2; --i >= 0; ){
237
p[i] = p[dw - i - 1];
244
int* MImageScale::mimageCalcApoints(int s, int d, int up)
246
int *p, i, j = 0, rv = 0;
260
for(i = 0; i < d; i++){
261
p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
262
if((val >> 16) >= (s - 1))
269
int val, inc, ap, Cp;
272
Cp = ((d << 14) / s) + 1;
273
for(i = 0; i < d; i++){
274
ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
275
p[j] = ap | (Cp << 16);
282
for(i = d / 2; --i >= 0; ){
291
MImageScaleInfo* MImageScale::mimageFreeScaleInfo(MImageScaleInfo *isi)
294
delete[] isi->xpoints;
295
delete[] isi->ypoints;
296
delete[] isi->xapoints;
297
delete[] isi->yapoints;
303
MImageScaleInfo* MImageScale::mimageCalcScaleInfo(QImage &img, int sw, int sh,
304
int dw, int dh, char aa)
306
MImageScaleInfo *isi;
309
scw = dw * img.width() / sw;
310
sch = dh * img.height() / sh;
312
isi = new MImageScaleInfo;
315
memset(isi, 0, sizeof(MImageScaleInfo));
317
isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
319
isi->xpoints = mimageCalcXPoints(img.width(), scw);
321
return(mimageFreeScaleInfo(isi));
322
isi->ypoints = mimageCalcYPoints((unsigned int *)img.scanLine(0),
323
img.width(), img.height(), sch);
325
return(mimageFreeScaleInfo(isi));
327
isi->xapoints = mimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
329
return(mimageFreeScaleInfo(isi));
330
isi->yapoints = mimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
332
return(mimageFreeScaleInfo(isi));
337
/* scale by pixel sampling only */
338
void MImageScale::mimageSampleRGBA(MImageScaleInfo *isi, unsigned int *dest,
339
int dxx, int dyy, int dx, int dy, int dw,
342
unsigned int *sptr, *dptr;
344
unsigned int **ypoints = isi->ypoints;
345
int *xpoints = isi->xpoints;
347
/* whats the last pixel ont he line so we stop there */
349
/* go through every scanline in the output buffer */
350
for(y = 0; y < dh; y++){
351
/* get the pointer to the start of the destination scanline */
352
dptr = dest + dx + ((y + dy) * dow);
353
/* calculate the source line we'll scan from */
354
sptr = ypoints[dyy + y];
355
/* go thru the scanline and copy across */
356
for(x = dxx; x < end; x++)
357
*dptr++ = sptr[xpoints[x]];
361
/* FIXME: NEED to optimise ScaleAARGBA - currently it is "ok" but needs work*/
363
/* scale by area sampling */
364
void MImageScale::mimageScaleAARGBA(MImageScaleInfo *isi, unsigned int *dest,
365
int dxx, int dyy, int dx, int dy, int dw,
366
int dh, int dow, int sow)
368
unsigned int *sptr, *dptr;
370
unsigned int **ypoints = isi->ypoints;
371
int *xpoints = isi->xpoints;
372
int *xapoints = isi->xapoints;
373
int *yapoints = isi->yapoints;
376
/* scaling up both ways */
377
if(isi->xup_yup == 3){
378
/* go through every scanline in the output buffer */
379
for(y = 0; y < dh; y++){
380
/* calculate the source line we'll scan from */
381
dptr = dest + dx + ((y + dy) * dow);
382
sptr = ypoints[dyy + y];
384
for(x = dxx; x < end; x++){
390
pix = ypoints[dyy + y] + xpoints[x];
391
r = R_VAL(pix) * INV_XAP;
392
g = G_VAL(pix) * INV_XAP;
393
b = B_VAL(pix) * INV_XAP;
394
a = A_VAL(pix) * INV_XAP;
396
r += R_VAL(pix) * XAP;
397
g += G_VAL(pix) * XAP;
398
b += B_VAL(pix) * XAP;
399
a += A_VAL(pix) * XAP;
401
rr = R_VAL(pix) * XAP;
402
gg = G_VAL(pix) * XAP;
403
bb = B_VAL(pix) * XAP;
404
aa = A_VAL(pix) * XAP;
406
rr += R_VAL(pix) * INV_XAP;
407
gg += G_VAL(pix) * INV_XAP;
408
bb += B_VAL(pix) * INV_XAP;
409
aa += A_VAL(pix) * INV_XAP;
410
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
411
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
412
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
413
a = ((aa * YAP) + (a * INV_YAP)) >> 16;
414
*dptr++ = qRgba(r, g, b, a);
417
pix = ypoints[dyy + y] + xpoints[x];
418
r = R_VAL(pix) * INV_YAP;
419
g = G_VAL(pix) * INV_YAP;
420
b = B_VAL(pix) * INV_YAP;
421
a = A_VAL(pix) * INV_YAP;
423
r += R_VAL(pix) * YAP;
424
g += G_VAL(pix) * YAP;
425
b += B_VAL(pix) * YAP;
426
a += A_VAL(pix) * YAP;
431
*dptr++ = qRgba(r, g, b, a);
436
for(x = dxx; x < end; x++){
441
pix = ypoints[dyy + y] + xpoints[x];
442
r = R_VAL(pix) * INV_XAP;
443
g = G_VAL(pix) * INV_XAP;
444
b = B_VAL(pix) * INV_XAP;
445
a = A_VAL(pix) * INV_XAP;
447
r += R_VAL(pix) * XAP;
448
g += G_VAL(pix) * XAP;
449
b += B_VAL(pix) * XAP;
450
a += A_VAL(pix) * XAP;
455
*dptr++ = qRgba(r, g, b, a);
458
*dptr++ = sptr[xpoints[x] ];
463
/* if we're scaling down vertically */
464
else if(isi->xup_yup == 1){
465
/*\ 'Correct' version, with math units prepared for MMXification \*/
468
int r, g, b, a, rr, gg, bb, aa;
471
/* go through every scanline in the output buffer */
472
for(y = 0; y < dh; y++){
476
dptr = dest + dx + ((y + dy) * dow);
477
for(x = dxx; x < end; x++){
478
pix = ypoints[dyy + y] + xpoints[x];
479
r = (R_VAL(pix) * yap) >> 10;
480
g = (G_VAL(pix) * yap) >> 10;
481
b = (B_VAL(pix) * yap) >> 10;
482
a = (A_VAL(pix) * yap) >> 10;
483
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
485
r += (R_VAL(pix) * Cy) >> 10;
486
g += (G_VAL(pix) * Cy) >> 10;
487
b += (B_VAL(pix) * Cy) >> 10;
488
a += (A_VAL(pix) * Cy) >> 10;
492
r += (R_VAL(pix) * j) >> 10;
493
g += (G_VAL(pix) * j) >> 10;
494
b += (B_VAL(pix) * j) >> 10;
495
a += (A_VAL(pix) * j) >> 10;
498
pix = ypoints[dyy + y] + xpoints[x] + 1;
499
rr = (R_VAL(pix) * yap) >> 10;
500
gg = (G_VAL(pix) * yap) >> 10;
501
bb = (B_VAL(pix) * yap) >> 10;
502
aa = (A_VAL(pix) * yap) >> 10;
503
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
505
rr += (R_VAL(pix) * Cy) >> 10;
506
gg += (G_VAL(pix) * Cy) >> 10;
507
bb += (B_VAL(pix) * Cy) >> 10;
508
aa += (A_VAL(pix) * Cy) >> 10;
512
rr += (R_VAL(pix) * j) >> 10;
513
gg += (G_VAL(pix) * j) >> 10;
514
bb += (B_VAL(pix) * j) >> 10;
515
aa += (A_VAL(pix) * j) >> 10;
521
r = (r + ((rr * XAP))) >> 12;
522
g = (g + ((gg * XAP))) >> 12;
523
b = (b + ((bb * XAP))) >> 12;
524
a = (a + ((aa * XAP))) >> 12;
532
*dptr = qRgba(r, g, b, a);
537
/* if we're scaling down horizontally */
538
else if(isi->xup_yup == 2){
539
/*\ 'Correct' version, with math units prepared for MMXification \*/
542
int r, g, b, a, rr, gg, bb, aa;
545
/* go through every scanline in the output buffer */
546
for(y = 0; y < dh; y++){
547
dptr = dest + dx + ((y + dy) * dow);
548
for(x = dxx; x < end; x++){
552
pix = ypoints[dyy + y] + xpoints[x];
553
r = (R_VAL(pix) * xap) >> 10;
554
g = (G_VAL(pix) * xap) >> 10;
555
b = (B_VAL(pix) * xap) >> 10;
556
a = (A_VAL(pix) * xap) >> 10;
557
for(j = (1 << 14) - xap; j > Cx; j -= Cx){
559
r += (R_VAL(pix) * Cx) >> 10;
560
g += (G_VAL(pix) * Cx) >> 10;
561
b += (B_VAL(pix) * Cx) >> 10;
562
a += (A_VAL(pix) * Cx) >> 10;
566
r += (R_VAL(pix) * j) >> 10;
567
g += (G_VAL(pix) * j) >> 10;
568
b += (B_VAL(pix) * j) >> 10;
569
a += (A_VAL(pix) * j) >> 10;
572
pix = ypoints[dyy + y] + xpoints[x] + sow;
573
rr = (R_VAL(pix) * xap) >> 10;
574
gg = (G_VAL(pix) * xap) >> 10;
575
bb = (B_VAL(pix) * xap) >> 10;
576
aa = (A_VAL(pix) * xap) >> 10;
577
for(j = (1 << 14) - xap; j > Cx; j -= Cx){
579
rr += (R_VAL(pix) * Cx) >> 10;
580
gg += (G_VAL(pix) * Cx) >> 10;
581
bb += (B_VAL(pix) * Cx) >> 10;
582
aa += (A_VAL(pix) * Cx) >> 10;
586
rr += (R_VAL(pix) * j) >> 10;
587
gg += (G_VAL(pix) * j) >> 10;
588
bb += (B_VAL(pix) * j) >> 10;
589
aa += (A_VAL(pix) * j) >> 10;
595
r = (r + ((rr * YAP))) >> 12;
596
g = (g + ((gg * YAP))) >> 12;
597
b = (b + ((bb * YAP))) >> 12;
598
a = (a + ((aa * YAP))) >> 12;
606
*dptr = qRgba(r, g, b, a);
611
/* if we're scaling down horizontally & vertically */
613
/*\ 'Correct' version, with math units prepared for MMXification:
614
|*| The operation 'b = (b * c) >> 16' translates to pmulhw,
615
|*| so the operation 'b = (b * c) >> d' would translate to
616
|*| psllw (16 - d), %mmb; pmulh %mmc, %mmb
620
int a, r, g, b, ax, rx, gx, bx;
623
for(y = 0; y < dh; y++){
627
dptr = dest + dx + ((y + dy) * dow);
628
for(x = dxx; x < end; x++){
632
sptr = ypoints[dyy + y] + xpoints[x];
635
rx = (R_VAL(pix) * xap) >> 9;
636
gx = (G_VAL(pix) * xap) >> 9;
637
bx = (B_VAL(pix) * xap) >> 9;
638
ax = (A_VAL(pix) * xap) >> 9;
640
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
641
rx += (R_VAL(pix) * Cx) >> 9;
642
gx += (G_VAL(pix) * Cx) >> 9;
643
bx += (B_VAL(pix) * Cx) >> 9;
644
ax += (A_VAL(pix) * Cx) >> 9;
648
rx += (R_VAL(pix) * i) >> 9;
649
gx += (G_VAL(pix) * i) >> 9;
650
bx += (B_VAL(pix) * i) >> 9;
651
ax += (A_VAL(pix) * i) >> 9;
654
r = (rx * yap) >> 14;
655
g = (gx * yap) >> 14;
656
b = (bx * yap) >> 14;
657
a = (ax * yap) >> 14;
659
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
662
rx = (R_VAL(pix) * xap) >> 9;
663
gx = (G_VAL(pix) * xap) >> 9;
664
bx = (B_VAL(pix) * xap) >> 9;
665
ax = (A_VAL(pix) * xap) >> 9;
667
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
668
rx += (R_VAL(pix) * Cx) >> 9;
669
gx += (G_VAL(pix) * Cx) >> 9;
670
bx += (B_VAL(pix) * Cx) >> 9;
671
ax += (A_VAL(pix) * Cx) >> 9;
675
rx += (R_VAL(pix) * i) >> 9;
676
gx += (G_VAL(pix) * i) >> 9;
677
bx += (B_VAL(pix) * i) >> 9;
678
ax += (A_VAL(pix) * i) >> 9;
681
r += (rx * Cy) >> 14;
682
g += (gx * Cy) >> 14;
683
b += (bx * Cy) >> 14;
684
a += (ax * Cy) >> 14;
689
rx = (R_VAL(pix) * xap) >> 9;
690
gx = (G_VAL(pix) * xap) >> 9;
691
bx = (B_VAL(pix) * xap) >> 9;
692
ax = (A_VAL(pix) * xap) >> 9;
694
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
695
rx += (R_VAL(pix) * Cx) >> 9;
696
gx += (G_VAL(pix) * Cx) >> 9;
697
bx += (B_VAL(pix) * Cx) >> 9;
698
ax += (A_VAL(pix) * Cx) >> 9;
702
rx += (R_VAL(pix) * i) >> 9;
703
gx += (G_VAL(pix) * i) >> 9;
704
bx += (B_VAL(pix) * i) >> 9;
705
ax += (A_VAL(pix) * i) >> 9;
714
R_VAL(dptr) = r >> 5;
715
G_VAL(dptr) = g >> 5;
716
B_VAL(dptr) = b >> 5;
717
A_VAL(dptr) = a >> 5;
724
/* scale by area sampling - IGNORE the ALPHA byte*/
725
void MImageScale::mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest,
726
int dxx, int dyy, int dx, int dy, int dw,
727
int dh, int dow, int sow)
729
unsigned int *sptr, *dptr;
731
unsigned int **ypoints = isi->ypoints;
732
int *xpoints = isi->xpoints;
733
int *xapoints = isi->xapoints;
734
int *yapoints = isi->yapoints;
737
/* scaling up both ways */
738
if(isi->xup_yup == 3){
739
/* go through every scanline in the output buffer */
740
for(y = 0; y < dh; y++){
741
/* calculate the source line we'll scan from */
742
dptr = dest + dx + ((y + dy) * dow);
743
sptr = ypoints[dyy + y];
745
for(x = dxx; x < end; x++){
746
int r = 0, g = 0, b = 0;
747
int rr = 0, gg = 0, bb = 0;
751
pix = ypoints[dyy + y] + xpoints[x];
752
r = R_VAL(pix) * INV_XAP;
753
g = G_VAL(pix) * INV_XAP;
754
b = B_VAL(pix) * INV_XAP;
756
r += R_VAL(pix) * XAP;
757
g += G_VAL(pix) * XAP;
758
b += B_VAL(pix) * XAP;
760
rr = R_VAL(pix) * XAP;
761
gg = G_VAL(pix) * XAP;
762
bb = B_VAL(pix) * XAP;
764
rr += R_VAL(pix) * INV_XAP;
765
gg += G_VAL(pix) * INV_XAP;
766
bb += B_VAL(pix) * INV_XAP;
767
r = ((rr * YAP) + (r * INV_YAP)) >> 16;
768
g = ((gg * YAP) + (g * INV_YAP)) >> 16;
769
b = ((bb * YAP) + (b * INV_YAP)) >> 16;
770
*dptr++ = qRgba(r, g, b, 0xff);
773
pix = ypoints[dyy + y] + xpoints[x];
774
r = R_VAL(pix) * INV_YAP;
775
g = G_VAL(pix) * INV_YAP;
776
b = B_VAL(pix) * INV_YAP;
778
r += R_VAL(pix) * YAP;
779
g += G_VAL(pix) * YAP;
780
b += B_VAL(pix) * YAP;
784
*dptr++ = qRgba(r, g, b, 0xff);
789
for(x = dxx; x < end; x++){
790
int r = 0, g = 0, b = 0;
794
pix = ypoints[dyy + y] + xpoints[x];
795
r = R_VAL(pix) * INV_XAP;
796
g = G_VAL(pix) * INV_XAP;
797
b = B_VAL(pix) * INV_XAP;
799
r += R_VAL(pix) * XAP;
800
g += G_VAL(pix) * XAP;
801
b += B_VAL(pix) * XAP;
805
*dptr++ = qRgba(r, g, b, 0xff);
808
*dptr++ = sptr[xpoints[x] ];
813
/* if we're scaling down vertically */
814
else if(isi->xup_yup == 1){
815
/*\ 'Correct' version, with math units prepared for MMXification \*/
818
int r, g, b, rr, gg, bb;
821
/* go through every scanline in the output buffer */
822
for(y = 0; y < dh; y++){
826
dptr = dest + dx + ((y + dy) * dow);
827
for(x = dxx; x < end; x++){
828
pix = ypoints[dyy + y] + xpoints[x];
829
r = (R_VAL(pix) * yap) >> 10;
830
g = (G_VAL(pix) * yap) >> 10;
831
b = (B_VAL(pix) * yap) >> 10;
833
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
834
r += (R_VAL(pix) * Cy) >> 10;
835
g += (G_VAL(pix) * Cy) >> 10;
836
b += (B_VAL(pix) * Cy) >> 10;
840
r += (R_VAL(pix) * j) >> 10;
841
g += (G_VAL(pix) * j) >> 10;
842
b += (B_VAL(pix) * j) >> 10;
845
pix = ypoints[dyy + y] + xpoints[x] + 1;
846
rr = (R_VAL(pix) * yap) >> 10;
847
gg = (G_VAL(pix) * yap) >> 10;
848
bb = (B_VAL(pix) * yap) >> 10;
850
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
851
rr += (R_VAL(pix) * Cy) >> 10;
852
gg += (G_VAL(pix) * Cy) >> 10;
853
bb += (B_VAL(pix) * Cy) >> 10;
857
rr += (R_VAL(pix) * j) >> 10;
858
gg += (G_VAL(pix) * j) >> 10;
859
bb += (B_VAL(pix) * j) >> 10;
864
r = (r + ((rr * XAP))) >> 12;
865
g = (g + ((gg * XAP))) >> 12;
866
b = (b + ((bb * XAP))) >> 12;
873
*dptr = qRgba(r, g, b, 0xff);
878
/* if we're scaling down horizontally */
879
else if(isi->xup_yup == 2){
880
/*\ 'Correct' version, with math units prepared for MMXification \*/
883
int r, g, b, rr, gg, bb;
886
/* go through every scanline in the output buffer */
887
for(y = 0; y < dh; y++){
888
dptr = dest + dx + ((y + dy) * dow);
889
for(x = dxx; x < end; x++){
893
pix = ypoints[dyy + y] + xpoints[x];
894
r = (R_VAL(pix) * xap) >> 10;
895
g = (G_VAL(pix) * xap) >> 10;
896
b = (B_VAL(pix) * xap) >> 10;
898
for(j = (1 << 14) - xap; j > Cx; j -= Cx){
899
r += (R_VAL(pix) * Cx) >> 10;
900
g += (G_VAL(pix) * Cx) >> 10;
901
b += (B_VAL(pix) * Cx) >> 10;
905
r += (R_VAL(pix) * j) >> 10;
906
g += (G_VAL(pix) * j) >> 10;
907
b += (B_VAL(pix) * j) >> 10;
910
pix = ypoints[dyy + y] + xpoints[x] + sow;
911
rr = (R_VAL(pix) * xap) >> 10;
912
gg = (G_VAL(pix) * xap) >> 10;
913
bb = (B_VAL(pix) * xap) >> 10;
915
for(j = (1 << 14) - xap; j > Cx; j -= Cx){
916
rr += (R_VAL(pix) * Cx) >> 10;
917
gg += (G_VAL(pix) * Cx) >> 10;
918
bb += (B_VAL(pix) * Cx) >> 10;
922
rr += (R_VAL(pix) * j) >> 10;
923
gg += (G_VAL(pix) * j) >> 10;
924
bb += (B_VAL(pix) * j) >> 10;
929
r = (r + ((rr * YAP))) >> 12;
930
g = (g + ((gg * YAP))) >> 12;
931
b = (b + ((bb * YAP))) >> 12;
938
*dptr = qRgba(r, g, b, 0xff);
943
/* fully optimized (i think) - onyl change of algorithm can help */
944
/* if we're scaling down horizontally & vertically */
946
/*\ 'Correct' version, with math units prepared for MMXification \*/
949
int r, g, b, rx, gx, bx;
952
for(y = 0; y < dh; y++){
956
dptr = dest + dx + ((y + dy) * dow);
957
for(x = dxx; x < end; x++){
961
sptr = ypoints[dyy + y] + xpoints[x];
964
rx = (R_VAL(pix) * xap) >> 9;
965
gx = (G_VAL(pix) * xap) >> 9;
966
bx = (B_VAL(pix) * xap) >> 9;
968
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
969
rx += (R_VAL(pix) * Cx) >> 9;
970
gx += (G_VAL(pix) * Cx) >> 9;
971
bx += (B_VAL(pix) * Cx) >> 9;
975
rx += (R_VAL(pix) * i) >> 9;
976
gx += (G_VAL(pix) * i) >> 9;
977
bx += (B_VAL(pix) * i) >> 9;
980
r = (rx * yap) >> 14;
981
g = (gx * yap) >> 14;
982
b = (bx * yap) >> 14;
984
for(j = (1 << 14) - yap; j > Cy; j -= Cy){
987
rx = (R_VAL(pix) * xap) >> 9;
988
gx = (G_VAL(pix) * xap) >> 9;
989
bx = (B_VAL(pix) * xap) >> 9;
991
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
992
rx += (R_VAL(pix) * Cx) >> 9;
993
gx += (G_VAL(pix) * Cx) >> 9;
994
bx += (B_VAL(pix) * Cx) >> 9;
998
rx += (R_VAL(pix) * i) >> 9;
999
gx += (G_VAL(pix) * i) >> 9;
1000
bx += (B_VAL(pix) * i) >> 9;
1003
r += (rx * Cy) >> 14;
1004
g += (gx * Cy) >> 14;
1005
b += (bx * Cy) >> 14;
1010
rx = (R_VAL(pix) * xap) >> 9;
1011
gx = (G_VAL(pix) * xap) >> 9;
1012
bx = (B_VAL(pix) * xap) >> 9;
1014
for(i = (1 << 14) - xap; i > Cx; i -= Cx){
1015
rx += (R_VAL(pix) * Cx) >> 9;
1016
gx += (G_VAL(pix) * Cx) >> 9;
1017
bx += (B_VAL(pix) * Cx) >> 9;
1021
rx += (R_VAL(pix) * i) >> 9;
1022
gx += (G_VAL(pix) * i) >> 9;
1023
bx += (B_VAL(pix) * i) >> 9;
1026
r += (rx * j) >> 14;
1027
g += (gx * j) >> 14;
1028
b += (bx * j) >> 14;
1031
R_VAL(dptr) = r >> 5;
1032
G_VAL(dptr) = g >> 5;
1033
B_VAL(dptr) = b >> 5;
1041
QImage scale(const QImage& image, int width, int height)
1043
if( image.isNull()) return image.copy();
1045
QSize newSize( width, height );
1046
newSize = newSize.expandedTo( QSize( 1, 1 )); // make sure it doesn't become null
1048
if ( newSize == image.size() ) return image.copy();
1050
width = newSize.width();
1051
height = newSize.height();
1052
// return image.smoothScale( width, height );
1053
return MImageScale::smoothScale( image, width, height );