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 its "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
);