41 #include "kimageeffect.h"
49 #if defined(__i386__) && ( defined(__GNUC__) || defined(__INTEL_COMPILER) )
50 # if defined( HAVE_X86_MMX )
51 # define USE_MMX_INLINE_ASM
53 # if defined( HAVE_X86_SSE2 )
54 # define USE_SSE2_INLINE_ASM
65 #define DegreesToRadians(x) ((x)*M_PI/180.0)
66 #define MagickSQ2PI 2.50662827463100024161235523934010416269302368164062
67 #define MagickEpsilon 1.0e-12
68 #define MagickPI 3.14159265358979323846264338327950288419716939937510
69 #define MOD(x, y) ((x) < 0 ? ((y) - 1 - ((y) - 1 - (x)) % (y)) : (x) % (y))
76 #define FXCLAMP(x,low,high) fxClamp(x,low,high)
78 inline const T& fxClamp(
const T& x,
const T& low,
const T& high )
80 if ( x < low )
return low;
81 else if ( x > high )
return high;
85 static inline unsigned int intensityValue(
unsigned int color)
87 return((
unsigned int)((0.299*tqRed(color) +
88 0.587*tqGreen(color) +
89 0.1140000000000001*tqBlue(color))));
93 static inline void liberateMemory(T **memory)
95 assert(memory != NULL);
96 if(*memory == NULL)
return;
111 unsigned short int red;
112 unsigned short int green;
113 unsigned short int blue;
114 unsigned short int alpha;
127 int rDiff, gDiff, bDiff;
128 int rca, gca, bca, rcb, gcb, bcb;
130 TQImage image(size, 32);
132 if (size.width() == 0 || size.height() == 0) {
134 std::cerr <<
"WARNING: KImageEffect::gradient: invalid image" <<
std::endl;
141 rDiff = (rcb = cb.red()) - (rca = ca.red());
142 gDiff = (gcb = cb.green()) - (gca = ca.green());
143 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
145 if( eff == VerticalGradient || eff == HorizontalGradient ){
154 if( eff == VerticalGradient ) {
156 int rcdelta = ((1<<16) / size.height()) * rDiff;
157 int gcdelta = ((1<<16) / size.height()) * gDiff;
158 int bcdelta = ((1<<16) / size.height()) * bDiff;
160 for ( y = 0; y < size.height(); y++ ) {
161 p = (uint *) image.scanLine(y);
167 rgb = tqRgb( (rl>>16), (gl>>16), (bl>>16) );
169 for( x = 0; x < size.width(); x++ ) {
178 unsigned int *o_src = (
unsigned int *)image.scanLine(0);
179 unsigned int *src = o_src;
181 int rcdelta = ((1<<16) / size.width()) * rDiff;
182 int gcdelta = ((1<<16) / size.width()) * gDiff;
183 int bcdelta = ((1<<16) / size.width()) * bDiff;
185 for( x = 0; x < size.width(); x++) {
191 *src++ = tqRgb( (rl>>16), (gl>>16), (bl>>16));
200 for (y = 1; y < size.height(); ++y) {
202 p = (
unsigned int *)image.scanLine(y);
204 for(x=0; x < size.width(); ++x)
213 float rd = rca, gd = gca, bd = bca;
215 unsigned char *xtable[3];
216 unsigned char *ytable[3];
218 unsigned int w = size.width(), h = size.height();
219 xtable[0] =
new unsigned char[w];
220 xtable[1] =
new unsigned char[w];
221 xtable[2] =
new unsigned char[w];
222 ytable[0] =
new unsigned char[h];
223 ytable[1] =
new unsigned char[h];
224 ytable[2] =
new unsigned char[h];
227 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
232 rfd = (float)rDiff/w;
233 gfd = (float)gDiff/w;
234 bfd = (float)bDiff/w;
237 for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
238 dir = eff == DiagonalGradient? x : size.width() - x - 1;
239 xtable[0][dir] = (
unsigned char) rd;
240 xtable[1][dir] = (
unsigned char) gd;
241 xtable[2][dir] = (
unsigned char) bd;
243 rfd = (float)rDiff/h;
244 gfd = (float)gDiff/h;
245 bfd = (float)bDiff/h;
247 for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
248 ytable[0][y] = (
unsigned char) rd;
249 ytable[1][y] = (
unsigned char) gd;
250 ytable[2][y] = (
unsigned char) bd;
253 for (y = 0; y < size.height(); y++) {
254 unsigned int *scanline = (
unsigned int *)image.scanLine(y);
255 for (x = 0; x < size.width(); x++) {
256 scanline[x] = tqRgb(xtable[0][x] + ytable[0][y],
257 xtable[1][x] + ytable[1][y],
258 xtable[2][x] + ytable[2][y]);
263 else if (eff == RectangleGradient ||
264 eff == PyramidGradient ||
265 eff == PipeCrossGradient ||
266 eff == EllipticGradient)
268 int rSign = rDiff>0? 1: -1;
269 int gSign = gDiff>0? 1: -1;
270 int bSign = bDiff>0? 1: -1;
272 rfd = (float)rDiff / size.width();
273 gfd = (float)gDiff / size.width();
274 bfd = (float)bDiff / size.width();
280 for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
282 xtable[0][x] = (
unsigned char) abs((
int)rd);
283 xtable[1][x] = (
unsigned char) abs((
int)gd);
284 xtable[2][x] = (
unsigned char) abs((
int)bd);
287 rfd = (float)rDiff/size.height();
288 gfd = (float)gDiff/size.height();
289 bfd = (float)bDiff/size.height();
295 for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
297 ytable[0][y] = (
unsigned char) abs((
int)rd);
298 ytable[1][y] = (
unsigned char) abs((
int)gd);
299 ytable[2][y] = (
unsigned char) abs((
int)bd);
302 int h = (size.height()+1)>>1;
303 for (y = 0; y < h; y++) {
304 unsigned int *sl1 = (
unsigned int *)image.scanLine(y);
305 unsigned int *sl2 = (
unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
307 int w = (size.width()+1)>>1;
308 int x2 = size.width()-1;
310 for (x = 0; x < w; x++, x2--) {
311 unsigned int rgb = 0;
312 if (eff == PyramidGradient) {
313 rgb = tqRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
314 gcb-gSign*(xtable[1][x]+ytable[1][y]),
315 bcb-bSign*(xtable[2][x]+ytable[2][y]));
317 if (eff == RectangleGradient) {
318 rgb = tqRgb(rcb - rSign *
319 QMAX(xtable[0][x], ytable[0][y]) * 2,
321 QMAX(xtable[1][x], ytable[1][y]) * 2,
323 QMAX(xtable[2][x], ytable[2][y]) * 2);
325 if (eff == PipeCrossGradient) {
326 rgb = tqRgb(rcb - rSign *
327 QMIN(xtable[0][x], ytable[0][y]) * 2,
329 QMIN(xtable[1][x], ytable[1][y]) * 2,
331 QMIN(xtable[2][x], ytable[2][y]) * 2);
333 if (eff == EllipticGradient) {
334 rgb = tqRgb(rcb - rSign *
335 (
int)sqrt((xtable[0][x]*xtable[0][x] +
336 ytable[0][y]*ytable[0][y])*2.0),
338 (
int)sqrt((xtable[1][x]*xtable[1][x] +
339 ytable[1][y]*ytable[1][y])*2.0),
341 (
int)sqrt((xtable[2][x]*xtable[2][x] +
342 ytable[2][y]*ytable[2][y])*2.0));
345 sl1[x] = sl2[x] = rgb;
346 sl1[x2] = sl2[x2] = rgb;
360 if (ncols && (TQPixmap::defaultDepth() < 15 )) {
361 if ( ncols < 2 || ncols > 256 )
363 TQColor *dPal =
new TQColor[ncols];
364 for (
int i=0; i<ncols; i++) {
365 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
366 gca + gDiff * i / ( ncols - 1 ),
367 bca + bDiff * i / ( ncols - 1 ) );
369 dither(image, dPal, ncols);
389 const TQColor &cb,
GradientType eff,
int xfactor,
int yfactor,
394 bool _xanti = false , _yanti =
false;
396 if (xfactor < 0) _xanti =
true;
397 if (yfactor < 0) _yanti =
true;
399 xfactor = abs(xfactor);
400 yfactor = abs(yfactor);
402 if (!xfactor) xfactor = 1;
403 if (!yfactor) yfactor = 1;
405 if (xfactor > 200 ) xfactor = 200;
406 if (yfactor > 200 ) yfactor = 200;
411 float xbal = xfactor/30./size.width();
412 float ybal = yfactor/30./size.height();
415 int rDiff, gDiff, bDiff;
416 int rca, gca, bca, rcb, gcb, bcb;
418 TQImage image(size, 32);
420 if (size.width() == 0 || size.height() == 0) {
422 std::cerr <<
"WARNING: KImageEffect::unbalancedGradient : invalid image\n";
428 unsigned int *scanline;
430 rDiff = (rcb = cb.red()) - (rca = ca.red());
431 gDiff = (gcb = cb.green()) - (gca = ca.green());
432 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
434 if( eff == VerticalGradient || eff == HorizontalGradient){
440 if( eff == VerticalGradient) {
441 for ( y = 0; y < size.height(); y++ ) {
442 dir = _yanti ? y : size.height() - 1 - y;
443 p = (uint *) image.scanLine(dir);
444 rat = 1 - exp( - (
float)y * ybal );
446 cRow.setRgb( rcb - (
int) ( rDiff * rat ),
447 gcb - (
int) ( gDiff * rat ),
448 bcb - (
int) ( bDiff * rat ) );
452 for( x = 0; x < size.width(); x++ ) {
460 unsigned int *src = (
unsigned int *)image.scanLine(0);
461 for(x = 0; x < size.width(); x++ )
463 dir = _xanti ? x : size.width() - 1 - x;
464 rat = 1 - exp( - (
float)x * xbal );
466 src[dir] = tqRgb(rcb - (
int) ( rDiff * rat ),
467 gcb - (
int) ( gDiff * rat ),
468 bcb - (
int) ( bDiff * rat ));
475 for(y = 1; y < size.height(); ++y)
477 scanline = (
unsigned int *)image.scanLine(y);
478 for(x=0; x < size.width(); ++x)
479 scanline[x] = src[x];
485 int w=size.width(), h=size.height();
487 unsigned char *xtable[3];
488 unsigned char *ytable[3];
489 xtable[0] =
new unsigned char[w];
490 xtable[1] =
new unsigned char[w];
491 xtable[2] =
new unsigned char[w];
492 ytable[0] =
new unsigned char[h];
493 ytable[1] =
new unsigned char[h];
494 ytable[2] =
new unsigned char[h];
496 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient)
498 for (x = 0; x < w; x++) {
499 dir = _xanti ? x : w - 1 - x;
500 rat = 1 - exp( - (
float)x * xbal );
502 xtable[0][dir] = (
unsigned char) ( rDiff/2 * rat );
503 xtable[1][dir] = (
unsigned char) ( gDiff/2 * rat );
504 xtable[2][dir] = (
unsigned char) ( bDiff/2 * rat );
507 for (y = 0; y < h; y++) {
508 dir = _yanti ? y : h - 1 - y;
509 rat = 1 - exp( - (
float)y * ybal );
511 ytable[0][dir] = (
unsigned char) ( rDiff/2 * rat );
512 ytable[1][dir] = (
unsigned char) ( gDiff/2 * rat );
513 ytable[2][dir] = (
unsigned char) ( bDiff/2 * rat );
516 for (y = 0; y < h; y++) {
517 unsigned int *scanline = (
unsigned int *)image.scanLine(y);
518 for (x = 0; x < w; x++) {
519 scanline[x] = tqRgb(rcb - (xtable[0][x] + ytable[0][y]),
520 gcb - (xtable[1][x] + ytable[1][y]),
521 bcb - (xtable[2][x] + ytable[2][y]));
526 else if (eff == RectangleGradient ||
527 eff == PyramidGradient ||
528 eff == PipeCrossGradient ||
529 eff == EllipticGradient)
531 int rSign = rDiff>0? 1: -1;
532 int gSign = gDiff>0? 1: -1;
533 int bSign = bDiff>0? 1: -1;
535 for (x = 0; x < w; x++)
537 dir = _xanti ? x : w - 1 - x;
538 rat = 1 - exp( - (
float)x * xbal );
540 xtable[0][dir] = (
unsigned char) abs((
int)(rDiff*(0.5-rat)));
541 xtable[1][dir] = (
unsigned char) abs((
int)(gDiff*(0.5-rat)));
542 xtable[2][dir] = (
unsigned char) abs((
int)(bDiff*(0.5-rat)));
545 for (y = 0; y < h; y++)
547 dir = _yanti ? y : h - 1 - y;
549 rat = 1 - exp( - (
float)y * ybal );
551 ytable[0][dir] = (
unsigned char) abs((
int)(rDiff*(0.5-rat)));
552 ytable[1][dir] = (
unsigned char) abs((
int)(gDiff*(0.5-rat)));
553 ytable[2][dir] = (
unsigned char) abs((
int)(bDiff*(0.5-rat)));
556 for (y = 0; y < h; y++) {
557 unsigned int *scanline = (
unsigned int *)image.scanLine(y);
558 for (x = 0; x < w; x++) {
559 if (eff == PyramidGradient)
561 scanline[x] = tqRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
562 gcb-gSign*(xtable[1][x]+ytable[1][y]),
563 bcb-bSign*(xtable[2][x]+ytable[2][y]));
565 else if (eff == RectangleGradient)
567 scanline[x] = tqRgb(rcb - rSign *
568 QMAX(xtable[0][x], ytable[0][y]) * 2,
570 QMAX(xtable[1][x], ytable[1][y]) * 2,
572 QMAX(xtable[2][x], ytable[2][y]) * 2);
574 else if (eff == PipeCrossGradient)
576 scanline[x] = tqRgb(rcb - rSign *
577 QMIN(xtable[0][x], ytable[0][y]) * 2,
579 QMIN(xtable[1][x], ytable[1][y]) * 2,
581 QMIN(xtable[2][x], ytable[2][y]) * 2);
583 else if (eff == EllipticGradient)
585 scanline[x] = tqRgb(rcb - rSign *
586 (
int)sqrt((xtable[0][x]*xtable[0][x] +
587 ytable[0][y]*ytable[0][y])*2.0),
589 (
int)sqrt((xtable[1][x]*xtable[1][x] +
590 ytable[1][y]*ytable[1][y])*2.0),
592 (
int)sqrt((xtable[2][x]*xtable[2][x] +
593 ytable[2][y]*ytable[2][y])*2.0));
599 if (ncols && (TQPixmap::defaultDepth() < 15 )) {
600 if ( ncols < 2 || ncols > 256 )
602 TQColor *dPal =
new TQColor[ncols];
603 for (
int i=0; i<ncols; i++) {
604 dPal[i].setRgb ( rca + rDiff * i / ( ncols - 1 ),
605 gca + gDiff * i / ( ncols - 1 ),
606 bca + bDiff * i / ( ncols - 1 ) );
608 dither(image, dPal, ncols);
656 if (image.width() == 0 || image.height() == 0) {
658 std::cerr <<
"WARNING: KImageEffect::intensity : invalid image\n";
663 int segColors = image.depth() > 8 ? 256 : image.numColors();
664 int pixels = image.depth() > 8 ? image.width()*image.height() :
666 unsigned int *data = image.depth() > 8 ? (
unsigned int *)image.bits() :
667 (
unsigned int *)image.tqcolorTable();
669 bool brighten = (percent >= 0);
673 #ifdef USE_MMX_INLINE_ASM
678 TQ_UINT16 p = TQ_UINT16(256.0f*(percent));
679 KIE4Pack mult = {{p,p,p,0}};
681 __asm__ __volatile__(
682 "pxor %%mm7, %%mm7\n\t"
683 "movq (%0), %%mm6\n\t"
684 : :
"r"(&mult),
"m"(mult));
686 unsigned int rem = pixels % 4;
688 TQ_UINT32 *end = ( data + pixels );
692 while ( data != end ) {
693 __asm__ __volatile__(
694 "movq (%0), %%mm0\n\t"
695 "movq 8(%0), %%mm4\n\t"
696 "movq %%mm0, %%mm1\n\t"
697 "movq %%mm0, %%mm3\n\t"
698 "movq %%mm4, %%mm5\n\t"
699 "punpcklbw %%mm7, %%mm0\n\t"
700 "punpckhbw %%mm7, %%mm1\n\t"
701 "pmullw %%mm6, %%mm0\n\t"
702 "punpcklbw %%mm7, %%mm4\n\t"
703 "pmullw %%mm6, %%mm1\n\t"
704 "psrlw $8, %%mm0\n\t"
705 "pmullw %%mm6, %%mm4\n\t"
706 "psrlw $8, %%mm1\n\t"
707 "psrlw $8, %%mm4\n\t"
708 "packuswb %%mm1, %%mm0\n\t"
709 "movq %%mm5, %%mm1\n\t"
711 "punpckhbw %%mm7, %%mm1\n\t"
713 "pmullw %%mm6, %%mm1\n\t"
714 "paddusb %%mm3, %%mm0\n\t"
715 "psrlw $8, %%mm1\n\t"
716 "packuswb %%mm1, %%mm4\n\t"
718 "movq %%mm0, (%0)\n\t"
719 "paddusb %%mm5, %%mm4\n\t"
720 "movq %%mm4, 8(%0)\n\t"
726 while ( data != end ) {
727 __asm__ __volatile__(
728 "movd (%0), %%mm0\n\t"
729 "punpcklbw %%mm7, %%mm0\n\t"
730 "movq %%mm0, %%mm3\n\t"
731 "pmullw %%mm6, %%mm0\n\t"
732 "psrlw $8, %%mm0\n\t"
733 "paddw %%mm3, %%mm0\n\t"
734 "packuswb %%mm0, %%mm0\n\t"
735 "movd %%mm0, (%0)\n\t"
742 while ( data != end ) {
743 __asm__ __volatile__(
744 "movq (%0), %%mm0\n\t"
745 "movq 8(%0), %%mm4\n\t"
746 "movq %%mm0, %%mm1\n\t"
747 "movq %%mm0, %%mm3\n\t"
749 "movq %%mm4, %%mm5\n\t"
751 "punpcklbw %%mm7, %%mm0\n\t"
752 "punpckhbw %%mm7, %%mm1\n\t"
753 "pmullw %%mm6, %%mm0\n\t"
754 "punpcklbw %%mm7, %%mm4\n\t"
755 "pmullw %%mm6, %%mm1\n\t"
756 "psrlw $8, %%mm0\n\t"
757 "pmullw %%mm6, %%mm4\n\t"
758 "psrlw $8, %%mm1\n\t"
759 "psrlw $8, %%mm4\n\t"
760 "packuswb %%mm1, %%mm0\n\t"
761 "movq %%mm5, %%mm1\n\t"
763 "punpckhbw %%mm7, %%mm1\n\t"
765 "pmullw %%mm6, %%mm1\n\t"
766 "psubusb %%mm0, %%mm3\n\t"
767 "psrlw $8, %%mm1\n\t"
768 "packuswb %%mm1, %%mm4\n\t"
770 "movq %%mm3, (%0)\n\t"
771 "psubusb %%mm4, %%mm5\n\t"
772 "movq %%mm5, 8(%0)\n\t"
778 while ( data != end ) {
779 __asm__ __volatile__(
780 "movd (%0), %%mm0\n\t"
781 "punpcklbw %%mm7, %%mm0\n\t"
782 "movq %%mm0, %%mm3\n\t"
783 "pmullw %%mm6, %%mm0\n\t"
784 "psrlw $8, %%mm0\n\t"
785 "psubusw %%mm0, %%mm3\n\t"
786 "packuswb %%mm3, %%mm3\n\t"
787 "movd %%mm3, (%0)\n\t"
792 __asm__ __volatile__(
"emms");
795 #endif // USE_MMX_INLINE_ASM
797 unsigned char *segTbl =
new unsigned char[segColors];
800 for(
int i=0; i < segColors; ++i){
801 tmp = (int)(i*percent);
808 for(
int i=0; i < segColors; ++i){
809 tmp = (int)(i*percent);
817 for(
int i=0; i < pixels; ++i){
818 int r = tqRed(data[i]);
819 int g = tqGreen(data[i]);
820 int b = tqBlue(data[i]);
821 int a = tqAlpha(data[i]);
822 r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
823 g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
824 b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
825 data[i] = tqRgba(r, g, b,a);
829 for(
int i=0; i < pixels; ++i){
830 int r = tqRed(data[i]);
831 int g = tqGreen(data[i]);
832 int b = tqBlue(data[i]);
833 int a = tqAlpha(data[i]);
834 r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
835 g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
836 b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
837 data[i] = tqRgba(r, g, b, a);
849 if (image.width() == 0 || image.height() == 0) {
851 std::cerr <<
"WARNING: KImageEffect::channelIntensity : invalid image\n";
856 int segColors = image.depth() > 8 ? 256 : image.numColors();
857 unsigned char *segTbl =
new unsigned char[segColors];
858 int pixels = image.depth() > 8 ? image.width()*image.height() :
860 unsigned int *data = image.depth() > 8 ? (
unsigned int *)image.bits() :
861 (
unsigned int *)image.tqcolorTable();
862 bool brighten = (percent >= 0);
867 for(
int i=0; i < segColors; ++i){
868 int tmp = (int)(i*percent);
875 for(
int i=0; i < segColors; ++i){
876 int tmp = (int)(i*percent);
885 for(
int i=0; i < pixels; ++i){
886 int c = tqRed(data[i]);
887 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
888 data[i] = tqRgba(c, tqGreen(data[i]), tqBlue(data[i]), tqAlpha(data[i]));
891 else if(channel ==
Green){
892 for(
int i=0; i < pixels; ++i){
893 int c = tqGreen(data[i]);
894 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
895 data[i] = tqRgba(tqRed(data[i]), c, tqBlue(data[i]), tqAlpha(data[i]));
899 for(
int i=0; i < pixels; ++i){
900 int c = tqBlue(data[i]);
901 c = c + segTbl[c] > 255 ? 255 : c + segTbl[c];
902 data[i] = tqRgba(tqRed(data[i]), tqGreen(data[i]), c, tqAlpha(data[i]));
909 for(
int i=0; i < pixels; ++i){
910 int c = tqRed(data[i]);
911 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
912 data[i] = tqRgba(c, tqGreen(data[i]), tqBlue(data[i]), tqAlpha(data[i]));
915 else if(channel ==
Green){
916 for(
int i=0; i < pixels; ++i){
917 int c = tqGreen(data[i]);
918 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
919 data[i] = tqRgba(tqRed(data[i]), c, tqBlue(data[i]), tqAlpha(data[i]));
923 for(
int i=0; i < pixels; ++i){
924 int c = tqBlue(data[i]);
925 c = c - segTbl[c] < 0 ? 0 : c - segTbl[c];
926 data[i] = tqRgba(tqRed(data[i]), tqGreen(data[i]), c, tqAlpha(data[i]));
940 if (image.width() == 0 || image.height() == 0 ||
941 modImage.width() == 0 || modImage.height() == 0) {
943 std::cerr <<
"WARNING: KImageEffect::modulate : invalid image\n";
948 int r, g, b, h, s, v, a;
951 unsigned int x1, x2, y1, y2;
955 if (image.depth()<32) image = image.convertDepth(32);
958 if (modImage.depth()<8) modImage = modImage.convertDepth(8);
960 unsigned int *colorTable2 = (modImage.depth()==8) ?
961 modImage.tqcolorTable():0;
962 unsigned int *data1, *data2;
963 unsigned char *data2b;
964 unsigned int color1, color2;
966 x1 = image.width(); y1 = image.height();
967 x2 = modImage.width(); y2 = modImage.height();
969 for (y = 0; y < (int)y1; y++) {
970 data1 = (
unsigned int *) image.scanLine(y);
971 data2 = (
unsigned int *) modImage.scanLine( y%y2 );
972 data2b = (
unsigned char *) modImage.scanLine( y%y2 );
976 color2 = (colorTable2) ? colorTable2[*data2b] : *data2;
988 if (channel !=
All) {
989 mod = (channel ==
Red) ? tqRed(color2) :
990 (channel ==
Green) ? tqGreen(color2) :
991 (channel ==
Blue) ? tqBlue(color2) :
992 (channel ==
Gray) ? tqGray(color2) : 0;
997 if (channel ==
All) {
998 r += r * factor/50 * tqRed(color2)/256;
999 g += g * factor/50 * tqGreen(color2)/256;
1000 b += b * factor/50 * tqBlue(color2)/256;
1009 if (channel ==
All) {
1010 r += (r-128) * factor/50 * tqRed(color2)/128;
1011 g += (g-128) * factor/50 * tqGreen(color2)/128;
1012 b += (b-128) * factor/50 * tqBlue(color2)/128;
1015 r += (r-128) * mod/128;
1016 g += (g-128) * mod/128;
1017 b += (b-128) * mod/128;
1021 if (r<0) r=0;
if (r>255) r=255;
1022 if (g<0) g=0;
if (g>255) g=255;
1023 if (b<0) b=0;
if (b>255) b=255;
1024 a = tqAlpha(*data1);
1025 *data1 = tqRgba(r, g, b, a);
1029 clr.hsv(&h, &s, &v);
1030 mod = (channel ==
Red) ? tqRed(color2) :
1031 (channel ==
Green) ? tqGreen(color2) :
1032 (channel ==
Blue) ? tqBlue(color2) :
1033 (channel ==
Gray) ? tqGray(color2) : 0;
1034 mod = mod*factor/50;
1038 if (s<0) s=0;
if (s>255) s=255;
1046 clr.setHsv(h, s, v);
1047 a = tqAlpha(*data1);
1048 *data1 = clr.rgb() | ((uint)(a & 0xff) << 24);
1050 data1++; data2++; data2b++; x++;
1051 if ( (x%x2) ==0) { data2 -= x2; data2b -= x2; }
1069 if (dst.width() <= 0 || dst.height() <= 0)
1072 if (opacity < 0.0 || opacity > 1.0) {
1074 std::cerr <<
"WARNING: KImageEffect::blend : invalid opacity. Range [0, 1]\n";
1079 if (dst.depth() != 32)
1080 dst = dst.convertDepth(32);
1083 if (dst.format() != QImage::Format_ARGB32)
1084 dst = dst.convertToFormat(QImage::Format_ARGB32);
1087 int pixels = dst.width() * dst.height();
1089 #ifdef USE_SSE2_INLINE_ASM
1091 TQ_UINT16 alpha = TQ_UINT16( ( 1.0 - opacity ) * 256.0 );
1093 KIE8Pack packedalpha = { { alpha, alpha, alpha, 256,
1094 alpha, alpha, alpha, 256 } };
1096 TQ_UINT16 red = TQ_UINT16( clr.red() * 256 * opacity );
1097 TQ_UINT16 green = TQ_UINT16( clr.green() * 256 * opacity );
1098 TQ_UINT16 blue = TQ_UINT16( clr.blue() * 256 * opacity );
1100 KIE8Pack packedcolor = { { blue, green, red, 0,
1101 blue, green, red, 0 } };
1104 __asm__ __volatile__(
1105 "pxor %%xmm7, %%xmm7\n\t"
1106 "movdqu (%0), %%xmm6\n\t"
1107 "movdqu (%1), %%xmm5\n\t"
1108 : :
"r"(&packedalpha),
"r"(&packedcolor),
1109 "m"(packedcolor),
"m"(packedalpha) );
1111 TQ_UINT32 *data =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1114 int offset = (16 - (TQ_UINT32( data ) & 0x0f)) / 4;
1117 int remainder = (pixels - offset) % 8;
1118 pixels -= remainder;
1121 for (
int i = 0; i < offset; i++ ) {
1122 __asm__ __volatile__(
1123 "movd (%0,%1,4), %%xmm0\n\t"
1124 "punpcklbw %%xmm7, %%xmm0\n\t"
1125 "pmullw %%xmm6, %%xmm0\n\t"
1126 "paddw %%xmm5, %%xmm0\n\t"
1127 "psrlw $8, %%xmm0\n\t"
1128 "packuswb %%xmm1, %%xmm0\n\t"
1129 "movd %%xmm0, (%0,%1,4)\n\t"
1130 : :
"r"(data),
"r"(i) );
1134 for (
int i = offset; i < pixels; i += 8 ) {
1137 "movq (%0,%1,4), %%xmm0\n\t"
1138 "movq 8(%0,%1,4), %%xmm1\n\t"
1139 "movq 16(%0,%1,4), %%xmm2\n\t"
1140 "movq 24(%0,%1,4), %%xmm3\n\t"
1143 "prefetchnta 32(%0,%1,4) \n\t"
1146 "punpcklbw %%xmm7, %%xmm0\n\t"
1147 "pmullw %%xmm6, %%xmm0\n\t"
1148 "paddw %%xmm5, %%xmm0\n\t"
1149 "psrlw $8, %%xmm0\n\t"
1152 "punpcklbw %%xmm7, %%xmm1\n\t"
1153 "pmullw %%xmm6, %%xmm1\n\t"
1154 "paddw %%xmm5, %%xmm1\n\t"
1155 "psrlw $8, %%xmm1\n\t"
1158 "punpcklbw %%xmm7, %%xmm2\n\t"
1159 "pmullw %%xmm6, %%xmm2\n\t"
1160 "paddw %%xmm5, %%xmm2\n\t"
1161 "psrlw $8, %%xmm2\n\t"
1164 "punpcklbw %%xmm7, %%xmm3\n\t"
1165 "pmullw %%xmm6, %%xmm3\n\t"
1166 "paddw %%xmm5, %%xmm3\n\t"
1167 "psrlw $8, %%xmm3\n\t"
1170 "packuswb %%xmm1, %%xmm0\n\t"
1171 "packuswb %%xmm3, %%xmm2\n\t"
1174 "movdqa %%xmm0, (%0,%1,4)\n\t"
1175 "movdqa %%xmm2, 16(%0,%1,4)\n\t"
1176 : :
"r"(data),
"r"(i) );
1180 for (
int i = pixels; i < pixels + remainder; i++ ) {
1181 __asm__ __volatile__(
1182 "movd (%0,%1,4), %%xmm0\n\t"
1183 "punpcklbw %%xmm7, %%xmm0\n\t"
1184 "pmullw %%xmm6, %%xmm0\n\t"
1185 "paddw %%xmm5, %%xmm0\n\t"
1186 "psrlw $8, %%xmm0\n\t"
1187 "packuswb %%xmm1, %%xmm0\n\t"
1188 "movd %%xmm0, (%0,%1,4)\n\t"
1189 : :
"r"(data),
"r"(i) );
1194 #ifdef USE_MMX_INLINE_ASM
1196 TQ_UINT16 alpha = TQ_UINT16( ( 1.0 - opacity ) * 256.0 );
1197 KIE4Pack packedalpha = { { alpha, alpha, alpha, 256 } };
1199 TQ_UINT16 red = TQ_UINT16( clr.red() * 256 * opacity );
1200 TQ_UINT16 green = TQ_UINT16( clr.green() * 256 * opacity );
1201 TQ_UINT16 blue = TQ_UINT16( clr.blue() * 256 * opacity );
1203 KIE4Pack packedcolor = { { blue, green, red, 0 } };
1205 __asm__ __volatile__(
1206 "pxor %%mm7, %%mm7\n\t"
1207 "movq (%0), %%mm6\n\t"
1208 "movq (%1), %%mm5\n\t"
1209 : :
"r"(&packedalpha),
"r"(&packedcolor),
"m"(packedcolor),
"m"(packedalpha) );
1211 TQ_UINT32 *data =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1214 int remainder = pixels % 4;
1215 pixels -= remainder;
1218 for (
int i = 0; i < pixels; i += 4 ) {
1219 __asm__ __volatile__(
1221 "movd (%0,%1,4), %%mm0\n\t"
1222 "movd 4(%0,%1,4), %%mm1\n\t"
1223 "movd 8(%0,%1,4), %%mm2\n\t"
1224 "movd 12(%0,%1,4), %%mm3\n\t"
1227 "punpcklbw %%mm7, %%mm0\n\t"
1228 "pmullw %%mm6, %%mm0\n\t"
1229 "paddw %%mm5, %%mm0\n\t"
1230 "psrlw $8, %%mm0\n\t"
1233 "punpcklbw %%mm7, %%mm1\n\t"
1234 "pmullw %%mm6, %%mm1\n\t"
1235 "paddw %%mm5, %%mm1\n\t"
1236 "psrlw $8, %%mm1\n\t"
1239 "punpcklbw %%mm7, %%mm2\n\t"
1240 "pmullw %%mm6, %%mm2\n\t"
1241 "paddw %%mm5, %%mm2\n\t"
1242 "psrlw $8, %%mm2\n\t"
1245 "punpcklbw %%mm7, %%mm3\n\t"
1246 "pmullw %%mm6, %%mm3\n\t"
1247 "paddw %%mm5, %%mm3\n\t"
1248 "psrlw $8, %%mm3\n\t"
1251 "packuswb %%mm1, %%mm0\n\t"
1252 "packuswb %%mm3, %%mm2\n\t"
1255 "movq %%mm0, (%0,%1,4)\n\t"
1256 "movq %%mm2, 8(%0,%1,4)\n\t"
1257 : :
"r"(data),
"r"(i) );
1261 for (
int i = pixels; i < pixels + remainder; i++ ) {
1262 __asm__ __volatile__(
1263 "movd (%0,%1,4), %%mm0\n\t"
1264 "punpcklbw %%mm7, %%mm0\n\t"
1265 "pmullw %%mm6, %%mm0\n\t"
1266 "paddw %%mm5, %%mm0\n\t"
1267 "psrlw $8, %%mm0\n\t"
1268 "packuswb %%mm0, %%mm0\n\t"
1269 "movd %%mm0, (%0,%1,4)\n\t"
1270 : :
"r"(data),
"r"(i) );
1274 __asm__ __volatile__(
"emms");
1276 #endif // USE_MMX_INLINE_ASM
1279 int rcol, gcol, bcol;
1280 clr.rgb(&rcol, &gcol, &bcol);
1282 #ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
1283 unsigned char *data = (
unsigned char *)dst.bits() + 1;
1285 unsigned char *data = (
unsigned char *)dst.bits();
1288 for (
int i=0; i<pixels; i++)
1290 #ifdef WORDS_BIGENDIAN
1291 *data += (
unsigned char)((rcol - *data) * opacity);
1293 *data += (
unsigned char)((gcol - *data) * opacity);
1295 *data += (
unsigned char)((bcol - *data) * opacity);
1298 *data += (
unsigned char)((bcol - *data) * opacity);
1300 *data += (
unsigned char)((gcol - *data) * opacity);
1302 *data += (
unsigned char)((rcol - *data) * opacity);
1315 if (src.width() <= 0 || src.height() <= 0)
1317 if (dst.width() <= 0 || dst.height() <= 0)
1320 if (src.width() != dst.width() || src.height() != dst.height()) {
1322 std::cerr <<
"WARNING: KImageEffect::blend : src and destination images are not the same size\n";
1327 if (opacity < 0.0 || opacity > 1.0) {
1329 std::cerr <<
"WARNING: KImageEffect::blend : invalid opacity. Range [0, 1]\n";
1334 if (src.depth() != 32) src = src.convertDepth(32);
1335 if (dst.depth() != 32) dst = dst.convertDepth(32);
1338 if (src.format() != QImage::Format_ARGB32)
1339 src = dst.convertToFormat(QImage::Format_ARGB32);
1340 if (dst.format() != QImage::Format_ARGB32)
1341 dst = dst.convertToFormat(QImage::Format_ARGB32);
1344 int pixels = src.width() * src.height();
1346 #ifdef USE_SSE2_INLINE_ASM
1348 TQ_UINT16 alpha = TQ_UINT16( opacity * 256.0 );
1349 KIE8Pack packedalpha = { { alpha, alpha, alpha, 0,
1350 alpha, alpha, alpha, 0 } };
1353 __asm__ __volatile__(
1354 "pxor %%xmm7, %%xmm7\n\t"
1355 "movdqu (%0), %%xmm6\n\t"
1356 : :
"r"(&packedalpha),
"m"(packedalpha) );
1358 TQ_UINT32 *data1 =
reinterpret_cast<TQ_UINT32*
>( src.bits() );
1359 TQ_UINT32 *data2 =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1362 int offset = (16 - (TQ_UINT32( data2 ) & 0x0f)) / 4;
1365 int remainder = (pixels - offset) % 4;
1366 pixels -= remainder;
1369 for (
int i = 0; i < offset; i++ ) {
1370 __asm__ __volatile__(
1371 "movd (%1,%2,4), %%xmm1\n\t"
1372 "punpcklbw %%xmm7, %%xmm1\n\t"
1373 "movd (%0,%2,4), %%xmm0\n\t"
1374 "punpcklbw %%xmm7, %%xmm0\n\t"
1375 "psubw %%xmm1, %%xmm0\n\t"
1376 "pmullw %%xmm6, %%xmm0\n\t"
1377 "psllw $8, %%xmm1\n\t"
1378 "paddw %%xmm1, %%xmm0\n\t"
1379 "psrlw $8, %%xmm0\n\t"
1380 "packuswb %%xmm1, %%xmm0\n\t"
1381 "movd %%xmm0, (%1,%2,4)\n\t"
1382 : :
"r"(data1),
"r"(data2),
"r"(i) );
1386 for (
int i = offset; i < pixels; i += 4 ) {
1387 __asm__ __volatile__(
1389 "movq (%0,%2,4), %%xmm0\n\t"
1390 "movq (%1,%2,4), %%xmm1\n\t"
1391 "movq 8(%0,%2,4), %%xmm2\n\t"
1392 "movq 8(%1,%2,4), %%xmm3\n\t"
1395 "prefetchnta 32(%0,%2,4) \n\t"
1396 "prefetchnta 32(%1,%2,4) \n\t"
1399 "punpcklbw %%xmm7, %%xmm1\n\t"
1400 "punpcklbw %%xmm7, %%xmm0\n\t"
1401 "psubw %%xmm1, %%xmm0\n\t"
1402 "pmullw %%xmm6, %%xmm0\n\t"
1403 "psllw $8, %%xmm1\n\t"
1404 "paddw %%xmm1, %%xmm0\n\t"
1405 "psrlw $8, %%xmm0\n\t"
1408 "punpcklbw %%xmm7, %%xmm3\n\t"
1409 "punpcklbw %%xmm7, %%xmm2\n\t"
1410 "psubw %%xmm3, %%xmm2\n\t"
1411 "pmullw %%xmm6, %%xmm2\n\t"
1412 "psllw $8, %%xmm3\n\t"
1413 "paddw %%xmm3, %%xmm2\n\t"
1414 "psrlw $8, %%xmm2\n\t"
1417 "packuswb %%xmm2, %%xmm0\n\t"
1418 "movdqa %%xmm0, (%1,%2,4)\n\t"
1419 : :
"r"(data1),
"r"(data2),
"r"(i) );
1423 for (
int i = pixels; i < pixels + remainder; i++ ) {
1424 __asm__ __volatile__(
1425 "movd (%1,%2,4), %%xmm1\n\t"
1426 "punpcklbw %%xmm7, %%xmm1\n\t"
1427 "movd (%0,%2,4), %%xmm0\n\t"
1428 "punpcklbw %%xmm7, %%xmm0\n\t"
1429 "psubw %%xmm1, %%xmm0\n\t"
1430 "pmullw %%xmm6, %%xmm0\n\t"
1431 "psllw $8, %%xmm1\n\t"
1432 "paddw %%xmm1, %%xmm0\n\t"
1433 "psrlw $8, %%xmm0\n\t"
1434 "packuswb %%xmm1, %%xmm0\n\t"
1435 "movd %%xmm0, (%1,%2,4)\n\t"
1436 : :
"r"(data1),
"r"(data2),
"r"(i) );
1439 #endif // USE_SSE2_INLINE_ASM
1441 #ifdef USE_MMX_INLINE_ASM
1443 TQ_UINT16 alpha = TQ_UINT16( opacity * 256.0 );
1444 KIE4Pack packedalpha = { { alpha, alpha, alpha, 0 } };
1447 __asm__ __volatile__(
1448 "pxor %%mm7, %%mm7\n\t"
1449 "movq (%0), %%mm6\n\t"
1450 : :
"r"(&packedalpha),
"m"(packedalpha) );
1452 TQ_UINT32 *data1 =
reinterpret_cast<TQ_UINT32*
>( src.bits() );
1453 TQ_UINT32 *data2 =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1456 int remainder = pixels % 2;
1457 pixels -= remainder;
1460 for (
int i = 0; i < pixels; i += 2 ) {
1461 __asm__ __volatile__(
1463 "movd (%0,%2,4), %%mm0\n\t"
1464 "movd (%1,%2,4), %%mm1\n\t"
1465 "movd 4(%0,%2,4), %%mm2\n\t"
1466 "movd 4(%1,%2,4), %%mm3\n\t"
1469 "punpcklbw %%mm7, %%mm0\n\t"
1470 "punpcklbw %%mm7, %%mm1\n\t"
1471 "psubw %%mm1, %%mm0\n\t"
1472 "pmullw %%mm6, %%mm0\n\t"
1473 "psllw $8, %%mm1\n\t"
1474 "paddw %%mm1, %%mm0\n\t"
1475 "psrlw $8, %%mm0\n\t"
1478 "punpcklbw %%mm7, %%mm2\n\t"
1479 "punpcklbw %%mm7, %%mm3\n\t"
1480 "psubw %%mm3, %%mm2\n\t"
1481 "pmullw %%mm6, %%mm2\n\t"
1482 "psllw $8, %%mm3\n\t"
1483 "paddw %%mm3, %%mm2\n\t"
1484 "psrlw $8, %%mm2\n\t"
1487 "packuswb %%mm2, %%mm0\n\t"
1488 "movq %%mm0, (%1,%2,4)\n\t"
1489 : :
"r"(data1),
"r"(data2),
"r"(i) );
1494 __asm__ __volatile__(
1495 "movd (%0), %%mm0\n\t"
1496 "punpcklbw %%mm7, %%mm0\n\t"
1497 "movd (%1), %%mm1\n\t"
1498 "punpcklbw %%mm7, %%mm1\n\t"
1499 "psubw %%mm1, %%mm0\n\t"
1500 "pmullw %%mm6, %%mm0\n\t"
1501 "psllw $8, %%mm1\n\t"
1502 "paddw %%mm1, %%mm0\n\t"
1503 "psrlw $8, %%mm0\n\t"
1504 "packuswb %%mm0, %%mm0\n\t"
1505 "movd %%mm0, (%1)\n\t"
1506 : :
"r"(data1 + pixels),
"r"(data2 + pixels) );
1510 __asm__ __volatile__(
"emms");
1512 #endif // USE_MMX_INLINE_ASM
1515 #ifdef WORDS_BIGENDIAN // ARGB (skip alpha)
1516 unsigned char *data1 = (
unsigned char *)dst.bits() + 1;
1517 unsigned char *data2 = (
unsigned char *)src.bits() + 1;
1519 unsigned char *data1 = (
unsigned char *)dst.bits();
1520 unsigned char *data2 = (
unsigned char *)src.bits();
1523 for (
int i=0; i<pixels; i++)
1525 #ifdef WORDS_BIGENDIAN
1526 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1528 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1530 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1533 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1535 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1537 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1553 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
1555 std::cerr <<
"WARNING: KImageEffect::blend : invalid image\n";
1560 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
1564 unsigned int xi, xf, yi, yf;
1568 float unaffected = 1;
1569 if (initial_intensity > 1) initial_intensity = 1;
1570 if (initial_intensity < -1) initial_intensity = -1;
1571 if (initial_intensity < 0) {
1572 unaffected = 1. + initial_intensity;
1573 initial_intensity = 0;
1578 float var = 1. - initial_intensity;
1581 initial_intensity = intensity = 1.;
1587 unsigned int *data = (
unsigned int *)image.bits();
1589 int image_width = image.width();
1590 int image_height = image.height();
1593 if( eff == VerticalGradient || eff == HorizontalGradient ) {
1596 xi = 0, xf = image_width;
1597 yi = 0, yf = image_height;
1598 if (eff == VerticalGradient) {
1599 if (anti_dir) yf = (int)(image_height * unaffected);
1600 else yi = (int)(image_height * (1 - unaffected));
1603 if (anti_dir) xf = (int)(image_width * unaffected);
1604 else xi = (int)(image_height * (1 - unaffected));
1607 var /= (eff == VerticalGradient?yf-yi:xf-xi);
1610 for (y = yi; y < (int)yf; y++) {
1611 intensity = eff == VerticalGradient? intensity + var :
1613 ind_base = image_width * y ;
1614 for (x = xi; x < (int)xf ; x++) {
1615 if (eff == HorizontalGradient) intensity += var;
1617 r = tqRed (data[ind]) + (int)(intensity *
1618 (r_bgnd - tqRed (data[ind])));
1619 g = tqGreen(data[ind]) + (int)(intensity *
1620 (g_bgnd - tqGreen(data[ind])));
1621 b = tqBlue (data[ind]) + (int)(intensity *
1622 (b_bgnd - tqBlue (data[ind])));
1623 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1624 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1625 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1626 a = tqAlpha(data[ind]);
1627 data[ind] = tqRgba(r, g, b, a);
1631 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
1632 float xvar = var / 2 / image_width;
1633 float yvar = var / 2 / image_height;
1636 for (x = 0; x < image_width ; x++) {
1637 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
1639 for (y = 0; y < image_height ; y++) {
1640 intensity = initial_intensity + tmp + yvar * y;
1642 r = tqRed (data[ind]) + (int)(intensity *
1643 (r_bgnd - tqRed (data[ind])));
1644 g = tqGreen(data[ind]) + (int)(intensity *
1645 (g_bgnd - tqGreen(data[ind])));
1646 b = tqBlue (data[ind]) + (int)(intensity *
1647 (b_bgnd - tqBlue (data[ind])));
1648 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1649 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1650 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1651 a = tqAlpha(data[ind]);
1652 data[ind] = tqRgba(r, g, b, a);
1659 else if (eff == RectangleGradient || eff == EllipticGradient) {
1663 for (x = 0; x < image_width / 2 + image_width % 2; x++) {
1664 xvar = var / image_width * (image_width - x*2/unaffected-1);
1665 for (y = 0; y < image_height / 2 + image_height % 2; y++) {
1666 yvar = var / image_height * (image_height - y*2/unaffected -1);
1668 if (eff == RectangleGradient)
1669 intensity = initial_intensity + QMAX(xvar, yvar);
1671 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1672 if (intensity > 1) intensity = 1;
1673 if (intensity < 0) intensity = 0;
1676 ind = x + image_width * y ;
1677 r = tqRed (data[ind]) + (int)(intensity *
1678 (r_bgnd - tqRed (data[ind])));
1679 g = tqGreen(data[ind]) + (int)(intensity *
1680 (g_bgnd - tqGreen(data[ind])));
1681 b = tqBlue (data[ind]) + (int)(intensity *
1682 (b_bgnd - tqBlue (data[ind])));
1683 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1684 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1685 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1686 a = tqAlpha(data[ind]);
1687 data[ind] = tqRgba(r, g, b, a);
1690 ind = image_width - x - 1 + image_width * y ;
1691 r = tqRed (data[ind]) + (int)(intensity *
1692 (r_bgnd - tqRed (data[ind])));
1693 g = tqGreen(data[ind]) + (int)(intensity *
1694 (g_bgnd - tqGreen(data[ind])));
1695 b = tqBlue (data[ind]) + (int)(intensity *
1696 (b_bgnd - tqBlue (data[ind])));
1697 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1698 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1699 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1700 a = tqAlpha(data[ind]);
1701 data[ind] = tqRgba(r, g, b, a);
1707 for (x = 0; x < image_width / 2; x++) {
1708 xvar = var / image_width * (image_width - x*2/unaffected-1);
1709 for (y = 0; y < image_height / 2; y++) {
1710 yvar = var / image_height * (image_height - y*2/unaffected -1);
1712 if (eff == RectangleGradient)
1713 intensity = initial_intensity + QMAX(xvar, yvar);
1715 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1716 if (intensity > 1) intensity = 1;
1717 if (intensity < 0) intensity = 0;
1720 ind = x + image_width * (image_height - y -1) ;
1721 r = tqRed (data[ind]) + (int)(intensity *
1722 (r_bgnd - tqRed (data[ind])));
1723 g = tqGreen(data[ind]) + (int)(intensity *
1724 (g_bgnd - tqGreen(data[ind])));
1725 b = tqBlue (data[ind]) + (int)(intensity *
1726 (b_bgnd - tqBlue (data[ind])));
1727 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1728 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1729 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1730 a = tqAlpha(data[ind]);
1731 data[ind] = tqRgba(r, g, b, a);
1734 ind = image_width-x-1 + image_width * (image_height - y - 1) ;
1735 r = tqRed (data[ind]) + (int)(intensity *
1736 (r_bgnd - tqRed (data[ind])));
1737 g = tqGreen(data[ind]) + (int)(intensity *
1738 (g_bgnd - tqGreen(data[ind])));
1739 b = tqBlue (data[ind]) + (int)(intensity *
1740 (b_bgnd - tqBlue (data[ind])));
1741 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1742 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1743 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1744 a = tqAlpha(data[ind]);
1745 data[ind] = tqRgba(r, g, b, a);
1750 else std::cerr <<
"KImageEffect::blend effect not implemented" <<
std::endl;
1760 if (image1.width() == 0 || image1.height() == 0 ||
1761 image2.width() == 0 || image2.height() == 0)
1767 TQColor(0,0,0), TQColor(255,255,255),
1770 return blend(image1,image2,image3,
Red);
1778 if (image1.width() == 0 || image1.height() == 0 ||
1779 image2.width() == 0 || image2.height() == 0 ||
1780 blendImage.width() == 0 || blendImage.height() == 0) {
1782 std::cerr <<
"KImageEffect::blend effect invalid image" <<
std::endl;
1788 int ind1, ind2, ind3;
1790 unsigned int x1, x2, x3, y1, y2, y3;
1796 if (image1.depth()<32) image1 = image1.convertDepth(32);
1797 if (image2.depth()<32) image2 = image2.convertDepth(32);
1800 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
1802 unsigned int *colorTable3 = (blendImage.depth()==8) ?
1803 blendImage.tqcolorTable():0;
1805 unsigned int *data1 = (
unsigned int *)image1.bits();
1806 unsigned int *data2 = (
unsigned int *)image2.bits();
1807 unsigned int *data3 = (
unsigned int *)blendImage.bits();
1808 unsigned char *data3b = (
unsigned char *)blendImage.bits();
1809 unsigned int color3;
1811 x1 = image1.width(); y1 = image1.height();
1812 x2 = image2.width(); y2 = image2.height();
1813 x3 = blendImage.width(); y3 = blendImage.height();
1815 for (y = 0; y < (int)y1; y++) {
1821 while(x < (
int)x1) {
1822 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
1824 a = (channel ==
Red) ? tqRed(color3) :
1825 (channel ==
Green) ? tqGreen(color3) :
1826 (channel ==
Blue) ? tqBlue(color3) : tqGray(color3);
1828 r = (a*tqRed(data1[ind1]) + (256-a)*tqRed(data2[ind2]))/256;
1829 g = (a*tqGreen(data1[ind1]) + (256-a)*tqGreen(data2[ind2]))/256;
1830 b = (a*tqBlue(data1[ind1]) + (256-a)*tqBlue(data2[ind2]))/256;
1832 a = tqAlpha(data1[ind1]);
1833 data1[ind1] = tqRgba(r, g, b, a);
1835 ind1++; ind2++; ind3++; x++;
1836 if ( (x%x2) ==0) ind2 -= x2;
1837 if ( (x%x3) ==0) ind3 -= x3;
1850 unsigned int KImageEffect::lHash(
unsigned int c)
1852 unsigned char r = tqRed(c), g = tqGreen(c), b = tqBlue(c), a = tqAlpha(c);
1853 unsigned char nr, ng, nb;
1854 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
1855 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
1856 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
1858 return tqRgba(nr, ng, nb, a);
1864 unsigned int KImageEffect::uHash(
unsigned int c)
1866 unsigned char r = tqRed(c), g = tqGreen(c), b = tqBlue(c), a = tqAlpha(c);
1867 unsigned char nr, ng, nb;
1868 nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
1869 ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
1870 nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
1872 return tqRgba(nr, ng, nb, a);
1880 if (image.width() == 0 || image.height() == 0) {
1882 std::cerr <<
"KImageEffect::hash effect invalid image" <<
std::endl;
1888 unsigned int *data = (
unsigned int *)image.bits();
1894 (
unsigned)image.height() < 2+spacing)
return image;
1897 (unsigned)image.height() < 2+spacing)
return image;
1900 for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
1901 for (x = 0; x < image.width(); x++) {
1902 ind = x + image.width() * y;
1903 data[ind] = lite==
NorthLite?uHash(data[ind]):lHash(data[ind]);
1905 ind = ind + image.width();
1906 data[ind] = lite==
NorthLite?lHash(data[ind]):uHash(data[ind]);
1912 for (y = 0 ; y < image.height(); y++) {
1913 for (x = 0; x < image.width(); x = x + 2 + spacing) {
1914 ind = x + image.width() * y;
1915 data[ind] = lite==
EastLite?uHash(data[ind]):lHash(data[ind]);
1918 data[ind] = lite==
EastLite?lHash(data[ind]):uHash(data[ind]);
1924 for (y = 0 ; y < image.height(); y++) {
1926 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
1927 x = x + 2 + spacing) {
1928 ind = x + image.width() * y + ((y & 1)? 1 : 0);
1929 data[ind] = lite==
NWLite?uHash(data[ind]):lHash(data[ind]);
1932 data[ind] = lite==
NWLite?lHash(data[ind]):uHash(data[ind]);
1938 for (y = 0 ; y < image.height(); y++) {
1939 for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
1940 ind = x + image.width() * y - ((y & 1)? 1 : 0);
1941 data[ind] = lite==
SWLite?uHash(data[ind]):lHash(data[ind]);
1944 data[ind] = lite==
SWLite?lHash(data[ind]):uHash(data[ind]);
1960 const TQColor &cb,
int ncols)
1962 if (img.width() == 0 || img.height() == 0)
1966 if (img.depth() == 1) {
1967 img.setColor(0, ca.rgb());
1968 img.setColor(1, cb.rgb());
1972 int r1 = ca.red();
int r2 = cb.red();
1973 int g1 = ca.green();
int g2 = cb.green();
1974 int b1 = ca.blue();
int b2 = cb.blue();
1975 int min = 0, max = 255;
1980 if (img.numColors()) {
1982 for (
int i = 0; i < img.numColors(); i++) {
1984 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
1985 min = QMIN(min, mean);
1986 max = QMAX(max, mean);
1990 for (
int y=0; y < img.height(); y++)
1991 for (
int x=0; x < img.width(); x++) {
1992 col = img.pixel(x, y);
1993 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
1994 min = QMIN(min, mean);
1995 max = QMAX(max, mean);
2000 float sr = ((float) r2 - r1) / (max - min);
2001 float sg = ((float) g2 - g1) / (max - min);
2002 float sb = ((float) b2 - b1) / (max - min);
2006 if (img.numColors()) {
2007 for (
int i=0; i < img.numColors(); i++) {
2009 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
2010 int r = (int) (sr * (mean - min) + r1 + 0.5);
2011 int g = (int) (sg * (mean - min) + g1 + 0.5);
2012 int b = (int) (sb * (mean - min) + b1 + 0.5);
2013 img.setColor(i, tqRgba(r, g, b, tqAlpha(col)));
2016 for (
int y=0; y < img.height(); y++)
2017 for (
int x=0; x < img.width(); x++) {
2018 col = img.pixel(x, y);
2019 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
2020 int r = (int) (sr * (mean - min) + r1 + 0.5);
2021 int g = (int) (sg * (mean - min) + g1 + 0.5);
2022 int b = (int) (sb * (mean - min) + b1 + 0.5);
2023 img.setPixel(x, y, tqRgba(r, g, b, tqAlpha(col)));
2029 if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
2032 if (ncols == 1) ncols++;
2033 if (ncols > 256) ncols = 256;
2035 TQColor *pal =
new TQColor[ncols];
2036 sr = ((float) r2 - r1) / (ncols - 1);
2037 sg = ((float) g2 - g1) / (ncols - 1);
2038 sb = ((float) b2 - b1) / (ncols - 1);
2040 for (
int i=0; i<ncols; i++)
2041 pal[i] = TQColor(r1 +
int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
2058 if (img.width() == 0 || img.height() == 0)
2062 if (img.depth() == 1)
2065 unsigned char tbl[256];
2066 for (
int i=0; i<256; i++)
2067 tbl[i] = (
int) (val * i + 0.5);
2069 int red = color.red();
2070 int green = color.green();
2071 int blue = color.blue();
2074 int r, g, b, cr, cg, cb;
2076 if (img.depth() <= 8) {
2078 for (
int i=0; i<img.numColors(); i++) {
2080 cr = tqRed(col); cg = tqGreen(col); cb = tqBlue(col);
2082 r = cr - tbl[cr - red];
2084 r = cr + tbl[red - cr];
2086 g = cg - tbl[cg - green];
2088 g = cg + tbl[green - cg];
2090 b = cb - tbl[cb - blue];
2092 b = cb + tbl[blue - cb];
2093 img.setColor(i, tqRgba(r, g, b, tqAlpha(col)));
2098 for (
int y=0; y<img.height(); y++) {
2099 QRgb *data = (QRgb *) img.scanLine(y);
2100 for (
int x=0; x<img.width(); x++) {
2102 cr = tqRed(col); cg = tqGreen(col); cb = tqBlue(col);
2104 r = cr - tbl[cr - red];
2106 r = cr + tbl[red - cr];
2108 g = cg - tbl[cg - green];
2110 g = cg + tbl[green - cg];
2112 b = cb - tbl[cb - blue];
2114 b = cb + tbl[blue - cb];
2115 *data++ = tqRgba(r, g, b, tqAlpha(col));
2140 if (img.width() == 0 || img.height() == 0)
2144 if (img.depth() == 32) {
2145 uchar * r(img.bits());
2146 uchar * g(img.bits() + 1);
2147 uchar * b(img.bits() + 2);
2149 uchar * end(img.bits() + img.numBytes());
2153 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1;
2162 for (
int i = 0; i < img.numColors(); i++)
2164 uint r = tqRed(img.color(i));
2165 uint g = tqGreen(img.color(i));
2166 uint b = tqBlue(img.color(i));
2168 uint gray = (((r + g) >> 1) + b) >> 1;
2169 img.setColor(i, tqRgba(gray, gray, gray, tqAlpha(img.color(i))));
2174 int pixels = img.depth() > 8 ? img.width()*img.height() :
2176 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2177 (
unsigned int *)img.tqcolorTable();
2179 for(i=0; i < pixels; ++i){
2180 val = tqGray(data[i]);
2181 data[i] = tqRgba(val, val, val, tqAlpha(data[i]));
2190 if (img.width() == 0 || img.height() == 0)
2193 if (desat < 0) desat = 0.;
2194 if (desat > 1) desat = 1.;
2195 int pixels = img.depth() > 8 ? img.width()*img.height() :
2197 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2198 (
unsigned int *)img.tqcolorTable();
2201 for(i=0; i < pixels; ++i){
2202 clr.setRgb(data[i]);
2203 clr.hsv(&h, &s, &v);
2204 clr.setHsv(h, (
int)(s * (1. - desat)), v);
2205 data[i] = clr.rgb();
2213 if (img.width() == 0 || img.height() == 0)
2220 int pixels = img.depth() > 8 ? img.width()*img.height() :
2222 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2223 (
unsigned int *)img.tqcolorTable();
2225 for(i=0; i < pixels; ++i){
2227 g = tqGreen(data[i]);
2228 b = tqBlue(data[i]);
2229 if(tqGray(data[i]) <= 127){
2257 data[i] = tqRgba(r, g, b, tqAlpha(data[i]));
2275 if (img.width() == 0 || img.height() == 0 ||
2276 palette == 0 || img.depth() <= 8)
2279 TQImage dImage( img.width(), img.height(), 8, size );
2282 dImage.setNumColors( size );
2283 for ( i = 0; i < size; i++ )
2284 dImage.setColor( i, palette[ i ].rgb() );
2286 int *rerr1 =
new int [ img.width() * 2 ];
2287 int *gerr1 =
new int [ img.width() * 2 ];
2288 int *berr1 =
new int [ img.width() * 2 ];
2290 memset( rerr1, 0,
sizeof(
int ) * img.width() * 2 );
2291 memset( gerr1, 0,
sizeof(
int ) * img.width() * 2 );
2292 memset( berr1, 0,
sizeof(
int ) * img.width() * 2 );
2294 int *rerr2 = rerr1 + img.width();
2295 int *gerr2 = gerr1 + img.width();
2296 int *berr2 = berr1 + img.width();
2298 for (
int j = 0; j < img.height(); j++ )
2300 uint *ip = (uint * )img.scanLine( j );
2301 uchar *dp = dImage.scanLine( j );
2303 for ( i = 0; i < img.width(); i++ )
2305 rerr1[i] = rerr2[i] + tqRed( *ip );
2307 gerr1[i] = gerr2[i] + tqGreen( *ip );
2309 berr1[i] = berr2[i] + tqBlue( *ip );
2314 *dp++ = nearestColor( rerr1[0], gerr1[0], berr1[0], palette, size );
2316 for ( i = 1; i < img.width()-1; i++ )
2318 int indx = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
2321 int rerr = rerr1[i];
2322 rerr -= palette[indx].red();
2323 int gerr = gerr1[i];
2324 gerr -= palette[indx].green();
2325 int berr = berr1[i];
2326 berr -= palette[indx].blue();
2329 rerr1[ i+1 ] += ( rerr * 7 ) >> 4;
2330 rerr2[ i-1 ] += ( rerr * 3 ) >> 4;
2331 rerr2[ i ] += ( rerr * 5 ) >> 4;
2332 rerr2[ i+1 ] += ( rerr ) >> 4;
2335 gerr1[ i+1 ] += ( gerr * 7 ) >> 4;
2336 gerr2[ i-1 ] += ( gerr * 3 ) >> 4;
2337 gerr2[ i ] += ( gerr * 5 ) >> 4;
2338 gerr2[ i+1 ] += ( gerr ) >> 4;
2341 berr1[ i+1 ] += ( berr * 7 ) >> 4;
2342 berr2[ i-1 ] += ( berr * 3 ) >> 4;
2343 berr2[ i ] += ( berr * 5 ) >> 4;
2344 berr2[ i+1 ] += ( berr ) >> 4;
2349 *dp = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
2360 int KImageEffect::nearestColor(
int r,
int g,
int b,
const TQColor *palette,
int size )
2365 int dr = palette[0].red() - r;
2366 int dg = palette[0].green() - g;
2367 int db = palette[0].blue() - b;
2369 int minDist = dr*dr + dg*dg + db*db;
2372 for (
int i = 1; i < size; i++ )
2374 dr = palette[i].red() - r;
2375 dg = palette[i].green() - g;
2376 db = palette[i].blue() - b;
2378 int dist = dr*dr + dg*dg + db*db;
2380 if ( dist < minDist )
2391 const TQImage & upper,
2392 const TQImage & lower,
2397 upper.width() > lower.width() ||
2398 upper.height() > lower.height() ||
2399 upper.depth() != 32 ||
2404 std::cerr <<
"KImageEffect::blend : Sizes not correct\n" ;
2409 output = lower.copy();
2414 int w = upper.width();
2415 int row(upper.height() - 1);
2419 i =
const_cast<TQImage&
>(upper).scanLine(row);
2420 o =
const_cast<TQImage&
>(output).scanLine(row);
2427 while (!(a = i[col]) && (col != 3)) {
2428 --col; --col; --col; --col;
2432 o[col] += ((i[col] - o[col]) * a) >> 8;
2435 o[col] += ((i[col] - o[col]) * a) >> 8;
2438 o[col] += ((i[col] - o[col]) * a) >> 8;
2450 const TQImage & upper,
2451 const TQImage & lower,
2453 const TQRect & destRect
2456 output = lower.copy();
2464 const TQImage & upper,
2465 const TQImage & lower,
2469 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
2471 if ( upper.width() + x > lower.width() ||
2472 upper.height() + y > lower.height() ||
2474 upper.depth() != 32 || lower.depth() != 32 )
2476 if ( x > lower.width() || y > lower.height() )
return false;
2477 if ( upper.width()<=0 || upper.height() <= 0 )
return false;
2478 if ( lower.width()<=0 || lower.height() <= 0 )
return false;
2480 if (x<0) {cx=-x; cw+=x; x=0; };
2481 if (cw + x > lower.width()) { cw=lower.width()-x; };
2482 if (y<0) {cy=-y; ch+=y; y=0; };
2483 if (ch + y > lower.height()) { ch=lower.height()-y; };
2485 if ( cx >= upper.width() || cy >= upper.height() )
return true;
2486 if ( cw <= 0 || ch <= 0 )
return true;
2489 output.create(cw,ch,32);
2497 for (j=0; j<ch; j++)
2499 b=
reinterpret_cast<QRgb *
>(&
const_cast<TQImage&
>(lower).scanLine(y+j) [ (x+cw) << 2 ]);
2500 i=
reinterpret_cast<QRgb *
>(&
const_cast<TQImage&
>(upper).scanLine(cy+j)[ (cx+cw) << 2 ]);
2501 o=
reinterpret_cast<QRgb *
>(&
const_cast<TQImage&
>(output).scanLine(j) [ cw << 2 ]);
2507 while ( !(a=tqAlpha(*i)) && k>0 )
2516 *o = tqRgb(tqRed(*b) + (((tqRed(*i) - tqRed(*b)) * a) >> 8),
2517 tqGreen(*b) + (((tqGreen(*i) - tqGreen(*b)) * a) >> 8),
2518 tqBlue(*b) + (((tqBlue(*i) - tqBlue(*b)) * a) >> 8));
2528 const TQImage & upper,
2529 const TQImage & lower
2532 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
2534 if ( upper.depth() != 32 || lower.depth() != 32 )
return false;
2535 if ( x + cw > lower.width() ||
2536 y + ch > lower.height() ||
2539 if ( x > lower.width() || y > lower.height() )
return true;
2540 if ( upper.width()<=0 || upper.height() <= 0 )
return true;
2541 if ( lower.width()<=0 || lower.height() <= 0 )
return true;
2543 if (x<0) {cx=-x; cw+=x; x=0; };
2544 if (cw + x > lower.width()) { cw=lower.width()-x; };
2545 if (y<0) {cy=-y; ch+=y; y=0; };
2546 if (ch + y > lower.height()) { ch=lower.height()-y; };
2548 if ( cx >= upper.width() || cy >= upper.height() )
return true;
2549 if ( cw <= 0 || ch <= 0 )
return true;
2556 for (
int j=0; j<ch; j++)
2558 b=&
const_cast<TQImage&
>(lower).scanLine(y+j) [ (x+cw) << 2 ];
2559 i=&
const_cast<TQImage&
>(upper).scanLine(cy+j)[ (cx+cw) << 2 ];
2565 #ifndef WORDS_BIGENDIAN
2566 while ( !(a=*i) && k>0 )
2568 while ( !(a=*(i-3)) && k>0 )
2574 #ifndef WORDS_BIGENDIAN
2576 *b += ( ((*i - *b) * a) >> 8 );
2578 *b += ( ((*i - *b) * a) >> 8 );
2580 *b += ( ((*i - *b) * a) >> 8 );
2583 *b += ( ((*i - *b) * a) >> 8 );
2585 *b += ( ((*i - *b) * a) >> 8 );
2587 *b += ( ((*i - *b) * a) >> 8 );
2597 TQImage &lower,
const TQRect &lowerRect)
2600 TQRect lr = lowerRect & lower.rect();
2601 lr.setWidth( QMIN(lr.width(), upper.width()-upperOffset.x()) );
2602 lr.setHeight( QMIN(lr.height(), upper.height()-upperOffset.y()) );
2603 if ( !lr.isValid() )
return;
2606 for (
int y = 0; y < lr.height(); y++) {
2607 for (
int x = 0; x < lr.width(); x++) {
2608 QRgb *b =
reinterpret_cast<QRgb*
>(
const_cast<TQImage&
>(lower).scanLine(lr.y() + y)+ (lr.x() + x) *
sizeof(QRgb));
2609 QRgb *d =
reinterpret_cast<QRgb*
>(
const_cast<TQImage&
>(upper).scanLine(upperOffset.y() + y) + (upperOffset.x() + x) *
sizeof(QRgb));
2610 int a = tqAlpha(*d);
2611 *b = tqRgb(tqRed(*b) - (((tqRed(*b) - tqRed(*d)) * a) >> 8),
2612 tqGreen(*b) - (((tqGreen(*b) - tqGreen(*d)) * a) >> 8),
2613 tqBlue(*b) - (((tqBlue(*b) - tqBlue(*d)) * a) >> 8));
2619 TQImage &lower,
const TQRect &lowerRect,
float opacity)
2622 TQRect lr = lowerRect & lower.rect();
2623 lr.setWidth( QMIN(lr.width(), upper.width()-upperOffset.x()) );
2624 lr.setHeight( QMIN(lr.height(), upper.height()-upperOffset.y()) );
2625 if ( !lr.isValid() )
return;
2628 for (
int y = 0; y < lr.height(); y++) {
2629 for (
int x = 0; x < lr.width(); x++) {
2630 QRgb *b =
reinterpret_cast<QRgb*
>(
const_cast<TQImage&
>(lower).scanLine(lr.y() + y)+ (lr.x() + x) *
sizeof(QRgb));
2631 QRgb *d =
reinterpret_cast<QRgb*
>(
const_cast<TQImage&
>(upper).scanLine(upperOffset.y() + y) + (upperOffset.x() + x) *
sizeof(QRgb));
2632 int a = tqRound(opacity * tqAlpha(*d));
2633 *b = tqRgb(tqRed(*b) - (((tqRed(*b) - tqRed(*d)) * a) >> 8),
2634 tqGreen(*b) - (((tqGreen(*b) - tqGreen(*d)) * a) >> 8),
2635 tqBlue(*b) - (((tqBlue(*b) - tqBlue(*d)) * a) >> 8));
2643 int w = lowerSize.width();
2644 int h = lowerSize.height();
2645 int ww = upper.width();
2646 int wh = upper.height();
2649 switch (disposition) {
2653 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2656 d.setRect(0, 0, w, h);
2659 d.setCoords(-ww + ((w - ww) / 2) % ww, -wh + ((h - wh) / 2) % wh,
2663 upper = upper.smoothScale(w, h);
2664 d.setRect(0, 0, w, h);
2667 if( ww <= w && wh <= h ) {
2668 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2673 double sx = (double) w / ww;
2674 double sy = (double) h / wh;
2676 ww = (int)(sy * ww);
2679 wh = (int)(sx * wh);
2682 upper = upper.smoothScale(ww, wh);
2683 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2687 double sx = (double) w / ww;
2688 double sy = (double) h / wh;
2690 ww = (int)(sy * ww);
2693 wh = (int)(sx * wh);
2696 upper = upper.smoothScale(ww, wh);
2697 d.setRect(0, 0, w, h);
2709 for (
int y = r.top(); y<r.bottom(); y += upper.height())
2710 for (
int x = r.left(); x<r.right(); x += upper.width())
2712 lower, TQRect(x, y, upper.width(), upper.height()), opacity);
2719 return blend( col, img, 0.5);
2761 if(w == src.width() && h == src.height())
2764 int depth = src.depth();
2765 TQImage dest(w, h, depth, depth <= 8 ? src.numColors() : 0,
2766 depth == 1 ? TQImage::LittleEndian : TQImage::IgnoreEndian);
2767 int *x_offset = (
int *)malloc(w*
sizeof(
int));
2768 int *y_offset = (
int *)malloc(h*
sizeof(
int));
2769 if(!x_offset || !y_offset){
2771 qWarning(
"KImageEffect::sample(): Unable to allocate pixel buffer");
2779 for(
int x=0; x < w; ++x)
2780 x_offset[x] = (
int)(x*src.width()/((double)w));
2781 for(
int y=0; y < h; ++y)
2782 y_offset[y] = (
int)(y*src.height()/((double)h));
2785 for(
int y=0; y < h; ++y){
2786 unsigned int *destData = (
unsigned int *)dest.scanLine(y);
2787 unsigned int *srcData = (
unsigned int *)src.scanLine(y_offset[y]);
2788 for(
int x=0; x < w; ++x)
2789 destData[x] = srcData[x_offset[x]];
2792 else if(depth == 1) {
2793 int r = src.bitOrder() == TQImage::LittleEndian;
2794 memcpy(dest.tqcolorTable(), src.tqcolorTable(), src.numColors()*
sizeof(QRgb));
2795 for(
int y=0; y < h; ++y){
2796 unsigned char *destData = dest.scanLine(y);
2797 unsigned char *srcData = src.scanLine(y_offset[y]);
2798 for(
int x=0; x < w; ++x){
2799 int k = x_offset[x];
2800 int l = r ? (k & 7) : (7 - (k&7));
2801 if(srcData[k >> 3] & (1 << l))
2802 destData[x >> 3] |= 1 << (x & 7);
2804 destData[x >> 3] &= ~(1 << (x & 7));
2809 memcpy(dest.tqcolorTable(), src.tqcolorTable(), src.numColors()*
sizeof(QRgb));
2810 for(
int y=0; y < h; ++y){
2811 unsigned char *destData = dest.scanLine(y);
2812 unsigned char *srcData = src.scanLine(y_offset[y]);
2813 for(
int x=0; x < w; ++x)
2814 destData[x] = srcData[x_offset[x]];
2826 if(img.depth() > 8){
2827 count = img.width()*img.height();
2828 data = (
unsigned int *)img.bits();
2831 count = img.numColors();
2832 data = (
unsigned int *)img.tqcolorTable();
2834 for(i=0; i < count; ++i)
2835 data[i] = intensityValue(data[i]) < threshold ? QColor(Qt::black).rgb() : QColor(Qt::white).rgb();
2838 void KImageEffect::hull(
const int x_offset,
const int y_offset,
2839 const int polarity,
const int columns,
2841 unsigned int *f,
unsigned int *g)
2845 unsigned int *p, *q, *r, *s;
2847 if(f == NULL || g == NULL)
2851 r=p+(y_offset*(columns+2)+x_offset);
2852 for (y=0; y < rows; y++){
2857 for (x=0; x < columns; x++){
2867 for(x=0; x < columns; x++){
2869 if (v > (
unsigned int) (*r+1))
2882 r=q+(y_offset*(columns+2)+x_offset);
2883 s=q-(y_offset*(columns+2)+x_offset);
2884 for(y=0; y < rows; y++){
2890 for(x=0; x < (int) columns; x++){
2892 if (((
unsigned int) (*s+1) > v) && (*r > v))
2901 for (x=0; x < columns; x++){
2903 if (((
unsigned int) (*s+1) < v) && (*r < v))
2921 unsigned int *blue_channel, *red_channel, *green_channel, *buffer,
2928 unsigned int *destData;
2929 TQImage dest(src.width(), src.height(), 32);
2931 packets = (src.width()+2)*(src.height()+2);
2932 red_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2933 green_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2934 blue_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2935 alpha_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2936 buffer = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2937 if(!red_channel || ! green_channel || ! blue_channel || ! alpha_channel ||
2940 free(green_channel);
2942 free(alpha_channel);
2949 if(src.depth() > 8){
2950 unsigned int *srcData;
2951 for(y=0; y < src.height(); ++y){
2952 srcData = (
unsigned int *)src.scanLine(y);
2954 for(x=0; x < src.width(); ++x){
2955 red_channel[j] = tqRed(srcData[x]);
2956 green_channel[j] = tqGreen(srcData[x]);
2957 blue_channel[j] = tqBlue(srcData[x]);
2958 alpha_channel[j] = tqAlpha(srcData[x]);
2965 unsigned char *srcData;
2966 unsigned int *cTable = src.tqcolorTable();
2968 for(y=0; y < src.height(); ++y){
2969 srcData = (
unsigned char *)src.scanLine(y);
2971 for(x=0; x < src.width(); ++x){
2972 pixel = *(cTable+srcData[x]);
2973 red_channel[j] = tqRed(pixel);
2974 green_channel[j] = tqGreen(pixel);
2975 blue_channel[j] = tqBlue(pixel);
2976 alpha_channel[j] = tqAlpha(pixel);
2983 for(i=0; i < 4; i++){
2984 hull(X[i],Y[i],1,src.width(),src.height(),red_channel,buffer);
2985 hull(-X[i],-Y[i],1,src.width(),src.height(),red_channel,buffer);
2986 hull(-X[i],-Y[i],-1,src.width(),src.height(),red_channel,buffer);
2987 hull(X[i],Y[i],-1,src.width(),src.height(),red_channel,buffer);
2990 for (i=0; i < packets; i++)
2992 for (i=0; i < 4; i++){
2993 hull(X[i],Y[i],1,src.width(),src.height(),green_channel,buffer);
2994 hull(-X[i],-Y[i],1,src.width(),src.height(),green_channel,buffer);
2995 hull(-X[i],-Y[i],-1,src.width(),src.height(),green_channel,buffer);
2996 hull(X[i],Y[i],-1,src.width(),src.height(),green_channel,buffer);
2999 for (i=0; i < packets; i++)
3001 for (i=0; i < 4; i++){
3002 hull(X[i],Y[i],1,src.width(),src.height(),blue_channel,buffer);
3003 hull(-X[i],-Y[i],1,src.width(),src.height(),blue_channel,buffer);
3004 hull(-X[i],-Y[i],-1,src.width(),src.height(),blue_channel,buffer);
3005 hull(X[i],Y[i],-1,src.width(),src.height(),blue_channel,buffer);
3009 for(y=0; y < dest.height(); ++y)
3011 destData = (
unsigned int *)dest.scanLine(y);
3013 for (x=0; x < dest.width(); ++x)
3015 destData[x] = tqRgba(red_channel[j], green_channel[j],
3016 blue_channel[j], alpha_channel[j]);
3023 free(green_channel);
3025 free(alpha_channel);
3029 unsigned int KImageEffect::generateNoise(
unsigned int pixel,
3030 NoiseType noise_type)
3032 #define NoiseEpsilon 1.0e-5
3033 #define NoiseMask 0x7fff
3034 #define SigmaUniform 4.0
3035 #define SigmaGaussian 4.0
3036 #define SigmaImpulse 0.10
3037 #define SigmaLaplacian 10.0
3038 #define SigmaMultiplicativeGaussian 0.5
3039 #define SigmaPoisson 0.05
3040 #define TauGaussian 20.0
3042 double alpha, beta, sigma, value;
3043 alpha=(double) (rand() & NoiseMask)/NoiseMask;
3050 value=(double) pixel+SigmaUniform*(alpha-0.5);
3057 beta=(double) (rand() & NoiseMask)/NoiseMask;
3058 sigma=sqrt(-2.0*log(alpha))*cos(2.0*M_PI*beta);
3059 tau=sqrt(-2.0*log(alpha))*sin(2.0*M_PI*beta);
3060 value=(double) pixel+
3061 (sqrt((
double) pixel)*SigmaGaussian*sigma)+(TauGaussian*tau);
3066 if (alpha <= NoiseEpsilon)
3069 sigma=sqrt(-2.0*log(alpha));
3070 beta=(rand() & NoiseMask)/NoiseMask;
3071 value=(double) pixel+
3072 pixel*SigmaMultiplicativeGaussian*sigma*cos(2.0*M_PI*beta);
3077 if (alpha < (SigmaImpulse/2.0))
3080 if (alpha >= (1.0-(SigmaImpulse/2.0)))
3090 if (alpha <= NoiseEpsilon)
3091 value=(double) pixel-MaxRGB;
3093 value=(double) pixel+SigmaLaplacian*log(2.0*alpha);
3097 if (beta <= (0.5*NoiseEpsilon))
3098 value=(
double) pixel+MaxRGB;
3100 value=(double) pixel-SigmaLaplacian*log(2.0*beta);
3108 for (i=0; alpha > exp(-SigmaPoisson*pixel); i++)
3110 beta=(double) (rand() & NoiseMask)/NoiseMask;
3113 value=i/SigmaPoisson;
3121 return((
unsigned int) (value+0.5));
3127 TQImage dest(src.width(), src.height(), 32);
3128 unsigned int *destData;
3130 if(src.depth() > 8){
3131 unsigned int *srcData;
3132 for(y=0; y < src.height(); ++y){
3133 srcData = (
unsigned int *)src.scanLine(y);
3134 destData = (
unsigned int *)dest.scanLine(y);
3135 for(x=0; x < src.width(); ++x){
3136 destData[x] = tqRgba(generateNoise(tqRed(srcData[x]), noise_type),
3137 generateNoise(tqGreen(srcData[x]), noise_type),
3138 generateNoise(tqBlue(srcData[x]), noise_type),
3139 tqAlpha(srcData[x]));
3144 unsigned char *srcData;
3145 unsigned int *cTable = src.tqcolorTable();
3147 for(y=0; y < src.height(); ++y){
3148 srcData = (
unsigned char *)src.scanLine(y);
3149 destData = (
unsigned int *)dest.scanLine(y);
3150 for(x=0; x < src.width(); ++x){
3151 pixel = *(cTable+srcData[x]);
3152 destData[x] = tqRgba(generateNoise(tqRed(pixel), noise_type),
3153 generateNoise(tqGreen(pixel), noise_type),
3154 generateNoise(tqBlue(pixel), noise_type),
3163 unsigned int KImageEffect::interpolateColor(TQImage *image,
double x_offset,
3165 unsigned int background)
3168 unsigned int p, q, r, s;
3173 if((x < -1) || (x >= image->width()) || (y < -1) || (y >= image->height()))
3175 if(image->depth() > 8){
3176 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
3177 unsigned int *t = (
unsigned int *)image->scanLine(y);
3180 r = t[x+image->width()];
3181 s = t[x+image->width()+1];
3184 unsigned int *t = (
unsigned int *)image->scanLine(y);
3186 if((x >= 0) && (y >= 0)){
3190 if(((x+1) < image->width()) && (y >= 0)){
3194 if((x >= 0) && ((y+1) < image->height())){
3195 t = (
unsigned int *)image->scanLine(y+1);
3196 r = t[x+image->width()];
3199 if(((x+1) < image->width()) && ((y+1) < image->height())){
3200 t = (
unsigned int *)image->scanLine(y+1);
3201 s = t[x+image->width()+1];
3207 unsigned int *colorTable = (
unsigned int *)image->tqcolorTable();
3208 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
3210 t = (
unsigned char *)image->scanLine(y);
3211 p = *(colorTable+t[x]);
3212 q = *(colorTable+t[x+1]);
3213 t = (
unsigned char *)image->scanLine(y+1);
3214 r = *(colorTable+t[x]);
3215 s = *(colorTable+t[x+1]);
3220 if((x >= 0) && (y >= 0)){
3221 t = (
unsigned char *)image->scanLine(y);
3222 p = *(colorTable+t[x]);
3225 if(((x+1) < image->width()) && (y >= 0)){
3226 t = (
unsigned char *)image->scanLine(y);
3227 q = *(colorTable+t[x+1]);
3230 if((x >= 0) && ((y+1) < image->height())){
3231 t = (
unsigned char *)image->scanLine(y+1);
3232 r = *(colorTable+t[x]);
3235 if(((x+1) < image->width()) && ((y+1) < image->height())){
3236 t = (
unsigned char *)image->scanLine(y+1);
3237 s = *(colorTable+t[x+1]);
3243 x_offset -= floor(x_offset);
3244 y_offset -= floor(y_offset);
3245 alpha = 1.0-x_offset;
3246 beta = 1.0-y_offset;
3248 return(tqRgba((
unsigned char)(beta*(alpha*tqRed(p)+x_offset*tqRed(q))+y_offset*(alpha*tqRed(r)+x_offset*tqRed(s))),
3249 (
unsigned char)(beta*(alpha*tqGreen(p)+x_offset*tqGreen(q))+y_offset*(alpha*tqGreen(r)+x_offset*tqGreen(s))),
3250 (
unsigned char)(beta*(alpha*tqBlue(p)+x_offset*tqBlue(q))+y_offset*(alpha*tqBlue(r)+x_offset*tqBlue(s))),
3251 (
unsigned char)(beta*(alpha*tqAlpha(p)+x_offset*tqAlpha(q))+y_offset*(alpha*tqAlpha(r)+x_offset*tqAlpha(s)))));
3255 unsigned int background)
3257 double amount, distance, radius;
3258 double x_center, x_distance, x_scale;
3259 double y_center, y_distance, y_scale;
3260 unsigned int *destData;
3263 TQImage dest(src.width(), src.height(), 32);
3268 x_center = (double)0.5*src.width();
3269 y_center = (double)0.5*src.height();
3271 if(src.width() > src.height())
3272 y_scale = (
double)src.width()/src.height();
3273 else if(src.width() < src.height()){
3274 x_scale = (double) src.height()/src.width();
3280 if(src.depth() > 8){
3281 unsigned int *srcData;
3282 for(y=0; y < src.height(); ++y){
3283 srcData = (
unsigned int *)src.scanLine(y);
3284 destData = (
unsigned int *)dest.scanLine(y);
3285 y_distance=y_scale*(y-y_center);
3286 for(x=0; x < src.width(); ++x){
3287 destData[x] = srcData[x];
3288 x_distance = x_scale*(x-x_center);
3289 distance= x_distance*x_distance+y_distance*y_distance;
3290 if(distance < (radius*radius)){
3296 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
3297 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
3298 factor*y_distance/y_scale+y_center,
3305 unsigned char *srcData;
3307 unsigned int *cTable = src.tqcolorTable();
3308 for(y=0; y < src.height(); ++y){
3309 srcData = (
unsigned char *)src.scanLine(y);
3310 destData = (
unsigned int *)dest.scanLine(y);
3311 y_distance=y_scale*(y-y_center);
3312 for(x=0; x < src.width(); ++x){
3314 destData[x] = cTable[idx];
3315 x_distance = x_scale*(x-x_center);
3316 distance= x_distance*x_distance+y_distance*y_distance;
3317 if(distance < (radius*radius)){
3323 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
3324 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
3325 factor*y_distance/y_scale+y_center,
3339 if(img.depth() > 8){
3340 unsigned int *srcData, *destData;
3343 dest.create(img.height(), img.width(), img.depth());
3344 for(y=0; y < img.height(); ++y){
3345 srcData = (
unsigned int *)img.scanLine(y);
3346 for(x=0; x < img.width(); ++x){
3347 destData = (
unsigned int *)dest.scanLine(x);
3348 destData[img.height()-y-1] = srcData[x];
3353 dest.create(img.width(), img.height(), img.depth());
3354 for(y=0; y < img.height(); ++y){
3355 srcData = (
unsigned int *)img.scanLine(y);
3356 destData = (
unsigned int *)dest.scanLine(img.height()-y-1);
3357 for(x=0; x < img.width(); ++x)
3358 destData[img.width()-x-1] = srcData[x];
3362 dest.create(img.height(), img.width(), img.depth());
3363 for(y=0; y < img.height(); ++y){
3364 srcData = (
unsigned int *)img.scanLine(y);
3365 for(x=0; x < img.width(); ++x){
3366 destData = (
unsigned int *)dest.scanLine(img.width()-x-1);
3367 destData[y] = srcData[x];
3377 unsigned char *srcData, *destData;
3378 unsigned int *srcTable, *destTable;
3381 dest.create(img.height(), img.width(), img.depth());
3382 dest.setNumColors(img.numColors());
3383 srcTable = (
unsigned int *)img.tqcolorTable();
3384 destTable = (
unsigned int *)dest.tqcolorTable();
3385 for(x=0; x < img.numColors(); ++x)
3386 destTable[x] = srcTable[x];
3387 for(y=0; y < img.height(); ++y){
3388 srcData = (
unsigned char *)img.scanLine(y);
3389 for(x=0; x < img.width(); ++x){
3390 destData = (
unsigned char *)dest.scanLine(x);
3391 destData[img.height()-y-1] = srcData[x];
3396 dest.create(img.width(), img.height(), img.depth());
3397 dest.setNumColors(img.numColors());
3398 srcTable = (
unsigned int *)img.tqcolorTable();
3399 destTable = (
unsigned int *)dest.tqcolorTable();
3400 for(x=0; x < img.numColors(); ++x)
3401 destTable[x] = srcTable[x];
3402 for(y=0; y < img.height(); ++y){
3403 srcData = (
unsigned char *)img.scanLine(y);
3404 destData = (
unsigned char *)dest.scanLine(img.height()-y-1);
3405 for(x=0; x < img.width(); ++x)
3406 destData[img.width()-x-1] = srcData[x];
3410 dest.create(img.height(), img.width(), img.depth());
3411 dest.setNumColors(img.numColors());
3412 srcTable = (
unsigned int *)img.tqcolorTable();
3413 destTable = (
unsigned int *)dest.tqcolorTable();
3414 for(x=0; x < img.numColors(); ++x)
3415 destTable[x] = srcTable[x];
3416 for(y=0; y < img.height(); ++y){
3417 srcData = (
unsigned char *)img.scanLine(y);
3418 for(x=0; x < img.width(); ++x){
3419 destData = (
unsigned char *)dest.scanLine(img.width()-x-1);
3420 destData[y] = srcData[x];
3439 threshold = (int)(factor*(MaxRGB+1)/100.0);
3440 if(img.depth() < 32){
3441 data = (
unsigned int *)img.tqcolorTable();
3442 count = img.numColors();
3445 data = (
unsigned int *)img.bits();
3446 count = img.width()*img.height();
3448 for(i=0; i < count; ++i){
3449 data[i] = tqRgba(tqRed(data[i]) > threshold ? MaxRGB-tqRed(data[i]) : tqRed(data[i]),
3450 tqGreen(data[i]) > threshold ? MaxRGB-tqGreen(data[i]) : tqGreen(data[i]),
3451 tqBlue(data[i]) > threshold ? MaxRGB-tqBlue(data[i]) : tqBlue(data[i]),
3459 int x_distance, y_distance;
3460 if(src.width() < 3 || src.height() < 3)
3464 quantum=(amount+1) >> 1;
3465 if(src.depth() > 8){
3466 unsigned int *p, *q;
3467 for(y=0; y < src.height(); y++){
3468 q = (
unsigned int *)dest.scanLine(y);
3469 for(x=0; x < src.width(); x++){
3470 x_distance = x + ((rand() & (amount+1))-quantum);
3471 y_distance = y + ((rand() & (amount+1))-quantum);
3472 x_distance = QMIN(x_distance, src.width()-1);
3473 y_distance = QMIN(y_distance, src.height()-1);
3478 p = (
unsigned int *)src.scanLine(y_distance);
3486 unsigned char *p, *q;
3487 for(y=0; y < src.height(); y++){
3488 q = (
unsigned char *)dest.scanLine(y);
3489 for(x=0; x < src.width(); x++){
3490 x_distance = x + ((rand() & (amount+1))-quantum);
3491 y_distance = y + ((rand() & (amount+1))-quantum);
3492 x_distance = QMIN(x_distance, src.width()-1);
3493 y_distance = QMIN(y_distance, src.height()-1);
3498 p = (
unsigned char *)src.scanLine(y_distance);
3508 unsigned int background)
3510 double cosine, distance, factor, radius, sine, x_center, x_distance,
3511 x_scale, y_center, y_distance, y_scale;
3514 TQImage dest(src.width(), src.height(), 32);
3517 x_center = src.width()/2.0;
3518 y_center = src.height()/2.0;
3519 radius = QMAX(x_center,y_center);
3522 if(src.width() > src.height())
3523 y_scale=(
double)src.width()/src.height();
3524 else if(src.width() < src.height())
3525 x_scale=(
double)src.height()/src.width();
3526 degrees=DegreesToRadians(degrees);
3528 if(src.depth() > 8){
3530 for(y=0; y < src.height(); y++){
3531 p = (
unsigned int *)src.scanLine(y);
3532 q = (
unsigned int *)dest.scanLine(y);
3533 y_distance = y_scale*(y-y_center);
3534 for(x=0; x < src.width(); x++){
3537 x_distance = x_scale*(x-x_center);
3538 distance = x_distance*x_distance+y_distance*y_distance;
3539 if (distance < (radius*radius)){
3541 factor = 1.0-sqrt(distance)/radius;
3542 sine = sin(degrees*factor*factor);
3543 cosine = cos(degrees*factor*factor);
3544 *q = interpolateColor(&src,
3545 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3546 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3556 unsigned int *cTable = (
unsigned int *)src.tqcolorTable();
3557 for(y=0; y < src.height(); y++){
3558 p = (
unsigned char *)src.scanLine(y);
3559 q = (
unsigned int *)dest.scanLine(y);
3560 y_distance = y_scale*(y-y_center);
3561 for(x=0; x < src.width(); x++){
3563 *q = *(cTable+(*p));
3564 x_distance = x_scale*(x-x_center);
3565 distance = x_distance*x_distance+y_distance*y_distance;
3566 if (distance < (radius*radius)){
3568 factor = 1.0-sqrt(distance)/radius;
3569 sine = sin(degrees*factor*factor);
3570 cosine = cos(degrees*factor*factor);
3571 *q = interpolateColor(&src,
3572 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3573 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3586 unsigned int background)
3592 TQImage dest(src.width(), src.height() + (int)(2*fabs(amplitude)), 32);
3594 sine_map = (
double *)malloc(dest.width()*
sizeof(double));
3597 for(x=0; x < dest.width(); ++x)
3598 sine_map[x]=fabs(amplitude)+amplitude*sin((2*M_PI*x)/wavelength);
3600 for(y=0; y < dest.height(); ++y){
3601 q = (
unsigned int *)dest.scanLine(y);
3602 for (x=0; x < dest.width(); x++){
3603 *q=interpolateColor(&src, x, (
int)(y-sine_map[x]), background);
3626 unsigned long count ;
3627 unsigned long histogram[256];
3630 int x, y, mx, my, sx, sy;
3632 unsigned int *s=0, *q;
3634 if(src.depth() < 32)
3635 src.convertDepth(32);
3639 width = getOptimalKernelWidth(radius, 0.5);
3640 if(src.width() < width){
3641 qWarning(
"KImageEffect::oilPaintConvolve(): Image is smaller than radius!");
3651 unsigned int **jumpTable = (
unsigned int **)src.jumpTable();
3652 for(y=0; y < dest.height(); ++y){
3654 q = (
unsigned int *)dest.scanLine(y);
3655 for(x=0; x < dest.width(); ++x){
3657 memset(histogram, 0, 256*
sizeof(
unsigned long));
3660 for(mcy=0; mcy < width; ++mcy, ++sy){
3661 my = sy < 0 ? 0 : sy > src.height()-1 ?
3662 src.height()-1 : sy;
3664 for(mcx=0; mcx < width; ++mcx, ++sx){
3665 mx = sx < 0 ? 0 : sx > src.width()-1 ?
3668 k = intensityValue(jumpTable[my][mx]);
3670 qWarning(
"KImageEffect::oilPaintConvolve(): k is %d",
3675 if(histogram[k] > count){
3676 count = histogram[k];
3677 s = jumpTable[my]+mx;
3697 TQImage img(
edge(src, radius));
3698 img =
blur(img, radius, sigma);
3700 img.invertPixels(
false);
3707 struct double_packet high, low, intensity, *histogram;
3708 struct short_packet *normalize_map;
3709 TQ_INT64 number_pixels;
3711 unsigned int *p, *q;
3713 unsigned long threshold_intensity;
3714 unsigned char r, g, b, a;
3716 if(image.depth() < 32)
3717 image = image.convertDepth(32);
3719 histogram = (
struct double_packet *)
3720 malloc(256*
sizeof(
struct double_packet));
3721 normalize_map = (
struct short_packet *)
3722 malloc(256*
sizeof(
struct short_packet));
3724 if(!histogram || !normalize_map){
3726 liberateMemory(&histogram);
3728 liberateMemory(&normalize_map);
3729 qWarning(
"KImageEffect::normalize(): Unable to allocate memory!");
3736 memset(histogram, 0, 256*
sizeof(
struct double_packet));
3737 for(y=0; y < image.height(); ++y){
3738 p = (
unsigned int *)image.scanLine(y);
3739 for(x=0; x < image.width(); ++x){
3740 histogram[(
unsigned char)(tqRed(*p))].red++;
3741 histogram[(
unsigned char)(tqGreen(*p))].green++;
3742 histogram[(
unsigned char)(tqBlue(*p))].blue++;
3743 histogram[(
unsigned char)(tqAlpha(*p))].alpha++;
3751 number_pixels = (TQ_INT64)image.width()*image.height();
3752 threshold_intensity = number_pixels/1000;
3755 memset(&intensity, 0,
sizeof(
struct double_packet));
3756 memset(&high, 0,
sizeof(
struct double_packet));
3757 memset(&low, 0,
sizeof(
struct double_packet));
3758 for(high.red=255; high.red != 0; high.red--){
3759 intensity.red+=histogram[(
unsigned char)high.red].red;
3760 if(intensity.red > threshold_intensity)
3763 if(low.red == high.red){
3764 threshold_intensity = 0;
3765 memset(&intensity, 0,
sizeof(
struct double_packet));
3766 for(low.red=0; low.red < 255; low.red++){
3767 intensity.red+=histogram[(
unsigned char)low.red].red;
3768 if(intensity.red > threshold_intensity)
3771 memset(&intensity, 0,
sizeof(
struct double_packet));
3772 for(high.red=255; high.red != 0; high.red--){
3773 intensity.red+=histogram[(
unsigned char)high.red].red;
3774 if(intensity.red > threshold_intensity)
3780 memset(&intensity, 0,
sizeof(
struct double_packet));
3781 for(high.green=255; high.green != 0; high.green--){
3782 intensity.green+=histogram[(
unsigned char)high.green].green;
3783 if(intensity.green > threshold_intensity)
3786 if(low.green == high.green){
3787 threshold_intensity = 0;
3788 memset(&intensity, 0,
sizeof(
struct double_packet));
3789 for(low.green=0; low.green < 255; low.green++){
3790 intensity.green+=histogram[(
unsigned char)low.green].green;
3791 if(intensity.green > threshold_intensity)
3794 memset(&intensity,0,
sizeof(
struct double_packet));
3795 for(high.green=255; high.green != 0; high.green--){
3796 intensity.green+=histogram[(
unsigned char)high.green].green;
3797 if(intensity.green > threshold_intensity)
3803 memset(&intensity, 0,
sizeof(
struct double_packet));
3804 for(high.blue=255; high.blue != 0; high.blue--){
3805 intensity.blue+=histogram[(
unsigned char)high.blue].blue;
3806 if(intensity.blue > threshold_intensity)
3809 if(low.blue == high.blue){
3810 threshold_intensity = 0;
3811 memset(&intensity, 0,
sizeof(
struct double_packet));
3812 for(low.blue=0; low.blue < 255; low.blue++){
3813 intensity.blue+=histogram[(
unsigned char)low.blue].blue;
3814 if(intensity.blue > threshold_intensity)
3817 memset(&intensity,0,
sizeof(
struct double_packet));
3818 for(high.blue=255; high.blue != 0; high.blue--){
3819 intensity.blue+=histogram[(
unsigned char)high.blue].blue;
3820 if(intensity.blue > threshold_intensity)
3826 memset(&intensity, 0,
sizeof(
struct double_packet));
3827 for(high.alpha=255; high.alpha != 0; high.alpha--){
3828 intensity.alpha+=histogram[(
unsigned char)high.alpha].alpha;
3829 if(intensity.alpha > threshold_intensity)
3832 if(low.alpha == high.alpha){
3833 threshold_intensity = 0;
3834 memset(&intensity, 0,
sizeof(
struct double_packet));
3835 for(low.alpha=0; low.alpha < 255; low.alpha++){
3836 intensity.alpha+=histogram[(
unsigned char)low.alpha].alpha;
3837 if(intensity.alpha > threshold_intensity)
3840 memset(&intensity,0,
sizeof(
struct double_packet));
3841 for(high.alpha=255; high.alpha != 0; high.alpha--){
3842 intensity.alpha+=histogram[(
unsigned char)high.alpha].alpha;
3843 if(intensity.alpha > threshold_intensity)
3847 liberateMemory(&histogram);
3854 memset(normalize_map, 0 ,256*
sizeof(
struct short_packet));
3855 for(i=0; i <= (long) 255; i++){
3856 if(i < (
long) low.red)
3857 normalize_map[i].red=0;
3858 else if (i > (
long) high.red)
3859 normalize_map[i].red=65535;
3860 else if (low.red != high.red)
3861 normalize_map[i].red =
3862 (
unsigned short)((65535*(i-low.red))/(high.red-low.red));
3864 if(i < (
long) low.green)
3865 normalize_map[i].green=0;
3866 else if (i > (
long) high.green)
3867 normalize_map[i].green=65535;
3868 else if (low.green != high.green)
3869 normalize_map[i].green =
3870 (
unsigned short)((65535*(i-low.green))/(high.green-low.green));
3872 if(i < (
long) low.blue)
3873 normalize_map[i].blue=0;
3874 else if (i > (
long) high.blue)
3875 normalize_map[i].blue=65535;
3876 else if (low.blue != high.blue)
3877 normalize_map[i].blue =
3878 (
unsigned short)((65535*(i-low.blue))/(high.blue-low.blue));
3880 if(i < (
long) low.alpha)
3881 normalize_map[i].alpha=0;
3882 else if (i > (
long) high.alpha)
3883 normalize_map[i].alpha=65535;
3884 else if (low.alpha != high.alpha)
3885 normalize_map[i].alpha =
3886 (
unsigned short)((65535*(i-low.alpha))/(high.alpha-low.alpha));
3890 for(y=0; y < image.height(); ++y){
3891 q = (
unsigned int *)image.scanLine(y);
3892 for(x=0; x < image.width(); ++x){
3893 if(low.red != high.red)
3894 r = (normalize_map[(
unsigned short)(tqRed(q[x]))].red)/257;
3897 if(low.green != high.green)
3898 g = (normalize_map[(
unsigned short)(tqGreen(q[x]))].green)/257;
3901 if(low.blue != high.blue)
3902 b = (normalize_map[(
unsigned short)(tqBlue(q[x]))].blue)/257;
3905 if(low.alpha != high.alpha)
3906 a = (normalize_map[(
unsigned short)(tqAlpha(q[x]))].alpha)/257;
3909 q[x] = tqRgba(r, g, b, a);
3912 liberateMemory(&normalize_map);
3917 struct double_packet high, low, intensity, *map, *histogram;
3918 struct short_packet *equalize_map;
3920 unsigned int *p, *q;
3922 unsigned char r, g, b, a;
3924 if(image.depth() < 32)
3925 image = image.convertDepth(32);
3927 histogram=(
struct double_packet *) malloc(256*
sizeof(
struct double_packet));
3928 map=(
struct double_packet *) malloc(256*
sizeof(
struct double_packet));
3929 equalize_map=(
struct short_packet *)malloc(256*
sizeof(
struct short_packet));
3930 if(!histogram || !map || !equalize_map){
3932 liberateMemory(&histogram);
3934 liberateMemory(&map);
3936 liberateMemory(&equalize_map);
3937 qWarning(
"KImageEffect::equalize(): Unable to allocate memory!");
3944 memset(histogram, 0, 256*
sizeof(
struct double_packet));
3945 for(y=0; y < image.height(); ++y){
3946 p = (
unsigned int *)image.scanLine(y);
3947 for(x=0; x < image.width(); ++x){
3948 histogram[(
unsigned char)(tqRed(*p))].red++;
3949 histogram[(
unsigned char)(tqGreen(*p))].green++;
3950 histogram[(
unsigned char)(tqBlue(*p))].blue++;
3951 histogram[(
unsigned char)(tqAlpha(*p))].alpha++;
3958 memset(&intensity, 0 ,
sizeof(
struct double_packet));
3959 for(i=0; i <= 255; ++i){
3960 intensity.red += histogram[i].red;
3961 intensity.green += histogram[i].green;
3962 intensity.blue += histogram[i].blue;
3963 intensity.alpha += histogram[i].alpha;
3968 memset(equalize_map, 0, 256*
sizeof(short_packet));
3969 for(i=0; i <= 255; ++i){
3970 if(high.red != low.red)
3971 equalize_map[i].red=(
unsigned short)
3972 ((65535*(map[i].red-low.red))/(high.red-low.red));
3973 if(high.green != low.green)
3974 equalize_map[i].green=(
unsigned short)
3975 ((65535*(map[i].green-low.green))/(high.green-low.green));
3976 if(high.blue != low.blue)
3977 equalize_map[i].blue=(
unsigned short)
3978 ((65535*(map[i].blue-low.blue))/(high.blue-low.blue));
3979 if(high.alpha != low.alpha)
3980 equalize_map[i].alpha=(
unsigned short)
3981 ((65535*(map[i].alpha-low.alpha))/(high.alpha-low.alpha));
3983 liberateMemory(&histogram);
3984 liberateMemory(&map);
3989 for(y=0; y < image.height(); ++y){
3990 q = (
unsigned int *)image.scanLine(y);
3991 for(x=0; x < image.width(); ++x){
3992 if(low.red != high.red)
3993 r = (equalize_map[(
unsigned short)(tqRed(q[x]))].red/257);
3996 if(low.green != high.green)
3997 g = (equalize_map[(
unsigned short)(tqGreen(q[x]))].green/257);
4000 if(low.blue != high.blue)
4001 b = (equalize_map[(
unsigned short)(tqBlue(q[x]))].blue/257);
4004 if(low.alpha != high.alpha)
4005 a = (equalize_map[(
unsigned short)(tqAlpha(q[x]))].alpha/257);
4008 q[x] = tqRgba(r, g, b, a);
4011 liberateMemory(&equalize_map);
4029 width = getOptimalKernelWidth(radius, 0.5);
4030 if(image.width() < width || image.height() < width){
4031 qWarning(
"KImageEffect::edge(): Image is smaller than radius!");
4034 kernel= (
double *)malloc(width*width*
sizeof(
double));
4036 qWarning(
"KImageEffect::edge(): Unable to allocate memory!");
4039 for(i=0; i < (width*width); i++)
4041 kernel[i/2]=width*width-1.0;
4042 convolveImage(&image, &dest, width, kernel);
4050 return(
emboss(src, 0, 1));
4055 double alpha, *kernel;
4061 qWarning(
"KImageEffect::emboss(): Zero sigma is not permitted!");
4065 width = getOptimalKernelWidth(radius, sigma);
4066 if(image.width() < width || image.height() < width){
4067 qWarning(
"KImageEffect::emboss(): Image is smaller than radius!");
4070 kernel= (
double *)malloc(width*width*
sizeof(
double));
4072 qWarning(
"KImageEffect::emboss(): Unable to allocate memory!");
4075 if(image.depth() < 32)
4076 image = image.convertDepth(32);
4080 for(v=(-width/2); v <= (width/2); v++){
4081 for(u=(-width/2); u <= (width/2); u++){
4082 alpha=exp(-((
double) u*u+v*v)/(2.0*sigma*sigma));
4083 kernel[i]=((u < 0) || (v < 0) ? -8.0 : 8.0)*alpha/
4084 (2.0*MagickPI*sigma*sigma);
4091 convolveImage(&image, &dest, width, kernel);
4092 liberateMemory(&kernel);
4098 void KImageEffect::blurScanLine(
double *kernel,
int width,
4099 unsigned int *src,
unsigned int *dest,
4106 double red, green, blue, alpha;
4109 if(width > columns){
4110 for(x=0; x < columns; ++x){
4112 red = blue = green = alpha = 0.0;
4115 for(i=0; i < columns; ++i){
4116 if((i >= (x-width/2)) && (i <= (x+width/2))){
4117 red += (*p)*(tqRed(*q)*257);
4118 green += (*p)*(tqGreen(*q)*257);
4119 blue += (*p)*(tqBlue(*q)*257);
4120 alpha += (*p)*(tqAlpha(*q)*257);
4122 if(((i+width/2-x) >= 0) && ((i+width/2-x) < width))
4123 scale+=kernel[i+width/2-x];
4128 red = scale*(red+0.5);
4129 green = scale*(green+0.5);
4130 blue = scale*(blue+0.5);
4131 alpha = scale*(alpha+0.5);
4133 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4134 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4135 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4136 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4138 dest[x] = tqRgba((
unsigned char)(red/257UL),
4139 (
unsigned char)(green/257UL),
4140 (
unsigned char)(blue/257UL),
4141 (
unsigned char)(alpha/257UL));
4146 for(x=0; x < width/2; ++x){
4148 red = blue = green = alpha = 0.0;
4149 p = kernel+width/2-x;
4151 for(i=width/2-x; i < width; ++i){
4152 red += (*p)*(tqRed(*q)*257);
4153 green += (*p)*(tqGreen(*q)*257);
4154 blue += (*p)*(tqBlue(*q)*257);
4155 alpha += (*p)*(tqAlpha(*q)*257);
4162 red = scale*(red+0.5);
4163 green = scale*(green+0.5);
4164 blue = scale*(blue+0.5);
4165 alpha = scale*(alpha+0.5);
4167 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4168 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4169 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4170 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4172 dest[x] = tqRgba((
unsigned char)(red/257UL),
4173 (
unsigned char)(green/257UL),
4174 (
unsigned char)(blue/257UL),
4175 (
unsigned char)(alpha/257UL));
4178 for(; x < columns-width/2; ++x){
4179 red = blue = green = alpha = 0.0;
4181 q = src+(x-width/2);
4182 for (i=0; i < (long) width; ++i){
4183 red += (*p)*(tqRed(*q)*257);
4184 green += (*p)*(tqGreen(*q)*257);
4185 blue += (*p)*(tqBlue(*q)*257);
4186 alpha += (*p)*(tqAlpha(*q)*257);
4190 red = scale*(red+0.5);
4191 green = scale*(green+0.5);
4192 blue = scale*(blue+0.5);
4193 alpha = scale*(alpha+0.5);
4195 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4196 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4197 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4198 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4200 dest[x] = tqRgba((
unsigned char)(red/257UL),
4201 (
unsigned char)(green/257UL),
4202 (
unsigned char)(blue/257UL),
4203 (
unsigned char)(alpha/257UL));
4206 for(; x < columns; ++x){
4207 red = blue = green = alpha = 0.0;
4210 q = src+(x-width/2);
4211 for(i=0; i < columns-x+width/2; ++i){
4212 red += (*p)*(tqRed(*q)*257);
4213 green += (*p)*(tqGreen(*q)*257);
4214 blue += (*p)*(tqBlue(*q)*257);
4215 alpha += (*p)*(tqAlpha(*q)*257);
4221 red = scale*(red+0.5);
4222 green = scale*(green+0.5);
4223 blue = scale*(blue+0.5);
4224 alpha = scale*(alpha+0.5);
4226 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4227 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4228 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4229 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4231 dest[x] = tqRgba((
unsigned char)(red/257UL),
4232 (
unsigned char)(green/257UL),
4233 (
unsigned char)(blue/257UL),
4234 (
unsigned char)(alpha/257UL));
4238 int KImageEffect::getBlurKernel(
int width,
double sigma,
double **kernel)
4240 #define KernelRank 3
4245 assert(sigma != 0.0);
4248 *kernel=(
double *)malloc(width*
sizeof(
double));
4249 if(*kernel == (
double *)NULL)
4251 memset(*kernel, 0, width*
sizeof(
double));
4252 bias = KernelRank*width/2;
4253 for(i=(-bias); i <= bias; i++){
4254 alpha=exp(-((
double) i*i)/(2.0*KernelRank*KernelRank*sigma*sigma));
4255 (*kernel)[(i+bias)/KernelRank]+=alpha/(MagickSQ2PI*sigma);
4258 for(i=0; i < width; i++)
4259 normalize+=(*kernel)[i];
4260 for(i=0; i < width; i++)
4269 return(
blur(src, 0, 1));
4278 unsigned int *scanline, *temp;
4279 unsigned int *p, *q;
4282 qWarning(
"KImageEffect::blur(): Zero sigma is not permitted!");
4285 if(src.depth() < 32)
4286 src = src.convertDepth(32);
4288 kernel=(
double *) NULL;
4290 width=getBlurKernel((
int) (2*ceil(radius)+1),sigma,&kernel);
4292 double *last_kernel;
4293 last_kernel=(
double *) NULL;
4294 width=getBlurKernel(3,sigma,&kernel);
4296 while ((
long) (MaxRGB*kernel[0]) > 0){
4297 if(last_kernel != (
double *)NULL){
4298 liberateMemory(&last_kernel);
4301 kernel = (
double *)NULL;
4302 width = getBlurKernel(width+2, sigma, &kernel);
4304 if(last_kernel != (
double *) NULL){
4305 liberateMemory(&kernel);
4307 kernel = last_kernel;
4312 qWarning(
"KImageEffect::blur(): Kernel radius is too small!");
4313 liberateMemory(&kernel);
4317 dest.create(src.width(), src.height(), 32);
4320 scanline = (
unsigned int *)malloc(
sizeof(
unsigned int)*src.height());
4321 temp = (
unsigned int *)malloc(
sizeof(
unsigned int)*src.height());
4322 for(y=0; y < src.height(); ++y){
4323 p = (
unsigned int *)src.scanLine(y);
4324 q = (
unsigned int *)dest.scanLine(y);
4325 blurScanLine(kernel, width, p, q, src.width());
4328 TQImage partial = dest;
4331 unsigned int **srcTable = (
unsigned int **)partial.jumpTable();
4332 unsigned int **destTable = (
unsigned int **)dest.jumpTable();
4333 for(x=0; x < partial.width(); ++x){
4334 for(y=0; y < partial.height(); ++y){
4335 scanline[y] = srcTable[y][x];
4337 blurScanLine(kernel, width, scanline, temp, partial.height());
4338 for(y=0; y < partial.height(); ++y){
4339 destTable[y][x] = temp[y];
4348 bool KImageEffect::convolveImage(TQImage *image, TQImage *dest,
4349 const unsigned int order,
4350 const double *kernel)
4353 double red, green, blue, alpha;
4357 int x, y, mx, my, sx, sy;
4362 if((width % 2) == 0){
4363 qWarning(
"KImageEffect: Kernel width must be an odd number!");
4366 normal_kernel = (
double *)malloc(width*width*
sizeof(
double));
4368 qWarning(
"KImageEffect: Unable to allocate memory!");
4372 dest->create(image->width(), image->height(), 32);
4373 if(image->depth() < 32)
4374 *image = image->convertDepth(32);
4377 for(i=0; i < (width*width); i++)
4378 normalize += kernel[i];
4379 if(fabs(normalize) <= MagickEpsilon)
4382 for(i=0; i < (width*width); i++)
4383 normal_kernel[i] = normalize*kernel[i];
4385 unsigned int **jumpTable = (
unsigned int **)image->jumpTable();
4386 for(y=0; y < dest->height(); ++y){
4388 q = (
unsigned int *)dest->scanLine(y);
4389 for(x=0; x < dest->width(); ++x){
4391 red = green = blue = alpha = 0;
4393 for(mcy=0; mcy < width; ++mcy, ++sy){
4394 my = sy < 0 ? 0 : sy > image->height()-1 ?
4395 image->height()-1 : sy;
4397 for(mcx=0; mcx < width; ++mcx, ++sx){
4398 mx = sx < 0 ? 0 : sx > image->width()-1 ?
4399 image->width()-1 : sx;
4400 red += (*k)*(tqRed(jumpTable[my][mx])*257);
4401 green += (*k)*(tqGreen(jumpTable[my][mx])*257);
4402 blue += (*k)*(tqBlue(jumpTable[my][mx])*257);
4403 alpha += (*k)*(tqAlpha(jumpTable[my][mx])*257);
4408 red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
4409 green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
4410 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
4411 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
4413 *q++ = tqRgba((
unsigned char)(red/257UL),
4414 (
unsigned char)(green/257UL),
4415 (
unsigned char)(blue/257UL),
4416 (
unsigned char)(alpha/257UL));
4419 free(normal_kernel);
4424 int KImageEffect::getOptimalKernelWidth(
double radius,
double sigma)
4430 assert(sigma != 0.0);
4432 return((
int)(2.0*ceil(radius)+1.0));
4435 for(u=(-width/2); u <= (width/2); u++)
4436 normalize+=exp(-((
double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma);
4438 value=exp(-((
double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma)/normalize;
4439 if((
long)(65535*value) <= 0)
4443 return((
int)width-2);
4460 qWarning(
"KImageEffect::sharpen(): Zero sigma is not permitted!");
4463 width = getOptimalKernelWidth(radius, sigma);
4464 if(image.width() < width){
4465 qWarning(
"KImageEffect::sharpen(): Image is smaller than radius!");
4468 kernel = (
double *)malloc(width*width*
sizeof(
double));
4470 qWarning(
"KImageEffect::sharpen(): Unable to allocate memory!");
4476 for(v=(-width/2); v <= (width/2); v++){
4477 for(u=(-width/2); u <= (width/2); u++){
4478 alpha=exp(-((
double) u*u+v*v)/(2.0*sigma*sigma));
4479 kernel[i]=alpha/(2.0*MagickPI*sigma*sigma);
4480 normalize+=kernel[i];
4485 convolveImage(&image, &dest, width, kernel);
4499 double distance, normal_distance,
shade;
4502 struct PointInfo light, normal;
4506 TQImage dest(src.width(), src.height(), 32);
4508 azimuth = DegreesToRadians(azimuth);
4509 elevation = DegreesToRadians(elevation);
4510 light.x = MaxRGB*cos(azimuth)*cos(elevation);
4511 light.y = MaxRGB*sin(azimuth)*cos(elevation);
4512 light.z = MaxRGB*sin(elevation);
4515 if(src.depth() > 8){
4516 unsigned int *p, *s0, *s1, *s2;
4517 for(y=0; y < src.height(); ++y){
4518 p = (
unsigned int *)src.scanLine(QMIN(QMAX(y-1,0),src.height()-3));
4519 q = (
unsigned int *)dest.scanLine(y);
4521 *q++=(*(p+src.width()));
4524 s1 = p + src.width();
4525 s2 = p + 2*src.width();
4526 for(x=1; x < src.width()-1; ++x){
4528 normal.x=intensityValue(*(s0-1))+intensityValue(*(s1-1))+intensityValue(*(s2-1))-
4529 (double) intensityValue(*(s0+1))-(
double) intensityValue(*(s1+1))-
4530 (double) intensityValue(*(s2+1));
4531 normal.y=intensityValue(*(s2-1))+intensityValue(*s2)+intensityValue(*(s2+1))-
4532 (double) intensityValue(*(s0-1))-(
double) intensityValue(*s0)-
4533 (double) intensityValue(*(s0+1));
4534 if((normal.x == 0) && (normal.y == 0))
4538 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4539 if (distance > 0.0){
4541 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
4542 if(fabs(normal_distance) > 0.0000001)
4543 shade=distance/sqrt(normal_distance);
4547 *q = tqRgba((
unsigned char)(shade),
4548 (
unsigned char)(shade),
4549 (
unsigned char)(shade),
4553 *q = tqRgba((
unsigned char)((shade*tqRed(*s1))/(MaxRGB+1)),
4554 (
unsigned char)((shade*tqGreen(*s1))/(MaxRGB+1)),
4555 (
unsigned char)((shade*tqBlue(*s1))/(MaxRGB+1)),
4567 unsigned char *p, *s0, *s1, *s2;
4569 unsigned int *cTable = (
unsigned int *)src.tqcolorTable();
4570 for(y=0; y < src.height(); ++y){
4571 scanLineIdx = QMIN(QMAX(y-1,0),src.height()-3);
4572 p = (
unsigned char *)src.scanLine(scanLineIdx);
4573 q = (
unsigned int *)dest.scanLine(y);
4576 s1 = (
unsigned char *) src.scanLine(scanLineIdx+1);
4577 s2 = (
unsigned char *) src.scanLine(scanLineIdx+2);
4578 *q++=(*(cTable+(*s1)));
4583 for(x=1; x < src.width()-1; ++x){
4585 normal.x=intensityValue(*(cTable+(*(s0-1))))+intensityValue(*(cTable+(*(s1-1))))+intensityValue(*(cTable+(*(s2-1))))-
4586 (double) intensityValue(*(cTable+(*(s0+1))))-(
double) intensityValue(*(cTable+(*(s1+1))))-
4587 (double) intensityValue(*(cTable+(*(s2+1))));
4588 normal.y=intensityValue(*(cTable+(*(s2-1))))+intensityValue(*(cTable+(*s2)))+intensityValue(*(cTable+(*(s2+1))))-
4589 (double) intensityValue(*(cTable+(*(s0-1))))-(
double) intensityValue(*(cTable+(*s0)))-
4590 (double) intensityValue(*(cTable+(*(s0+1))));
4591 if((normal.x == 0) && (normal.y == 0))
4595 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4596 if (distance > 0.0){
4598 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
4599 if(fabs(normal_distance) > 0.0000001)
4600 shade=distance/sqrt(normal_distance);
4604 *q = tqRgba((
unsigned char)(shade),
4605 (
unsigned char)(shade),
4606 (
unsigned char)(shade),
4607 tqAlpha(*(cTable+(*s1))));
4610 *q = tqRgba((
unsigned char)((shade*tqRed(*(cTable+(*s1))))/(MaxRGB+1)),
4611 (
unsigned char)((shade*tqGreen(*(cTable+(*s1))))/(MaxRGB+1)),
4612 (
unsigned char)((shade*tqBlue(*(cTable+(*s1))))/(MaxRGB+1)),
4620 *q++=(*(cTable+(*s1)));
4635 double brightness, scale, theta;
4639 sign = sharpen ? 1 : -1;
4640 scale=0.5000000000000001;
4641 if(img.depth() > 8){
4642 count = img.width()*img.height();
4643 data = (
unsigned int *)img.bits();
4646 count = img.numColors();
4647 data = (
unsigned int *)img.tqcolorTable();
4649 for(i=0; i < count; ++i){
4652 brightness = v/255.0;
4653 theta=(brightness-0.5)*M_PI;
4654 brightness+=scale*(((scale*((sin(theta)+1.0)))-brightness)*sign);
4655 if (brightness > 1.0)
4660 v = (int)(brightness*255);
4662 data[i] = tqRgba(c.red(), c.green(), c.blue(), tqAlpha(data[i]));
4667 struct BumpmapParams {
4668 BumpmapParams(
double bm_azimuth,
double bm_elevation,
4672 double azimuth = DegreesToRadians( bm_azimuth );
4673 double elevation = DegreesToRadians( bm_elevation );
4676 lx = (int)( cos(azimuth) * cos(elevation) * 255.0 );
4677 ly = (int)( sin(azimuth) * cos(elevation) * 255.0 );
4678 int lz = (int)( sin(elevation) * 255.0 );
4681 int nz = (6 * 255) / bm_depth;
4689 compensation = sin(elevation);
4692 for (
int i = 0; i < 256; i++)
4697 case KImageEffect::Spherical:
4698 n = i / 255.0 - 1.0;
4699 lut[i] = (int) (255.0 * sqrt(1.0 - n * n) + 0.5);
4702 case KImageEffect::Sinuosidal:
4704 lut[i] = (int) (255.0 * (sin((-M_PI / 2.0) + M_PI * n) + 1.0) /
4708 case KImageEffect::Linear:
4714 lut[i] = 255 - lut[i];
4720 double compensation;
4725 static void bumpmap_convert_row( uint *row,
4736 has_alpha = has_alpha ? 1 : 0;
4739 for (; width; width--)
4742 unsigned int idx = (
unsigned int)(intensityValue( *row ) + 0.5);
4743 *p++ = lut[(
unsigned int) ( waterlevel +
4745 waterlevel) * tqBlue( *row )) / 255.0 )];
4747 unsigned int idx = (
unsigned int)(intensityValue( *row ) + 0.5);
4755 static void bumpmap_row( uint *src,
4766 bool row_in_bumpmap,
4769 BumpmapParams *params )
4771 int xofs1, xofs2, xofs3;
4779 xofs2 = MOD(tmp, bm_width);
4781 for (x = 0; x < width; x++)
4785 if (tiled || (row_in_bumpmap &&
4786 x >= - tmp && x < - tmp + bm_width)) {
4788 xofs1 = MOD(xofs2 - 1, bm_width);
4789 xofs3 = MOD(xofs2 + 1, bm_width);
4791 xofs1 = FXCLAMP(xofs2 - 1, 0, bm_width - 1);
4792 xofs3 = FXCLAMP(xofs2 + 1, 0, bm_width - 1);
4794 nx = (bm_row1[xofs1] + bm_row2[xofs1] + bm_row3[xofs1] -
4795 bm_row1[xofs3] - bm_row2[xofs3] - bm_row3[xofs3]);
4796 ny = (bm_row3[xofs1] + bm_row3[xofs2] + bm_row3[xofs3] -
4797 bm_row1[xofs1] - bm_row1[xofs2] - bm_row1[xofs3]);
4804 if ((nx == 0) && (ny == 0))
4805 shade = params->background;
4807 ndotl = nx * params->lx + ny * params->ly + params->nzlz;
4810 shade = (int)( params->compensation * ambient );
4812 shade = (int)( ndotl / sqrt(
double(nx * nx + ny * ny + params->nz2)) );
4814 shade = (int)( shade + QMAX(0.0, (255 * params->compensation - shade)) *
4826 int red = (int)((tqRed( *src ) * shade) / (params->compensation * 255));
4827 int green = (int)((tqGreen( *src ) * shade) / (params->compensation * 255));
4828 int blue = (int)((tqBlue( *src ) * shade) / (params->compensation * 255));
4829 int alpha = (int)((tqAlpha( *src ) * shade) / (params->compensation * 255));
4831 *dest++ = tqRgba( red, green, blue, alpha );
4833 int red = tqRed( *src ) * shade / 255;
4834 int green = tqGreen( *src ) * shade / 255;
4835 int blue = tqBlue( *src ) * shade / 255;
4836 int alpha = tqAlpha( *src ) * shade / 255;
4838 *dest++ = tqRgba( red, green, blue, alpha );
4843 if (++xofs2 == bm_width)
4868 int depth,
int xofs,
int yofs,
int waterlevel,
4869 int ambient,
bool compensate,
bool invert,
4874 if ( img.depth() != 32 || img.depth() != 32 ) {
4875 qWarning(
"Bump-mapping effect works only with 32 bit images");
4879 dst.create( img.width(), img.height(), img.depth() );
4880 int bm_width = map.width();
4881 int bm_height = map.height();
4882 int bm_bpp = map.depth();
4883 int bm_has_alpha = map.hasAlphaBuffer();
4885 int yofs1, yofs2, yofs3;
4888 yofs2 = MOD( yofs, bm_height );
4889 yofs1 = MOD( yofs2 - 1, bm_height);
4890 yofs3 = MOD( yofs2 + 1, bm_height);
4894 yofs3 = FXCLAMP( yofs2+1, 0, bm_height - 1 );
4897 BumpmapParams params( azimuth, elevation, depth, type, invert );
4899 uint* bm_row1 = (
unsigned int*)map.scanLine( yofs1 );
4900 uint* bm_row2 = (
unsigned int*)map.scanLine( yofs2 );
4901 uint* bm_row3 = (
unsigned int*)map.scanLine( yofs3 );
4903 bumpmap_convert_row( bm_row1, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4904 bumpmap_convert_row( bm_row2, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4905 bumpmap_convert_row( bm_row3, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4907 for (
int y = 0; y < img.height(); ++y)
4909 int row_in_bumpmap = (y >= - yofs && y < - yofs + bm_height);
4911 uint* src_row = (
unsigned int*)img.scanLine( y );
4912 uint* dest_row = (
unsigned int*)dst.scanLine( y );
4914 bumpmap_row( src_row, dest_row, img.width(), img.depth(), img.hasAlphaBuffer(),
4915 bm_row1, bm_row2, bm_row3, bm_width, xofs,
4917 row_in_bumpmap, ambient, compensate,
4922 if (tiled || row_in_bumpmap)
4924 uint* bm_tmprow = bm_row1;
4927 bm_row3 = bm_tmprow;
4929 if (++yofs2 == bm_height)
4933 yofs3 = MOD(yofs2 + 1, bm_height);
4935 yofs3 = FXCLAMP(yofs2 + 1, 0, bm_height - 1);
4937 bm_row3 = (
unsigned int*)map.scanLine( yofs3 );
4938 bumpmap_convert_row( bm_row3, bm_width, bm_bpp, bm_has_alpha,
4939 params.lut, waterlevel );
4954 TQImage alphaImage = input;
4955 if (!alphaImage.isNull()) alphaImage = alphaImage.convertDepth( 32 );
4957 int w = alphaImage.width();
4958 int h = alphaImage.height();
4967 for (
int y = 0; y < h; ++y) {
4968 ls = (TQRgb *)alphaImage.scanLine( y );
4969 for (
int x = 0; x < w; ++x) {
4971 alpha_adjust = (tqAlpha( l )/255.0);
4972 r = int( tqRed( l ) * alpha_adjust );
4973 g = int( tqGreen( l ) * alpha_adjust );
4974 b = int( tqBlue( l ) * alpha_adjust );
4975 a = int( tqAlpha( l ) * 1.0 );
4976 ls[x] = tqRgba( r, g, b, a );