summaryrefslogtreecommitdiff
path: root/libopie2
Unidiff
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opieui/oimageeffect.cpp76
1 files changed, 25 insertions, 51 deletions
diff --git a/libopie2/opieui/oimageeffect.cpp b/libopie2/opieui/oimageeffect.cpp
index 3c28bbe..2855da6 100644
--- a/libopie2/opieui/oimageeffect.cpp
+++ b/libopie2/opieui/oimageeffect.cpp
@@ -19,99 +19,97 @@ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28*/ 28*/
29 29
30// $Id$ 30// $Id$
31 31
32#include <math.h> 32#include <math.h>
33 33
34#include <qimage.h> 34#include <qimage.h>
35#include <stdlib.h> 35#include <stdlib.h>
36#include <iostream> 36#include <iostream>
37 37
38#include "oimageeffect.h" 38#include "oimageeffect.h"
39 39
40#define MaxRGB 255L 40#define MaxRGB 255L
41#define DegreesToRadians(x) ((x)*M_PI/180.0) 41#define DegreesToRadians(x) ((x)*M_PI/180.0)
42 42
43using namespace std; 43using namespace std;
44 44
45inline unsigned int intensityValue(unsigned int color) 45inline unsigned int intensityValue(unsigned int color)
46{ 46{
47 return((unsigned int)((0.299*qRed(color) + 47 return((unsigned int)((0.299*qRed(color) +
48 0.587*qGreen(color) + 48 0.587*qGreen(color) +
49 0.1140000000000001*qBlue(color)))); 49 0.1140000000000001*qBlue(color))));
50} 50}
51 51
52//====================================================================== 52//======================================================================
53// 53//
54// Gradient effects 54// Gradient effects
55// 55//
56//====================================================================== 56//======================================================================
57 57
58QImage OImageEffect::gradient(const QSize &size, const QColor &ca, 58QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
59 const QColor &cb, GradientType eff, int ncols) 59 const QColor &cb, GradientType eff, int ncols)
60{ 60{
61 int rDiff, gDiff, bDiff; 61 int rDiff, gDiff, bDiff;
62 int rca, gca, bca, rcb, gcb, bcb; 62 int rca, gca, bca, rcb, gcb, bcb;
63 63
64 QImage image(size, 32); 64 QImage image(size, 32);
65 65
66 if (size.width() == 0 || size.height() == 0) { 66 if (size.width() == 0 || size.height() == 0) {
67#ifndef NDEBUG 67 qDebug( "WARNING: OImageEffect::gradient: invalid image" );
68 cerr << "WARNING: OImageEffect::gradient: invalid image" << endl;
69#endif
70 return image; 68 return image;
71 } 69 }
72 70
73 register int x, y; 71 register int x, y;
74 72
75 rDiff = (rcb = cb.red()) - (rca = ca.red()); 73 rDiff = (rcb = cb.red()) - (rca = ca.red());
76 gDiff = (gcb = cb.green()) - (gca = ca.green()); 74 gDiff = (gcb = cb.green()) - (gca = ca.green());
77 bDiff = (bcb = cb.blue()) - (bca = ca.blue()); 75 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
78 76
79 if( eff == VerticalGradient || eff == HorizontalGradient ){ 77 if( eff == VerticalGradient || eff == HorizontalGradient ){
80 78
81 uint *p; 79 uint *p;
82 uint rgb; 80 uint rgb;
83 81
84 register int rl = rca << 16; 82 register int rl = rca << 16;
85 register int gl = gca << 16; 83 register int gl = gca << 16;
86 register int bl = bca << 16; 84 register int bl = bca << 16;
87 85
88 if( eff == VerticalGradient ) { 86 if( eff == VerticalGradient ) {
89 87
90 int rcdelta = ((1<<16) / size.height()) * rDiff; 88 int rcdelta = ((1<<16) / size.height()) * rDiff;
91 int gcdelta = ((1<<16) / size.height()) * gDiff; 89 int gcdelta = ((1<<16) / size.height()) * gDiff;
92 int bcdelta = ((1<<16) / size.height()) * bDiff; 90 int bcdelta = ((1<<16) / size.height()) * bDiff;
93 91
94 for ( y = 0; y < size.height(); y++ ) { 92 for ( y = 0; y < size.height(); y++ ) {
95 p = (uint *) image.scanLine(y); 93 p = (uint *) image.scanLine(y);
96 94
97 rl += rcdelta; 95 rl += rcdelta;
98 gl += gcdelta; 96 gl += gcdelta;
99 bl += bcdelta; 97 bl += bcdelta;
100 98
101 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) ); 99 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
102 100
103 for( x = 0; x < size.width(); x++ ) { 101 for( x = 0; x < size.width(); x++ ) {
104 *p = rgb; 102 *p = rgb;
105 p++; 103 p++;
106 } 104 }
107 } 105 }
108 106
109 } 107 }
110 else { // must be HorizontalGradient 108 else { // must be HorizontalGradient
111 109
112 unsigned int *o_src = (unsigned int *)image.scanLine(0); 110 unsigned int *o_src = (unsigned int *)image.scanLine(0);
113 unsigned int *src = o_src; 111 unsigned int *src = o_src;
114 112
115 int rcdelta = ((1<<16) / size.width()) * rDiff; 113 int rcdelta = ((1<<16) / size.width()) * rDiff;
116 int gcdelta = ((1<<16) / size.width()) * gDiff; 114 int gcdelta = ((1<<16) / size.width()) * gDiff;
117 int bcdelta = ((1<<16) / size.width()) * bDiff; 115 int bcdelta = ((1<<16) / size.width()) * bDiff;
@@ -307,99 +305,97 @@ QImage OImageEffect::gradient(const QSize &size, const QColor &ca,
307 return image; 305 return image;
308} 306}
309 307
310 308
311// ----------------------------------------------------------------------------- 309// -----------------------------------------------------------------------------
312 310
313//CT this was (before Dirk A. Mueller's speedup changes) 311//CT this was (before Dirk A. Mueller's speedup changes)
314// merely the same code as in the above method, but it's supposedly 312// merely the same code as in the above method, but it's supposedly
315// way less performant since it introduces a lot of supplementary tests 313// way less performant since it introduces a lot of supplementary tests
316// and simple math operations for the calculus of the balance. 314// and simple math operations for the calculus of the balance.
317// (surprizingly, it isn't less performant, in the contrary :-) 315// (surprizingly, it isn't less performant, in the contrary :-)
318// Yes, I could have merged them, but then the excellent performance of 316// Yes, I could have merged them, but then the excellent performance of
319// the balanced code would suffer with no other gain than a mere 317// the balanced code would suffer with no other gain than a mere
320// source code and byte code size economy. 318// source code and byte code size economy.
321 319
322QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca, 320QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
323 const QColor &cb, GradientType eff, int xfactor, int yfactor, 321 const QColor &cb, GradientType eff, int xfactor, int yfactor,
324 int ncols) 322 int ncols)
325{ 323{
326 int dir; // general parameter used for direction switches 324 int dir; // general parameter used for direction switches
327 325
328 bool _xanti = false , _yanti = false; 326 bool _xanti = false , _yanti = false;
329 327
330 if (xfactor < 0) _xanti = true; // negative on X direction 328 if (xfactor < 0) _xanti = true; // negative on X direction
331 if (yfactor < 0) _yanti = true; // negative on Y direction 329 if (yfactor < 0) _yanti = true; // negative on Y direction
332 330
333 xfactor = abs(xfactor); 331 xfactor = abs(xfactor);
334 yfactor = abs(yfactor); 332 yfactor = abs(yfactor);
335 333
336 if (!xfactor) xfactor = 1; 334 if (!xfactor) xfactor = 1;
337 if (!yfactor) yfactor = 1; 335 if (!yfactor) yfactor = 1;
338 336
339 if (xfactor > 200 ) xfactor = 200; 337 if (xfactor > 200 ) xfactor = 200;
340 if (yfactor > 200 ) yfactor = 200; 338 if (yfactor > 200 ) yfactor = 200;
341 339
342 340
343 // float xbal = xfactor/5000.; 341 // float xbal = xfactor/5000.;
344 // float ybal = yfactor/5000.; 342 // float ybal = yfactor/5000.;
345 float xbal = xfactor/30./size.width(); 343 float xbal = xfactor/30./size.width();
346 float ybal = yfactor/30./size.height(); 344 float ybal = yfactor/30./size.height();
347 float rat; 345 float rat;
348 346
349 int rDiff, gDiff, bDiff; 347 int rDiff, gDiff, bDiff;
350 int rca, gca, bca, rcb, gcb, bcb; 348 int rca, gca, bca, rcb, gcb, bcb;
351 349
352 QImage image(size, 32); 350 QImage image(size, 32);
353 351
354 if (size.width() == 0 || size.height() == 0) { 352 if (size.width() == 0 || size.height() == 0) {
355#ifndef NDEBUG 353 qDebug( "WARNING: OImageEffect::unbalancedGradient : invalid image" );
356 cerr << "WARNING: OImageEffect::unbalancedGradient : invalid image\n";
357#endif
358 return image; 354 return image;
359 } 355 }
360 356
361 register int x, y; 357 register int x, y;
362 unsigned int *scanline; 358 unsigned int *scanline;
363 359
364 rDiff = (rcb = cb.red()) - (rca = ca.red()); 360 rDiff = (rcb = cb.red()) - (rca = ca.red());
365 gDiff = (gcb = cb.green()) - (gca = ca.green()); 361 gDiff = (gcb = cb.green()) - (gca = ca.green());
366 bDiff = (bcb = cb.blue()) - (bca = ca.blue()); 362 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
367 363
368 if( eff == VerticalGradient || eff == HorizontalGradient){ 364 if( eff == VerticalGradient || eff == HorizontalGradient){
369 QColor cRow; 365 QColor cRow;
370 366
371 uint *p; 367 uint *p;
372 uint rgbRow; 368 uint rgbRow;
373 369
374 if( eff == VerticalGradient) { 370 if( eff == VerticalGradient) {
375 for ( y = 0; y < size.height(); y++ ) { 371 for ( y = 0; y < size.height(); y++ ) {
376 dir = _yanti ? y : size.height() - 1 - y; 372 dir = _yanti ? y : size.height() - 1 - y;
377 p = (uint *) image.scanLine(dir); 373 p = (uint *) image.scanLine(dir);
378 rat = 1 - exp( - (float)y * ybal ); 374 rat = 1 - exp( - (float)y * ybal );
379 375
380 cRow.setRgb( rcb - (int) ( rDiff * rat ), 376 cRow.setRgb( rcb - (int) ( rDiff * rat ),
381 gcb - (int) ( gDiff * rat ), 377 gcb - (int) ( gDiff * rat ),
382 bcb - (int) ( bDiff * rat ) ); 378 bcb - (int) ( bDiff * rat ) );
383 379
384 rgbRow = cRow.rgb(); 380 rgbRow = cRow.rgb();
385 381
386 for( x = 0; x < size.width(); x++ ) { 382 for( x = 0; x < size.width(); x++ ) {
387 *p = rgbRow; 383 *p = rgbRow;
388 p++; 384 p++;
389 } 385 }
390 } 386 }
391 } 387 }
392 else { 388 else {
393 389
394 unsigned int *src = (unsigned int *)image.scanLine(0); 390 unsigned int *src = (unsigned int *)image.scanLine(0);
395 for(x = 0; x < size.width(); x++ ) 391 for(x = 0; x < size.width(); x++ )
396 { 392 {
397 dir = _xanti ? x : size.width() - 1 - x; 393 dir = _xanti ? x : size.width() - 1 - x;
398 rat = 1 - exp( - (float)x * xbal ); 394 rat = 1 - exp( - (float)x * xbal );
399 395
400 src[dir] = qRgb(rcb - (int) ( rDiff * rat ), 396 src[dir] = qRgb(rcb - (int) ( rDiff * rat ),
401 gcb - (int) ( gDiff * rat ), 397 gcb - (int) ( gDiff * rat ),
402 bcb - (int) ( bDiff * rat )); 398 bcb - (int) ( bDiff * rat ));
403 } 399 }
404 400
405 // Believe it or not, manually copying in a for loop is faster 401 // Believe it or not, manually copying in a for loop is faster
@@ -528,259 +524,253 @@ QImage OImageEffect::unbalancedGradient(const QSize &size, const QColor &ca,
528 } 524 }
529 } 525 }
530 } 526 }
531 } 527 }
532 528
533 if (ncols && (QPixmap::defaultDepth() < 15 )) { 529 if (ncols && (QPixmap::defaultDepth() < 15 )) {
534 if ( ncols < 2 || ncols > 256 ) 530 if ( ncols < 2 || ncols > 256 )
535 ncols = 3; 531 ncols = 3;
536 QColor *dPal = new QColor[ncols]; 532 QColor *dPal = new QColor[ncols];
537 for (int i=0; i<ncols; i++) { 533 for (int i=0; i<ncols; i++) {
538 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ), 534 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
539 gca + gDiff * i / ( ncols - 1 ), 535 gca + gDiff * i / ( ncols - 1 ),
540 bca + bDiff * i / ( ncols - 1 ) ); 536 bca + bDiff * i / ( ncols - 1 ) );
541 } 537 }
542 dither(image, dPal, ncols); 538 dither(image, dPal, ncols);
543 delete [] dPal; 539 delete [] dPal;
544 } 540 }
545 541
546 delete [] xtable[0]; 542 delete [] xtable[0];
547 delete [] xtable[1]; 543 delete [] xtable[1];
548 delete [] xtable[2]; 544 delete [] xtable[2];
549 delete [] ytable[0]; 545 delete [] ytable[0];
550 delete [] ytable[1]; 546 delete [] ytable[1];
551 delete [] ytable[2]; 547 delete [] ytable[2];
552 548
553 } 549 }
554 550
555 return image; 551 return image;
556} 552}
557 553
558 554
559//====================================================================== 555//======================================================================
560// 556//
561// Intensity effects 557// Intensity effects
562// 558//
563//====================================================================== 559//======================================================================
564 560
565 561
566/* This builds a 256 byte unsigned char lookup table with all 562/* This builds a 256 byte unsigned char lookup table with all
567 * the possible percent values prior to applying the effect, then uses 563 * the possible percent values prior to applying the effect, then uses
568 * integer math for the pixels. For any image larger than 9x9 this will be 564 * integer math for the pixels. For any image larger than 9x9 this will be
569 * less expensive than doing a float operation on the 3 color components of 565 * less expensive than doing a float operation on the 3 color components of
570 * each pixel. (mosfet) 566 * each pixel. (mosfet)
571 */ 567 */
572 568
573QImage& OImageEffect::intensity(QImage &image, float percent) 569QImage& OImageEffect::intensity(QImage &image, float percent)
574{ 570{
575 if (image.width() == 0 || image.height() == 0) { 571 if (image.width() == 0 || image.height() == 0) {
576#ifndef NDEBUG 572 qDebug( "WARNING: OImageEffect::intensity : invalid image" );
577 cerr << "WARNING: OImageEffect::intensity : invalid image\n";
578#endif
579 return image; 573 return image;
580 } 574 }
581 575
582 int segColors = image.depth() > 8 ? 256 : image.numColors(); 576 int segColors = image.depth() > 8 ? 256 : image.numColors();
583 unsigned char *segTbl = new unsigned char[segColors]; 577 unsigned char *segTbl = new unsigned char[segColors];
584 int pixels = image.depth() > 8 ? image.width()*image.height() : 578 int pixels = image.depth() > 8 ? image.width()*image.height() :
585 image.numColors(); 579 image.numColors();
586 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() : 580 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
587 (unsigned int *)image.colorTable(); 581 (unsigned int *)image.colorTable();
588 582
589 bool brighten = (percent >= 0); 583 bool brighten = (percent >= 0);
590 if(percent < 0) 584 if(percent < 0)
591 percent = -percent; 585 percent = -percent;
592 586
593 if(brighten){ // keep overflow check out of loops 587 if(brighten){ // keep overflow check out of loops
594 for(int i=0; i < segColors; ++i){ 588 for(int i=0; i < segColors; ++i){
595 int tmp = (int)(i*percent); 589 int tmp = (int)(i*percent);
596 if(tmp > 255) 590 if(tmp > 255)
597 tmp = 255; 591 tmp = 255;
598 segTbl[i] = tmp; 592 segTbl[i] = tmp;
599 } 593 }
600 } 594 }
601 else{ 595 else{
602 for(int i=0; i < segColors; ++i){ 596 for(int i=0; i < segColors; ++i){
603 int tmp = (int)(i*percent); 597 int tmp = (int)(i*percent);
604 if(tmp < 0) 598 if(tmp < 0)
605 tmp = 0; 599 tmp = 0;
606 segTbl[i] = tmp; 600 segTbl[i] = tmp;
607 } 601 }
608 } 602 }
609 603
610 if(brighten){ // same here 604 if(brighten){ // same here
611 for(int i=0; i < pixels; ++i){ 605 for(int i=0; i < pixels; ++i){
612 int r = qRed(data[i]); 606 int r = qRed(data[i]);
613 int g = qGreen(data[i]); 607 int g = qGreen(data[i]);
614 int b = qBlue(data[i]); 608 int b = qBlue(data[i]);
615 int a = qAlpha(data[i]); 609 int a = qAlpha(data[i]);
616 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r]; 610 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
617 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g]; 611 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
618 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b]; 612 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
619 data[i] = qRgba(r, g, b,a); 613 data[i] = qRgba(r, g, b,a);
620 } 614 }
621 } 615 }
622 else{ 616 else{
623 for(int i=0; i < pixels; ++i){ 617 for(int i=0; i < pixels; ++i){
624 int r = qRed(data[i]); 618 int r = qRed(data[i]);
625 int g = qGreen(data[i]); 619 int g = qGreen(data[i]);
626 int b = qBlue(data[i]); 620 int b = qBlue(data[i]);
627 int a = qAlpha(data[i]); 621 int a = qAlpha(data[i]);
628 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r]; 622 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
629 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g]; 623 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
630 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b]; 624 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
631 data[i] = qRgba(r, g, b, a); 625 data[i] = qRgba(r, g, b, a);
632 } 626 }
633 } 627 }
634 delete [] segTbl; 628 delete [] segTbl;
635 629
636 return image; 630 return image;
637} 631}
638 632
639QImage& OImageEffect::channelIntensity(QImage &image, float percent, 633QImage& OImageEffect::channelIntensity(QImage &image, float percent,
640 RGBComponent channel) 634 RGBComponent channel)
641{ 635{
642 if (image.width() == 0 || image.height() == 0) { 636 if (image.width() == 0 || image.height() == 0) {
643#ifndef NDEBUG 637 qDebug( "WARNING: OImageEffect::channelIntensity : invalid image" );
644 cerr << "WARNING: OImageEffect::channelIntensity : invalid image\n";
645#endif
646 return image; 638 return image;
647 } 639 }
648 640
649 int segColors = image.depth() > 8 ? 256 : image.numColors(); 641 int segColors = image.depth() > 8 ? 256 : image.numColors();
650 unsigned char *segTbl = new unsigned char[segColors]; 642 unsigned char *segTbl = new unsigned char[segColors];
651 int pixels = image.depth() > 8 ? image.width()*image.height() : 643 int pixels = image.depth() > 8 ? image.width()*image.height() :
652 image.numColors(); 644 image.numColors();
653 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() : 645 unsigned int *data = image.depth() > 8 ? (unsigned int *)image.bits() :
654 (unsigned int *)image.colorTable(); 646 (unsigned int *)image.colorTable();
655 bool brighten = (percent >= 0); 647 bool brighten = (percent >= 0);
656 if(percent < 0) 648 if(percent < 0)
657 percent = -percent; 649 percent = -percent;
658 650
659 if(brighten){ // keep overflow check out of loops 651 if(brighten){ // keep overflow check out of loops
660 for(int i=0; i < segColors; ++i){ 652 for(int i=0; i < segColors; ++i){
661 int tmp = (int)(i*percent); 653 int tmp = (int)(i*percent);
662 if(tmp > 255) 654 if(tmp > 255)
663 tmp = 255; 655 tmp = 255;
664 segTbl[i] = tmp; 656 segTbl[i] = tmp;
665 } 657 }
666 } 658 }
667 else{ 659 else{
668 for(int i=0; i < segColors; ++i){ 660 for(int i=0; i < segColors; ++i){
669 int tmp = (int)(i*percent); 661 int tmp = (int)(i*percent);
670 if(tmp < 0) 662 if(tmp < 0)
671 tmp = 0; 663 tmp = 0;
672 segTbl[i] = tmp; 664 segTbl[i] = tmp;
673 } 665 }
674 } 666 }
675 667
676 if(brighten){ // same here 668 if(brighten){ // same here
677 if(channel == Red){ // and here ;-) 669 if(channel == Red){ // and here ;-)
678 for(int i=0; i < pixels; ++i){ 670 for(int i=0; i < pixels; ++i){
679 int c = qRed(data[i]); 671 int c = qRed(data[i]);
680 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 672 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
681 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i])); 673 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
682 } 674 }
683 } 675 }
684 if(channel == Green){ 676 if(channel == Green){
685 for(int i=0; i < pixels; ++i){ 677 for(int i=0; i < pixels; ++i){
686 int c = qGreen(data[i]); 678 int c = qGreen(data[i]);
687 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 679 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
688 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i])); 680 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
689 } 681 }
690 } 682 }
691 else{ 683 else{
692 for(int i=0; i < pixels; ++i){ 684 for(int i=0; i < pixels; ++i){
693 int c = qBlue(data[i]); 685 int c = qBlue(data[i]);
694 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c]; 686 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
695 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i])); 687 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
696 } 688 }
697 } 689 }
698 690
699 } 691 }
700 else{ 692 else{
701 if(channel == Red){ 693 if(channel == Red){
702 for(int i=0; i < pixels; ++i){ 694 for(int i=0; i < pixels; ++i){
703 int c = qRed(data[i]); 695 int c = qRed(data[i]);
704 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 696 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
705 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i])); 697 data[i] = qRgba(c, qGreen(data[i]), qBlue(data[i]), qAlpha(data[i]));
706 } 698 }
707 } 699 }
708 if(channel == Green){ 700 if(channel == Green){
709 for(int i=0; i < pixels; ++i){ 701 for(int i=0; i < pixels; ++i){
710 int c = qGreen(data[i]); 702 int c = qGreen(data[i]);
711 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 703 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
712 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i])); 704 data[i] = qRgba(qRed(data[i]), c, qBlue(data[i]), qAlpha(data[i]));
713 } 705 }
714 } 706 }
715 else{ 707 else{
716 for(int i=0; i < pixels; ++i){ 708 for(int i=0; i < pixels; ++i){
717 int c = qBlue(data[i]); 709 int c = qBlue(data[i]);
718 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c]; 710 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
719 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i])); 711 data[i] = qRgba(qRed(data[i]), qGreen(data[i]), c, qAlpha(data[i]));
720 } 712 }
721 } 713 }
722 } 714 }
723 delete [] segTbl; 715 delete [] segTbl;
724 716
725 return image; 717 return image;
726} 718}
727 719
728// Modulate an image with an RBG channel of another image 720// Modulate an image with an RBG channel of another image
729// 721//
730QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse, 722QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
731 ModulationType type, int factor, RGBComponent channel) 723 ModulationType type, int factor, RGBComponent channel)
732{ 724{
733 if (image.width() == 0 || image.height() == 0 || 725 if (image.width() == 0 || image.height() == 0 ||
734 modImage.width() == 0 || modImage.height() == 0) { 726 modImage.width() == 0 || modImage.height() == 0) {
735#ifndef NDEBUG 727 qDebug( "WARNING: OImageEffect::modulate : invalid image" );
736 cerr << "WARNING: OImageEffect::modulate : invalid image\n"; 728 return image;
737#endif
738 return image;
739 } 729 }
740 730
741 int r, g, b, h, s, v, a; 731 int r, g, b, h, s, v, a;
742 QColor clr; 732 QColor clr;
743 int mod=0; 733 int mod=0;
744 unsigned int x1, x2, y1, y2; 734 unsigned int x1, x2, y1, y2;
745 register int x, y; 735 register int x, y;
746 736
747 // for image, we handle only depth 32 737 // for image, we handle only depth 32
748 if (image.depth()<32) image = image.convertDepth(32); 738 if (image.depth()<32) image = image.convertDepth(32);
749 739
750 // for modImage, we handle depth 8 and 32 740 // for modImage, we handle depth 8 and 32
751 if (modImage.depth()<8) modImage = modImage.convertDepth(8); 741 if (modImage.depth()<8) modImage = modImage.convertDepth(8);
752 742
753 unsigned int *colorTable2 = (modImage.depth()==8) ? 743 unsigned int *colorTable2 = (modImage.depth()==8) ?
754 modImage.colorTable():0; 744 modImage.colorTable():0;
755 unsigned int *data1, *data2; 745 unsigned int *data1, *data2;
756 unsigned char *data2b; 746 unsigned char *data2b;
757 unsigned int color1, color2; 747 unsigned int color1, color2;
758 748
759 x1 = image.width(); y1 = image.height(); 749 x1 = image.width(); y1 = image.height();
760 x2 = modImage.width(); y2 = modImage.height(); 750 x2 = modImage.width(); y2 = modImage.height();
761 751
762 for (y = 0; y < (int)y1; y++) { 752 for (y = 0; y < (int)y1; y++) {
763 data1 = (unsigned int *) image.scanLine(y); 753 data1 = (unsigned int *) image.scanLine(y);
764 data2 = (unsigned int *) modImage.scanLine( y%y2 ); 754 data2 = (unsigned int *) modImage.scanLine( y%y2 );
765 data2b = (unsigned char *) modImage.scanLine( y%y2 ); 755 data2b = (unsigned char *) modImage.scanLine( y%y2 );
766 756
767 x=0; 757 x=0;
768 while(x < (int)x1) { 758 while(x < (int)x1) {
769 color2 = (colorTable2) ? colorTable2[*data2b] : *data2; 759 color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
770 if (reverse) { 760 if (reverse) {
771 color1 = color2; 761 color1 = color2;
772 color2 = *data1; 762 color2 = *data1;
773 } 763 }
774 else 764 else
775 color1 = *data1; 765 color1 = *data1;
776 766
777 if (type == Intensity || type == Contrast) { 767 if (type == Intensity || type == Contrast) {
778 r = qRed(color1); 768 r = qRed(color1);
779 g = qGreen(color1); 769 g = qGreen(color1);
780 b = qBlue(color1); 770 b = qBlue(color1);
781 if (channel != All) { 771 if (channel != All) {
782 mod = (channel == Red) ? qRed(color2) : 772 mod = (channel == Red) ? qRed(color2) :
783 (channel == Green) ? qGreen(color2) : 773 (channel == Green) ? qGreen(color2) :
784 (channel == Blue) ? qBlue(color2) : 774 (channel == Blue) ? qBlue(color2) :
785 (channel == Gray) ? qGray(color2) : 0; 775 (channel == Gray) ? qGray(color2) : 0;
786 mod = mod*factor/50; 776 mod = mod*factor/50;
@@ -815,197 +805,189 @@ QImage& OImageEffect::modulate(QImage &image, QImage &modImage, bool reverse,
815 if (g<0) g=0; if (g>255) g=255; 805 if (g<0) g=0; if (g>255) g=255;
816 if (b<0) b=0; if (b>255) b=255; 806 if (b<0) b=0; if (b>255) b=255;
817 a = qAlpha(*data1); 807 a = qAlpha(*data1);
818 *data1 = qRgba(r, g, b, a); 808 *data1 = qRgba(r, g, b, a);
819 } 809 }
820 else if (type == Saturation || type == HueShift) { 810 else if (type == Saturation || type == HueShift) {
821 clr.setRgb(color1); 811 clr.setRgb(color1);
822 clr.hsv(&h, &s, &v); 812 clr.hsv(&h, &s, &v);
823 mod = (channel == Red) ? qRed(color2) : 813 mod = (channel == Red) ? qRed(color2) :
824 (channel == Green) ? qGreen(color2) : 814 (channel == Green) ? qGreen(color2) :
825 (channel == Blue) ? qBlue(color2) : 815 (channel == Blue) ? qBlue(color2) :
826 (channel == Gray) ? qGray(color2) : 0; 816 (channel == Gray) ? qGray(color2) : 0;
827 mod = mod*factor/50; 817 mod = mod*factor/50;
828 818
829 if (type == Saturation) { 819 if (type == Saturation) {
830 s -= s * mod/256; 820 s -= s * mod/256;
831 if (s<0) s=0; if (s>255) s=255; 821 if (s<0) s=0; if (s>255) s=255;
832 } 822 }
833 else { // HueShift 823 else { // HueShift
834 h += mod; 824 h += mod;
835 while(h<0) h+=360; 825 while(h<0) h+=360;
836 h %= 360; 826 h %= 360;
837 } 827 }
838 828
839 clr.setHsv(h, s, v); 829 clr.setHsv(h, s, v);
840 a = qAlpha(*data1); 830 a = qAlpha(*data1);
841 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24); 831 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
842 } 832 }
843 data1++; data2++; data2b++; x++; 833 data1++; data2++; data2b++; x++;
844 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; } 834 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
845 } 835 }
846 } 836 }
847 return image; 837 return image;
848} 838}
849 839
850 840
851 841
852//====================================================================== 842//======================================================================
853// 843//
854// Blend effects 844// Blend effects
855// 845//
856//====================================================================== 846//======================================================================
857 847
858 848
859// Nice and fast direct pixel manipulation 849// Nice and fast direct pixel manipulation
860QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity) 850QImage& OImageEffect::blend(const QColor& clr, QImage& dst, float opacity)
861{ 851{
862 if (dst.width() <= 0 || dst.height() <= 0) 852 if (dst.width() <= 0 || dst.height() <= 0)
863 return dst; 853 return dst;
864 854
865 if (opacity < 0.0 || opacity > 1.0) { 855 if (opacity < 0.0 || opacity > 1.0) {
866#ifndef NDEBUG 856 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1] ");
867 cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n"; 857 return dst;
868#endif
869 return dst;
870 } 858 }
871 859
872 int depth = dst.depth(); 860 int depth = dst.depth();
873 if (depth != 32) 861 if (depth != 32)
874 dst = dst.convertDepth(32); 862 dst = dst.convertDepth(32);
875 863
876 int pixels = dst.width() * dst.height(); 864 int pixels = dst.width() * dst.height();
877 int rcol, gcol, bcol; 865 int rcol, gcol, bcol;
878 clr.rgb(&rcol, &gcol, &bcol); 866 clr.rgb(&rcol, &gcol, &bcol);
879 867
880#ifdef WORDS_BIGENDIAN // ARGB (skip alpha) 868#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
881 register unsigned char *data = (unsigned char *)dst.bits() + 1; 869 register unsigned char *data = (unsigned char *)dst.bits() + 1;
882#else // BGRA 870#else // BGRA
883 register unsigned char *data = (unsigned char *)dst.bits(); 871 register unsigned char *data = (unsigned char *)dst.bits();
884#endif 872#endif
885 873
886 for (register int i=0; i<pixels; i++) 874 for (register int i=0; i<pixels; i++)
887 { 875 {
888#ifdef WORDS_BIGENDIAN 876#ifdef WORDS_BIGENDIAN
889 *(data++) += (unsigned char)((rcol - *data) * opacity); 877 *(data++) += (unsigned char)((rcol - *data) * opacity);
890 *(data++) += (unsigned char)((gcol - *data) * opacity); 878 *(data++) += (unsigned char)((gcol - *data) * opacity);
891 *(data++) += (unsigned char)((bcol - *data) * opacity); 879 *(data++) += (unsigned char)((bcol - *data) * opacity);
892#else 880#else
893 *(data++) += (unsigned char)((bcol - *data) * opacity); 881 *(data++) += (unsigned char)((bcol - *data) * opacity);
894 *(data++) += (unsigned char)((gcol - *data) * opacity); 882 *(data++) += (unsigned char)((gcol - *data) * opacity);
895 *(data++) += (unsigned char)((rcol - *data) * opacity); 883 *(data++) += (unsigned char)((rcol - *data) * opacity);
896#endif 884#endif
897 data++; // skip alpha 885 data++; // skip alpha
898 } 886 }
899 return dst; 887 return dst;
900} 888}
901 889
902// Nice and fast direct pixel manipulation 890// Nice and fast direct pixel manipulation
903QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity) 891QImage& OImageEffect::blend(QImage& src, QImage& dst, float opacity)
904{ 892{
905 if (src.width() <= 0 || src.height() <= 0) 893 if (src.width() <= 0 || src.height() <= 0)
906 return dst; 894 return dst;
907 if (dst.width() <= 0 || dst.height() <= 0) 895 if (dst.width() <= 0 || dst.height() <= 0)
908 return dst; 896 return dst;
909 897
910 if (src.width() != dst.width() || src.height() != dst.height()) { 898 if (src.width() != dst.width() || src.height() != dst.height()) {
911#ifndef NDEBUG 899 qDebug( "WARNING: OImageEffect::blend : src and destination images are not the same size" );
912 cerr << "WARNING: OImageEffect::blend : src and destination images are not the same size\n"; 900 return dst;
913#endif
914 return dst;
915 } 901 }
916 902
917 if (opacity < 0.0 || opacity > 1.0) { 903 if (opacity < 0.0 || opacity > 1.0) {
918#ifndef NDEBUG 904 qDebug( "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]" );
919 cerr << "WARNING: OImageEffect::blend : invalid opacity. Range [0, 1]\n"; 905 return dst;
920#endif
921 return dst;
922 } 906 }
923 907
924 if (src.depth() != 32) src = src.convertDepth(32); 908 if (src.depth() != 32) src = src.convertDepth(32);
925 if (dst.depth() != 32) dst = dst.convertDepth(32); 909 if (dst.depth() != 32) dst = dst.convertDepth(32);
926 910
927 int pixels = src.width() * src.height(); 911 int pixels = src.width() * src.height();
928#ifdef WORDS_BIGENDIAN // ARGB (skip alpha) 912#ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
929 register unsigned char *data1 = (unsigned char *)dst.bits() + 1; 913 register unsigned char *data1 = (unsigned char *)dst.bits() + 1;
930 register unsigned char *data2 = (unsigned char *)src.bits() + 1; 914 register unsigned char *data2 = (unsigned char *)src.bits() + 1;
931#else // BGRA 915#else // BGRA
932 register unsigned char *data1 = (unsigned char *)dst.bits(); 916 register unsigned char *data1 = (unsigned char *)dst.bits();
933 register unsigned char *data2 = (unsigned char *)src.bits(); 917 register unsigned char *data2 = (unsigned char *)src.bits();
934#endif 918#endif
935 919
936 for (register int i=0; i<pixels; i++) 920 for (register int i=0; i<pixels; i++)
937 { 921 {
938#ifdef WORDS_BIGENDIAN 922#ifdef WORDS_BIGENDIAN
939 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 923 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
940 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 924 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
941 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 925 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
942#else 926#else
943 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 927 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
944 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 928 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
945 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity); 929 *(data1++) += (unsigned char)((*(data2++) - *data1) * opacity);
946#endif 930#endif
947 data1++; // skip alpha 931 data1++; // skip alpha
948 data2++; 932 data2++;
949 } 933 }
950 934
951 return dst; 935 return dst;
952} 936}
953 937
954 938
955QImage& OImageEffect::blend(QImage &image, float initial_intensity, 939QImage& OImageEffect::blend(QImage &image, float initial_intensity,
956 const QColor &bgnd, GradientType eff, 940 const QColor &bgnd, GradientType eff,
957 bool anti_dir) 941 bool anti_dir)
958{ 942{
959 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) { 943 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
960#ifndef NDEBUG 944 qDebug( "WARNING: OImageEffect::blend : invalid image" );
961 cerr << "WARNING: OImageEffect::blend : invalid image\n"; 945 return image;
962#endif
963 return image;
964 } 946 }
965 947
966 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue(); 948 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
967 int r, g, b; 949 int r, g, b;
968 int ind; 950 int ind;
969 951
970 unsigned int xi, xf, yi, yf; 952 unsigned int xi, xf, yi, yf;
971 unsigned int a; 953 unsigned int a;
972 954
973 // check the boundaries of the initial intesity param 955 // check the boundaries of the initial intesity param
974 float unaffected = 1; 956 float unaffected = 1;
975 if (initial_intensity > 1) initial_intensity = 1; 957 if (initial_intensity > 1) initial_intensity = 1;
976 if (initial_intensity < -1) initial_intensity = -1; 958 if (initial_intensity < -1) initial_intensity = -1;
977 if (initial_intensity < 0) { 959 if (initial_intensity < 0) {
978 unaffected = 1. + initial_intensity; 960 unaffected = 1. + initial_intensity;
979 initial_intensity = 0; 961 initial_intensity = 0;
980 } 962 }
981 963
982 964
983 float intensity = initial_intensity; 965 float intensity = initial_intensity;
984 float var = 1. - initial_intensity; 966 float var = 1. - initial_intensity;
985 967
986 if (anti_dir) { 968 if (anti_dir) {
987 initial_intensity = intensity = 1.; 969 initial_intensity = intensity = 1.;
988 var = -var; 970 var = -var;
989 } 971 }
990 972
991 register int x, y; 973 register int x, y;
992 974
993 unsigned int *data = (unsigned int *)image.bits(); 975 unsigned int *data = (unsigned int *)image.bits();
994 976
995 int image_width = image.width(); //Those can't change 977 int image_width = image.width(); //Those can't change
996 int image_height = image.height(); 978 int image_height = image.height();
997 979
998 980
999 if( eff == VerticalGradient || eff == HorizontalGradient ) { 981 if( eff == VerticalGradient || eff == HorizontalGradient ) {
1000 982
1001 // set the image domain to apply the effect to 983 // set the image domain to apply the effect to
1002 xi = 0, xf = image_width; 984 xi = 0, xf = image_width;
1003 yi = 0, yf = image_height; 985 yi = 0, yf = image_height;
1004 if (eff == VerticalGradient) { 986 if (eff == VerticalGradient) {
1005 if (anti_dir) yf = (int)(image_height * unaffected); 987 if (anti_dir) yf = (int)(image_height * unaffected);
1006 else yi = (int)(image_height * (1 - unaffected)); 988 else yi = (int)(image_height * (1 - unaffected));
1007 } 989 }
1008 else { 990 else {
1009 if (anti_dir) xf = (int)(image_width * unaffected); 991 if (anti_dir) xf = (int)(image_width * unaffected);
1010 else xi = (int)(image_height * (1 - unaffected)); 992 else xi = (int)(image_height * (1 - unaffected));
1011 } 993 }
@@ -1107,232 +1089,226 @@ QImage& OImageEffect::blend(QImage &image, float initial_intensity,
1107 data[ind] = qRgba(r, g, b, a); 1089 data[ind] = qRgba(r, g, b, a);
1108 } 1090 }
1109 } 1091 }
1110 1092
1111 //CT loop is doubled because of stupid central row/column issue. 1093 //CT loop is doubled because of stupid central row/column issue.
1112 // other solution? 1094 // other solution?
1113 for (x = 0; x < image_width / 2; x++) { 1095 for (x = 0; x < image_width / 2; x++) {
1114 xvar = var / image_width * (image_width - x*2/unaffected-1); 1096 xvar = var / image_width * (image_width - x*2/unaffected-1);
1115 for (y = 0; y < image_height / 2; y++) { 1097 for (y = 0; y < image_height / 2; y++) {
1116 yvar = var / image_height * (image_height - y*2/unaffected -1); 1098 yvar = var / image_height * (image_height - y*2/unaffected -1);
1117 1099
1118 if (eff == RectangleGradient) 1100 if (eff == RectangleGradient)
1119 intensity = initial_intensity + QMAX(xvar, yvar); 1101 intensity = initial_intensity + QMAX(xvar, yvar);
1120 else 1102 else
1121 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar); 1103 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1122 if (intensity > 1) intensity = 1; 1104 if (intensity > 1) intensity = 1;
1123 if (intensity < 0) intensity = 0; 1105 if (intensity < 0) intensity = 0;
1124 1106
1125 //SW 1107 //SW
1126 ind = x + image_width * (image_height - y -1) ; 1108 ind = x + image_width * (image_height - y -1) ;
1127 r = qRed (data[ind]) + (int)(intensity * 1109 r = qRed (data[ind]) + (int)(intensity *
1128 (r_bgnd - qRed (data[ind]))); 1110 (r_bgnd - qRed (data[ind])));
1129 g = qGreen(data[ind]) + (int)(intensity * 1111 g = qGreen(data[ind]) + (int)(intensity *
1130 (g_bgnd - qGreen(data[ind]))); 1112 (g_bgnd - qGreen(data[ind])));
1131 b = qBlue (data[ind]) + (int)(intensity * 1113 b = qBlue (data[ind]) + (int)(intensity *
1132 (b_bgnd - qBlue (data[ind]))); 1114 (b_bgnd - qBlue (data[ind])));
1133 if (r > 255) r = 255; if (r < 0 ) r = 0; 1115 if (r > 255) r = 255; if (r < 0 ) r = 0;
1134 if (g > 255) g = 255; if (g < 0 ) g = 0; 1116 if (g > 255) g = 255; if (g < 0 ) g = 0;
1135 if (b > 255) b = 255; if (b < 0 ) b = 0; 1117 if (b > 255) b = 255; if (b < 0 ) b = 0;
1136 a = qAlpha(data[ind]); 1118 a = qAlpha(data[ind]);
1137 data[ind] = qRgba(r, g, b, a); 1119 data[ind] = qRgba(r, g, b, a);
1138 1120
1139 //SE 1121 //SE
1140 ind = image_width-x-1 + image_width * (image_height - y - 1) ; 1122 ind = image_width-x-1 + image_width * (image_height - y - 1) ;
1141 r = qRed (data[ind]) + (int)(intensity * 1123 r = qRed (data[ind]) + (int)(intensity *
1142 (r_bgnd - qRed (data[ind]))); 1124 (r_bgnd - qRed (data[ind])));
1143 g = qGreen(data[ind]) + (int)(intensity * 1125 g = qGreen(data[ind]) + (int)(intensity *
1144 (g_bgnd - qGreen(data[ind]))); 1126 (g_bgnd - qGreen(data[ind])));
1145 b = qBlue (data[ind]) + (int)(intensity * 1127 b = qBlue (data[ind]) + (int)(intensity *
1146 (b_bgnd - qBlue (data[ind]))); 1128 (b_bgnd - qBlue (data[ind])));
1147 if (r > 255) r = 255; if (r < 0 ) r = 0; 1129 if (r > 255) r = 255; if (r < 0 ) r = 0;
1148 if (g > 255) g = 255; if (g < 0 ) g = 0; 1130 if (g > 255) g = 255; if (g < 0 ) g = 0;
1149 if (b > 255) b = 255; if (b < 0 ) b = 0; 1131 if (b > 255) b = 255; if (b < 0 ) b = 0;
1150 a = qAlpha(data[ind]); 1132 a = qAlpha(data[ind]);
1151 data[ind] = qRgba(r, g, b, a); 1133 data[ind] = qRgba(r, g, b, a);
1152 } 1134 }
1153 } 1135 }
1154 } 1136 }
1155#ifndef NDEBUG 1137 else qDebug( "OImageEffect::blend effect not implemented" );
1156 else cerr << "OImageEffect::blend effect not implemented" << endl;
1157#endif
1158 return image; 1138 return image;
1159} 1139}
1160 1140
1161// Not very efficient as we create a third big image... 1141// Not very efficient as we create a third big image...
1162// 1142//
1163QImage& OImageEffect::blend(QImage &image1, QImage &image2, 1143QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1164 GradientType gt, int xf, int yf) 1144 GradientType gt, int xf, int yf)
1165{ 1145{
1166 if (image1.width() == 0 || image1.height() == 0 || 1146 if (image1.width() == 0 || image1.height() == 0 ||
1167 image2.width() == 0 || image2.height() == 0) 1147 image2.width() == 0 || image2.height() == 0)
1168 return image1; 1148 return image1;
1169 1149
1170 QImage image3; 1150 QImage image3;
1171 1151
1172 image3 = OImageEffect::unbalancedGradient(image1.size(), 1152 image3 = OImageEffect::unbalancedGradient(image1.size(),
1173 QColor(0,0,0), QColor(255,255,255), 1153 QColor(0,0,0), QColor(255,255,255),
1174 gt, xf, yf, 0); 1154 gt, xf, yf, 0);
1175 1155
1176 return blend(image1,image2,image3, Red); // Channel to use is arbitrary 1156 return blend(image1,image2,image3, Red); // Channel to use is arbitrary
1177} 1157}
1178 1158
1179// Blend image2 into image1, using an RBG channel of blendImage 1159// Blend image2 into image1, using an RBG channel of blendImage
1180// 1160//
1181QImage& OImageEffect::blend(QImage &image1, QImage &image2, 1161QImage& OImageEffect::blend(QImage &image1, QImage &image2,
1182 QImage &blendImage, RGBComponent channel) 1162 QImage &blendImage, RGBComponent channel)
1183{ 1163{
1184 if (image1.width() == 0 || image1.height() == 0 || 1164 if (image1.width() == 0 || image1.height() == 0 ||
1185 image2.width() == 0 || image2.height() == 0 || 1165 image2.width() == 0 || image2.height() == 0 ||
1186 blendImage.width() == 0 || blendImage.height() == 0) { 1166 blendImage.width() == 0 || blendImage.height() == 0) {
1187#ifndef NDEBUG 1167 qDebug( "OImageEffect::blend effect invalid image" );
1188 cerr << "OImageEffect::blend effect invalid image" << endl; 1168 return image1;
1189#endif
1190 return image1;
1191 } 1169 }
1192 1170
1193 int r, g, b; 1171 int r, g, b;
1194 int ind1, ind2, ind3; 1172 int ind1, ind2, ind3;
1195 1173
1196 unsigned int x1, x2, x3, y1, y2, y3; 1174 unsigned int x1, x2, x3, y1, y2, y3;
1197 unsigned int a; 1175 unsigned int a;
1198 1176
1199 register int x, y; 1177 register int x, y;
1200 1178
1201 // for image1 and image2, we only handle depth 32 1179 // for image1 and image2, we only handle depth 32
1202 if (image1.depth()<32) image1 = image1.convertDepth(32); 1180 if (image1.depth()<32) image1 = image1.convertDepth(32);
1203 if (image2.depth()<32) image2 = image2.convertDepth(32); 1181 if (image2.depth()<32) image2 = image2.convertDepth(32);
1204 1182
1205 // for blendImage, we handle depth 8 and 32 1183 // for blendImage, we handle depth 8 and 32
1206 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8); 1184 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
1207 1185
1208 unsigned int *colorTable3 = (blendImage.depth()==8) ? 1186 unsigned int *colorTable3 = (blendImage.depth()==8) ?
1209 blendImage.colorTable():0; 1187 blendImage.colorTable():0;
1210 1188
1211 unsigned int *data1 = (unsigned int *)image1.bits(); 1189 unsigned int *data1 = (unsigned int *)image1.bits();
1212 unsigned int *data2 = (unsigned int *)image2.bits(); 1190 unsigned int *data2 = (unsigned int *)image2.bits();
1213 unsigned int *data3 = (unsigned int *)blendImage.bits(); 1191 unsigned int *data3 = (unsigned int *)blendImage.bits();
1214 unsigned char *data3b = (unsigned char *)blendImage.bits(); 1192 unsigned char *data3b = (unsigned char *)blendImage.bits();
1215 unsigned int color3; 1193 unsigned int color3;
1216 1194
1217 x1 = image1.width(); y1 = image1.height(); 1195 x1 = image1.width(); y1 = image1.height();
1218 x2 = image2.width(); y2 = image2.height(); 1196 x2 = image2.width(); y2 = image2.height();
1219 x3 = blendImage.width(); y3 = blendImage.height(); 1197 x3 = blendImage.width(); y3 = blendImage.height();
1220 1198
1221 for (y = 0; y < (int)y1; y++) { 1199 for (y = 0; y < (int)y1; y++) {
1222 ind1 = x1*y; 1200 ind1 = x1*y;
1223 ind2 = x2*(y%y2); 1201 ind2 = x2*(y%y2);
1224 ind3 = x3*(y%y3); 1202 ind3 = x3*(y%y3);
1225 1203
1226 x=0; 1204 x=0;
1227 while(x < (int)x1) { 1205 while(x < (int)x1) {
1228 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3]; 1206 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
1229 1207
1230 a = (channel == Red) ? qRed(color3) : 1208 a = (channel == Red) ? qRed(color3) :
1231 (channel == Green) ? qGreen(color3) : 1209 (channel == Green) ? qGreen(color3) :
1232 (channel == Blue) ? qBlue(color3) : qGray(color3); 1210 (channel == Blue) ? qBlue(color3) : qGray(color3);
1233 1211
1234 r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256; 1212 r = (a*qRed(data1[ind1]) + (256-a)*qRed(data2[ind2]))/256;
1235 g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256; 1213 g = (a*qGreen(data1[ind1]) + (256-a)*qGreen(data2[ind2]))/256;
1236 b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256; 1214 b = (a*qBlue(data1[ind1]) + (256-a)*qBlue(data2[ind2]))/256;
1237 1215
1238 a = qAlpha(data1[ind1]); 1216 a = qAlpha(data1[ind1]);
1239 data1[ind1] = qRgba(r, g, b, a); 1217 data1[ind1] = qRgba(r, g, b, a);
1240 1218
1241 ind1++; ind2++; ind3++; x++; 1219 ind1++; ind2++; ind3++; x++;
1242 if ( (x%x2) ==0) ind2 -= x2; 1220 if ( (x%x2) ==0) ind2 -= x2;
1243 if ( (x%x3) ==0) ind3 -= x3; 1221 if ( (x%x3) ==0) ind3 -= x3;
1244 } 1222 }
1245 } 1223 }
1246 return image1; 1224 return image1;
1247} 1225}
1248 1226
1249 1227
1250//====================================================================== 1228//======================================================================
1251// 1229//
1252// Hash effects 1230// Hash effects
1253// 1231//
1254//====================================================================== 1232//======================================================================
1255 1233
1256unsigned int OImageEffect::lHash(unsigned int c) 1234unsigned int OImageEffect::lHash(unsigned int c)
1257{ 1235{
1258 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c); 1236 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1259 unsigned char nr, ng, nb; 1237 unsigned char nr, ng, nb;
1260 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr; 1238 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
1261 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng; 1239 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
1262 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb; 1240 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
1263 1241
1264 return qRgba(nr, ng, nb, a); 1242 return qRgba(nr, ng, nb, a);
1265} 1243}
1266 1244
1267 1245
1268// ----------------------------------------------------------------------------- 1246// -----------------------------------------------------------------------------
1269 1247
1270unsigned int OImageEffect::uHash(unsigned int c) 1248unsigned int OImageEffect::uHash(unsigned int c)
1271{ 1249{
1272 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c); 1250 unsigned char r = qRed(c), g = qGreen(c), b = qBlue(c), a = qAlpha(c);
1273 unsigned char nr, ng, nb; 1251 unsigned char nr, ng, nb;
1274 nr = r + (r >> 3); nr = nr < r ? ~0 : nr; 1252 nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
1275 ng = g + (g >> 3); ng = ng < g ? ~0 : ng; 1253 ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
1276 nb = b + (b >> 3); nb = nb < b ? ~0 : nb; 1254 nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
1277 1255
1278 return qRgba(nr, ng, nb, a); 1256 return qRgba(nr, ng, nb, a);
1279} 1257}
1280 1258
1281 1259
1282// ----------------------------------------------------------------------------- 1260// -----------------------------------------------------------------------------
1283 1261
1284QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing) 1262QImage& OImageEffect::hash(QImage &image, Lighting lite, unsigned int spacing)
1285{ 1263{
1286 if (image.width() == 0 || image.height() == 0) { 1264 if (image.width() == 0 || image.height() == 0) {
1287#ifndef NDEBUG 1265 qDebug( "OImageEffect::hash effect invalid image" );
1288 cerr << "OImageEffect::hash effect invalid image" << endl; 1266 return image;
1289#endif
1290 return image;
1291 } 1267 }
1292 1268
1293 register int x, y; 1269 register int x, y;
1294 unsigned int *data = (unsigned int *)image.bits(); 1270 unsigned int *data = (unsigned int *)image.bits();
1295 unsigned int ind; 1271 unsigned int ind;
1296 1272
1297 //CT no need to do it if not enough space 1273 //CT no need to do it if not enough space
1298 if ((lite == NorthLite || 1274 if ((lite == NorthLite ||
1299 lite == SouthLite)&& 1275 lite == SouthLite)&&
1300 (unsigned)image.height() < 2+spacing) return image; 1276 (unsigned)image.height() < 2+spacing) return image;
1301 if ((lite == EastLite || 1277 if ((lite == EastLite ||
1302 lite == WestLite)&& 1278 lite == WestLite)&&
1303 (unsigned)image.height() < 2+spacing) return image; 1279 (unsigned)image.height() < 2+spacing) return image;
1304 1280
1305 if (lite == NorthLite || lite == SouthLite) { 1281 if (lite == NorthLite || lite == SouthLite) {
1306 for (y = 0 ; y < image.height(); y = y + 2 + spacing) { 1282 for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
1307 for (x = 0; x < image.width(); x++) { 1283 for (x = 0; x < image.width(); x++) {
1308 ind = x + image.width() * y; 1284 ind = x + image.width() * y;
1309 data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]); 1285 data[ind] = lite==NorthLite?uHash(data[ind]):lHash(data[ind]);
1310 1286
1311 ind = ind + image.width(); 1287 ind = ind + image.width();
1312 data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]); 1288 data[ind] = lite==NorthLite?lHash(data[ind]):uHash(data[ind]);
1313 } 1289 }
1314 } 1290 }
1315 } 1291 }
1316 1292
1317 else if (lite == EastLite || lite == WestLite) { 1293 else if (lite == EastLite || lite == WestLite) {
1318 for (y = 0 ; y < image.height(); y++) { 1294 for (y = 0 ; y < image.height(); y++) {
1319 for (x = 0; x < image.width(); x = x + 2 + spacing) { 1295 for (x = 0; x < image.width(); x = x + 2 + spacing) {
1320 ind = x + image.width() * y; 1296 ind = x + image.width() * y;
1321 data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]); 1297 data[ind] = lite==EastLite?uHash(data[ind]):lHash(data[ind]);
1322 1298
1323 ind++; 1299 ind++;
1324 data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]); 1300 data[ind] = lite==EastLite?lHash(data[ind]):uHash(data[ind]);
1325 } 1301 }
1326 } 1302 }
1327 } 1303 }
1328 1304
1329 else if (lite == NWLite || lite == SELite) { 1305 else if (lite == NWLite || lite == SELite) {
1330 for (y = 0 ; y < image.height(); y++) { 1306 for (y = 0 ; y < image.height(); y++) {
1331 for (x = 0; 1307 for (x = 0;
1332 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing); 1308 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
1333 x = x + 2 + spacing) { 1309 x = x + 2 + spacing) {
1334 ind = x + image.width() * y + ((y & 1)? 1 : 0); 1310 ind = x + image.width() * y + ((y & 1)? 1 : 0);
1335 data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]); 1311 data[ind] = lite==NWLite?uHash(data[ind]):lHash(data[ind]);
1336 1312
1337 ind++; 1313 ind++;
1338 data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]); 1314 data[ind] = lite==NWLite?lHash(data[ind]):uHash(data[ind]);
@@ -1749,100 +1725,98 @@ QImage& OImageEffect::dither(QImage &img, const QColor *palette, int size)
1749 1725
1750 img = dImage; 1726 img = dImage;
1751 return img; 1727 return img;
1752} 1728}
1753 1729
1754int OImageEffect::nearestColor( int r, int g, int b, const QColor *palette, int size ) 1730int OImageEffect::nearestColor( int r, int g, int b, const QColor *palette, int size )
1755{ 1731{
1756 if (palette == 0) 1732 if (palette == 0)
1757 return 0; 1733 return 0;
1758 1734
1759 int dr = palette[0].red() - r; 1735 int dr = palette[0].red() - r;
1760 int dg = palette[0].green() - g; 1736 int dg = palette[0].green() - g;
1761 int db = palette[0].blue() - b; 1737 int db = palette[0].blue() - b;
1762 1738
1763 int minDist = dr*dr + dg*dg + db*db; 1739 int minDist = dr*dr + dg*dg + db*db;
1764 int nearest = 0; 1740 int nearest = 0;
1765 1741
1766 for (int i = 1; i < size; i++ ) 1742 for (int i = 1; i < size; i++ )
1767 { 1743 {
1768 dr = palette[i].red() - r; 1744 dr = palette[i].red() - r;
1769 dg = palette[i].green() - g; 1745 dg = palette[i].green() - g;
1770 db = palette[i].blue() - b; 1746 db = palette[i].blue() - b;
1771 1747
1772 int dist = dr*dr + dg*dg + db*db; 1748 int dist = dr*dr + dg*dg + db*db;
1773 1749
1774 if ( dist < minDist ) 1750 if ( dist < minDist )
1775 { 1751 {
1776 minDist = dist; 1752 minDist = dist;
1777 nearest = i; 1753 nearest = i;
1778 } 1754 }
1779 } 1755 }
1780 1756
1781 return nearest; 1757 return nearest;
1782} 1758}
1783 1759
1784bool OImageEffect::blend( 1760bool OImageEffect::blend(
1785 const QImage & upper, 1761 const QImage & upper,
1786 const QImage & lower, 1762 const QImage & lower,
1787 QImage & output 1763 QImage & output
1788) 1764)
1789{ 1765{
1790 if ( 1766 if (
1791 upper.width() > lower.width() || 1767 upper.width() > lower.width() ||
1792 upper.height() > lower.height() || 1768 upper.height() > lower.height() ||
1793 upper.depth() != 32 || 1769 upper.depth() != 32 ||
1794 lower.depth() != 32 1770 lower.depth() != 32
1795 ) 1771 )
1796 { 1772 {
1797#ifndef NDEBUG 1773 qDebug( "OImageEffect::blend : Sizes not correct" );
1798 cerr << "OImageEffect::blend : Sizes not correct\n" ; 1774 return false;
1799#endif
1800 return false;
1801 } 1775 }
1802 1776
1803 output = lower.copy(); 1777 output = lower.copy();
1804 1778
1805 register uchar *i, *o; 1779 register uchar *i, *o;
1806 register int a; 1780 register int a;
1807 register int col; 1781 register int col;
1808 register int w = upper.width(); 1782 register int w = upper.width();
1809 int row(upper.height() - 1); 1783 int row(upper.height() - 1);
1810 1784
1811 do { 1785 do {
1812 1786
1813 i = upper.scanLine(row); 1787 i = upper.scanLine(row);
1814 o = output.scanLine(row); 1788 o = output.scanLine(row);
1815 1789
1816 col = w << 2; 1790 col = w << 2;
1817 --col; 1791 --col;
1818 1792
1819 do { 1793 do {
1820 1794
1821 while (!(a = i[col]) && (col != 3)) { 1795 while (!(a = i[col]) && (col != 3)) {
1822 --col; --col; --col; --col; 1796 --col; --col; --col; --col;
1823 } 1797 }
1824 1798
1825 --col; 1799 --col;
1826 o[col] += ((i[col] - o[col]) * a) >> 8; 1800 o[col] += ((i[col] - o[col]) * a) >> 8;
1827 1801
1828 --col; 1802 --col;
1829 o[col] += ((i[col] - o[col]) * a) >> 8; 1803 o[col] += ((i[col] - o[col]) * a) >> 8;
1830 1804
1831 --col; 1805 --col;
1832 o[col] += ((i[col] - o[col]) * a) >> 8; 1806 o[col] += ((i[col] - o[col]) * a) >> 8;
1833 1807
1834 } while (col--); 1808 } while (col--);
1835 1809
1836 } while (row--); 1810 } while (row--);
1837 1811
1838 return true; 1812 return true;
1839} 1813}
1840 1814
1841#if 0 1815#if 0
1842// Not yet... 1816// Not yet...
1843bool OImageEffect::blend( 1817bool OImageEffect::blend(
1844 const QImage & upper, 1818 const QImage & upper,
1845 const QImage & lower, 1819 const QImage & lower,
1846 QImage & output, 1820 QImage & output,
1847 const QRect & destRect 1821 const QRect & destRect
1848) 1822)