add more spacing
[personal-kdebase.git] / workspace / ksplash / ksplashx / scale.cpp
blob04ca230312574068931a3aed71a8194dc0dc04b1
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.
6 /**
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
28 are met:
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
70 and it's intent.
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>
82 #include "scale.h"
84 #include <string.h>
86 #include "kcpuinfo.h"
87 #include "qcolor.h"
89 namespace MImageScale{
90 typedef struct __mimage_scale_info
92 int *xpoints;
93 unsigned int **ypoints;
94 int *xapoints, *yapoints;
95 int xup_yup;
96 } MImageScaleInfo;
98 unsigned int** mimageCalcYPoints(unsigned int *src, int sw, int sh,
99 int dh);
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,
109 int sow);
110 void mimageScaleAARGB(MImageScaleInfo *isi, unsigned int *dest, int dxx,
111 int dyy, int dx, int dy, int dw, int dh, int dow, int
112 sow);
113 QImage smoothScale(const QImage& img, int dw, int dh);
116 #ifdef HAVE_X86_MMX
117 extern "C" {
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,
121 int dow, int sow);
123 #endif
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;
130 int w = img.width();
131 int h = img.height();
133 MImageScaleInfo *scaleinfo =
134 mimageCalcScaleInfo(img, w, h, dw, dh, true);
135 if(!scaleinfo)
136 return QImage();
138 QImage buffer(dw, dh, 32);
139 buffer.setAlphaBuffer(img.hasAlphaBuffer());
141 #ifdef HAVE_X86_MMX
142 //#warning Using MMX Smoothscale
143 bool haveMMX = KCPUInfo::haveExtension( KCPUInfo::IntelMMX );
144 if(haveMMX){
145 __mimageScale_mmx_AARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
146 0, 0, 0, 0, dw, dh, dw, w);
148 else
149 #endif
151 if(img.hasAlphaBuffer())
152 mimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
153 0, 0, dw, dh, dw, w);
154 else
155 mimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0), 0, 0,
156 0, 0, dw, dh, dw, w);
158 mimageFreeScaleInfo(scaleinfo);
159 return(buffer);
163 // Code ported from Imlib...
166 // FIXME: replace with mRed, etc... These work on pointers to pixels, not
167 // pixel values
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]
178 #else
179 #error "BYTE_ORDER is not defined"
180 #endif
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)
190 unsigned int **p;
191 int i, j = 0;
192 int val, inc, rv = 0;
194 if(dh < 0){
195 dh = -dh;
196 rv = 1;
198 p = new unsigned int* [dh+1];
200 val = 0;
201 inc = (sh << 16) / dh;
202 for(i = 0; i < dh; i++){
203 p[j++] = src + ((val >> 16) * sw);
204 val += inc;
206 if(rv){
207 for(i = dh / 2; --i >= 0; ){
208 unsigned int *tmp = p[i];
209 p[i] = p[dh - i - 1];
210 p[dh - i - 1] = tmp;
213 return(p);
216 int* MImageScale::mimageCalcXPoints(int sw, int dw)
218 int *p, i, j = 0;
219 int val, inc, rv = 0;
221 if(dw < 0){
222 dw = -dw;
223 rv = 1;
225 p = new int[dw+1];
227 val = 0;
228 inc = (sw << 16) / dw;
229 for(i = 0; i < dw; i++){
230 p[j++] = (val >> 16);
231 val += inc;
234 if(rv){
235 for(i = dw / 2; --i >= 0; ){
236 int tmp = p[i];
237 p[i] = p[dw - i - 1];
238 p[dw - i - 1] = tmp;
241 return(p);
244 int* MImageScale::mimageCalcApoints(int s, int d, int up)
246 int *p, i, j = 0, rv = 0;
248 if(d < 0){
249 rv = 1;
250 d = -d;
252 p = new int[d];
254 /* scaling up */
255 if(up){
256 int val, inc;
258 val = 0;
259 inc = (s << 16) / d;
260 for(i = 0; i < d; i++){
261 p[j++] = (val >> 8) - ((val >> 8) & 0xffffff00);
262 if((val >> 16) >= (s - 1))
263 p[j - 1] = 0;
264 val += inc;
267 /* scaling down */
268 else{
269 int val, inc, ap, Cp;
270 val = 0;
271 inc = (s << 16) / d;
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);
276 j++;
277 val += inc;
280 if(rv){
281 int tmp;
282 for(i = d / 2; --i >= 0; ){
283 tmp = p[i];
284 p[i] = p[d - i - 1];
285 p[d - i - 1] = tmp;
288 return(p);
291 MImageScaleInfo* MImageScale::mimageFreeScaleInfo(MImageScaleInfo *isi)
293 if(isi){
294 delete[] isi->xpoints;
295 delete[] isi->ypoints;
296 delete[] isi->xapoints;
297 delete[] isi->yapoints;
298 delete isi;
300 return(NULL);
303 MImageScaleInfo* MImageScale::mimageCalcScaleInfo(QImage &img, int sw, int sh,
304 int dw, int dh, char aa)
306 MImageScaleInfo *isi;
307 int scw, sch;
309 scw = dw * img.width() / sw;
310 sch = dh * img.height() / sh;
312 isi = new MImageScaleInfo;
313 if(!isi)
314 return(NULL);
315 memset(isi, 0, sizeof(MImageScaleInfo));
317 isi->xup_yup = (abs(dw) >= sw) + ((abs(dh) >= sh) << 1);
319 isi->xpoints = mimageCalcXPoints(img.width(), scw);
320 if(!isi->xpoints)
321 return(mimageFreeScaleInfo(isi));
322 isi->ypoints = mimageCalcYPoints((unsigned int *)img.scanLine(0),
323 img.width(), img.height(), sch);
324 if (!isi->ypoints)
325 return(mimageFreeScaleInfo(isi));
326 if(aa){
327 isi->xapoints = mimageCalcApoints(img.width(), scw, isi->xup_yup & 1);
328 if(!isi->xapoints)
329 return(mimageFreeScaleInfo(isi));
330 isi->yapoints = mimageCalcApoints(img.height(), sch, isi->xup_yup & 2);
331 if(!isi->yapoints)
332 return(mimageFreeScaleInfo(isi));
334 return(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,
340 int dh, int dow)
342 unsigned int *sptr, *dptr;
343 int x, y, end;
344 unsigned int **ypoints = isi->ypoints;
345 int *xpoints = isi->xpoints;
347 /* whats the last pixel ont he line so we stop there */
348 end = dxx + dw;
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;
369 int x, y, end;
370 unsigned int **ypoints = isi->ypoints;
371 int *xpoints = isi->xpoints;
372 int *xapoints = isi->xapoints;
373 int *yapoints = isi->yapoints;
375 end = dxx + dw;
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];
383 if(YAP > 0){
384 for(x = dxx; x < end; x++){
385 int r, g, b, a;
386 int rr, gg, bb, aa;
387 unsigned int *pix;
389 if(XAP > 0){
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;
395 pix++;
396 r += R_VAL(pix) * XAP;
397 g += G_VAL(pix) * XAP;
398 b += B_VAL(pix) * XAP;
399 a += A_VAL(pix) * XAP;
400 pix += sow;
401 rr = R_VAL(pix) * XAP;
402 gg = G_VAL(pix) * XAP;
403 bb = B_VAL(pix) * XAP;
404 aa = A_VAL(pix) * XAP;
405 pix--;
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);
416 else{
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;
422 pix += sow;
423 r += R_VAL(pix) * YAP;
424 g += G_VAL(pix) * YAP;
425 b += B_VAL(pix) * YAP;
426 a += A_VAL(pix) * YAP;
427 r >>= 8;
428 g >>= 8;
429 b >>= 8;
430 a >>= 8;
431 *dptr++ = qRgba(r, g, b, a);
435 else{
436 for(x = dxx; x < end; x++){
437 int r, g, b, a;
438 unsigned int *pix;
440 if(XAP > 0){
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;
446 pix++;
447 r += R_VAL(pix) * XAP;
448 g += G_VAL(pix) * XAP;
449 b += B_VAL(pix) * XAP;
450 a += A_VAL(pix) * XAP;
451 r >>= 8;
452 g >>= 8;
453 b >>= 8;
454 a >>= 8;
455 *dptr++ = qRgba(r, g, b, a);
457 else
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 \*/
466 int Cy, j;
467 unsigned int *pix;
468 int r, g, b, a, rr, gg, bb, aa;
469 int yap;
471 /* go through every scanline in the output buffer */
472 for(y = 0; y < dh; y++){
473 Cy = YAP >> 16;
474 yap = YAP & 0xffff;
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){
484 pix += sow;
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;
490 if(j > 0){
491 pix += sow;
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;
497 if(XAP > 0){
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){
504 pix += sow;
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;
510 if(j > 0){
511 pix += sow;
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;
517 r = r * INV_XAP;
518 g = g * INV_XAP;
519 b = b * INV_XAP;
520 a = a * INV_XAP;
521 r = (r + ((rr * XAP))) >> 12;
522 g = (g + ((gg * XAP))) >> 12;
523 b = (b + ((bb * XAP))) >> 12;
524 a = (a + ((aa * XAP))) >> 12;
526 else{
527 r >>= 4;
528 g >>= 4;
529 b >>= 4;
530 a >>= 4;
532 *dptr = qRgba(r, g, b, a);
533 dptr++;
537 /* if we're scaling down horizontally */
538 else if(isi->xup_yup == 2){
539 /*\ 'Correct' version, with math units prepared for MMXification \*/
540 int Cx, j;
541 unsigned int *pix;
542 int r, g, b, a, rr, gg, bb, aa;
543 int xap;
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++){
549 Cx = XAP >> 16;
550 xap = XAP & 0xffff;
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){
558 pix++;
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;
564 if(j > 0){
565 pix++;
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;
571 if(YAP > 0){
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){
578 pix++;
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;
584 if(j > 0){
585 pix++;
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;
591 r = r * INV_YAP;
592 g = g * INV_YAP;
593 b = b * INV_YAP;
594 a = a * INV_YAP;
595 r = (r + ((rr * YAP))) >> 12;
596 g = (g + ((gg * YAP))) >> 12;
597 b = (b + ((bb * YAP))) >> 12;
598 a = (a + ((aa * YAP))) >> 12;
600 else{
601 r >>= 4;
602 g >>= 4;
603 b >>= 4;
604 a >>= 4;
606 *dptr = qRgba(r, g, b, a);
607 dptr++;
611 /* if we're scaling down horizontally & vertically */
612 else{
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
618 int Cx, Cy, i, j;
619 unsigned int *pix;
620 int a, r, g, b, ax, rx, gx, bx;
621 int xap, yap;
623 for(y = 0; y < dh; y++){
624 Cy = YAP >> 16;
625 yap = YAP & 0xffff;
627 dptr = dest + dx + ((y + dy) * dow);
628 for(x = dxx; x < end; x++){
629 Cx = XAP >> 16;
630 xap = XAP & 0xffff;
632 sptr = ypoints[dyy + y] + xpoints[x];
633 pix = sptr;
634 sptr += sow;
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;
639 pix++;
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;
645 pix++;
647 if(i > 0){
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){
660 pix = sptr;
661 sptr += sow;
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;
666 pix++;
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;
672 pix++;
674 if(i > 0){
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;
686 if(j > 0){
687 pix = sptr;
688 sptr += sow;
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;
693 pix++;
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;
699 pix++;
701 if(i > 0){
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;
708 r += (rx * j) >> 14;
709 g += (gx * j) >> 14;
710 b += (bx * j) >> 14;
711 a += (ax * j) >> 14;
714 R_VAL(dptr) = r >> 5;
715 G_VAL(dptr) = g >> 5;
716 B_VAL(dptr) = b >> 5;
717 A_VAL(dptr) = a >> 5;
718 dptr++;
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;
730 int x, y, end;
731 unsigned int **ypoints = isi->ypoints;
732 int *xpoints = isi->xpoints;
733 int *xapoints = isi->xapoints;
734 int *yapoints = isi->yapoints;
736 end = dxx + dw;
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];
744 if(YAP > 0){
745 for(x = dxx; x < end; x++){
746 int r = 0, g = 0, b = 0;
747 int rr = 0, gg = 0, bb = 0;
748 unsigned int *pix;
750 if(XAP > 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;
755 pix++;
756 r += R_VAL(pix) * XAP;
757 g += G_VAL(pix) * XAP;
758 b += B_VAL(pix) * XAP;
759 pix += sow;
760 rr = R_VAL(pix) * XAP;
761 gg = G_VAL(pix) * XAP;
762 bb = B_VAL(pix) * XAP;
763 pix --;
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);
772 else{
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;
777 pix += sow;
778 r += R_VAL(pix) * YAP;
779 g += G_VAL(pix) * YAP;
780 b += B_VAL(pix) * YAP;
781 r >>= 8;
782 g >>= 8;
783 b >>= 8;
784 *dptr++ = qRgba(r, g, b, 0xff);
788 else{
789 for(x = dxx; x < end; x++){
790 int r = 0, g = 0, b = 0;
791 unsigned int *pix;
793 if(XAP > 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;
798 pix++;
799 r += R_VAL(pix) * XAP;
800 g += G_VAL(pix) * XAP;
801 b += B_VAL(pix) * XAP;
802 r >>= 8;
803 g >>= 8;
804 b >>= 8;
805 *dptr++ = qRgba(r, g, b, 0xff);
807 else
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 \*/
816 int Cy, j;
817 unsigned int *pix;
818 int r, g, b, rr, gg, bb;
819 int yap;
821 /* go through every scanline in the output buffer */
822 for(y = 0; y < dh; y++){
823 Cy = YAP >> 16;
824 yap = YAP & 0xffff;
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;
832 pix += sow;
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;
837 pix += sow;
839 if(j > 0){
840 r += (R_VAL(pix) * j) >> 10;
841 g += (G_VAL(pix) * j) >> 10;
842 b += (B_VAL(pix) * j) >> 10;
844 if(XAP > 0){
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;
849 pix += sow;
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;
854 pix += sow;
856 if(j > 0){
857 rr += (R_VAL(pix) * j) >> 10;
858 gg += (G_VAL(pix) * j) >> 10;
859 bb += (B_VAL(pix) * j) >> 10;
861 r = r * INV_XAP;
862 g = g * INV_XAP;
863 b = b * INV_XAP;
864 r = (r + ((rr * XAP))) >> 12;
865 g = (g + ((gg * XAP))) >> 12;
866 b = (b + ((bb * XAP))) >> 12;
868 else{
869 r >>= 4;
870 g >>= 4;
871 b >>= 4;
873 *dptr = qRgba(r, g, b, 0xff);
874 dptr++;
878 /* if we're scaling down horizontally */
879 else if(isi->xup_yup == 2){
880 /*\ 'Correct' version, with math units prepared for MMXification \*/
881 int Cx, j;
882 unsigned int *pix;
883 int r, g, b, rr, gg, bb;
884 int xap;
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++){
890 Cx = XAP >> 16;
891 xap = XAP & 0xffff;
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;
897 pix++;
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;
902 pix++;
904 if(j > 0){
905 r += (R_VAL(pix) * j) >> 10;
906 g += (G_VAL(pix) * j) >> 10;
907 b += (B_VAL(pix) * j) >> 10;
909 if(YAP > 0){
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;
914 pix++;
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;
919 pix++;
921 if(j > 0){
922 rr += (R_VAL(pix) * j) >> 10;
923 gg += (G_VAL(pix) * j) >> 10;
924 bb += (B_VAL(pix) * j) >> 10;
926 r = r * INV_YAP;
927 g = g * INV_YAP;
928 b = b * INV_YAP;
929 r = (r + ((rr * YAP))) >> 12;
930 g = (g + ((gg * YAP))) >> 12;
931 b = (b + ((bb * YAP))) >> 12;
933 else{
934 r >>= 4;
935 g >>= 4;
936 b >>= 4;
938 *dptr = qRgba(r, g, b, 0xff);
939 dptr++;
943 /* fully optimized (i think) - onyl change of algorithm can help */
944 /* if we're scaling down horizontally & vertically */
945 else{
946 /*\ 'Correct' version, with math units prepared for MMXification \*/
947 int Cx, Cy, i, j;
948 unsigned int *pix;
949 int r, g, b, rx, gx, bx;
950 int xap, yap;
952 for(y = 0; y < dh; y++){
953 Cy = YAP >> 16;
954 yap = YAP & 0xffff;
956 dptr = dest + dx + ((y + dy) * dow);
957 for(x = dxx; x < end; x++){
958 Cx = XAP >> 16;
959 xap = XAP & 0xffff;
961 sptr = ypoints[dyy + y] + xpoints[x];
962 pix = sptr;
963 sptr += sow;
964 rx = (R_VAL(pix) * xap) >> 9;
965 gx = (G_VAL(pix) * xap) >> 9;
966 bx = (B_VAL(pix) * xap) >> 9;
967 pix++;
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;
972 pix++;
974 if(i > 0){
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){
985 pix = sptr;
986 sptr += sow;
987 rx = (R_VAL(pix) * xap) >> 9;
988 gx = (G_VAL(pix) * xap) >> 9;
989 bx = (B_VAL(pix) * xap) >> 9;
990 pix++;
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;
995 pix++;
997 if(i > 0){
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;
1007 if(j > 0){
1008 pix = sptr;
1009 sptr += sow;
1010 rx = (R_VAL(pix) * xap) >> 9;
1011 gx = (G_VAL(pix) * xap) >> 9;
1012 bx = (B_VAL(pix) * xap) >> 9;
1013 pix++;
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;
1018 pix++;
1020 if(i > 0){
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;
1034 dptr++;
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 );