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(TQMAX(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 TQMAX(xtable[0][x], ytable[0][y]) * 2,
321 TQMAX(xtable[1][x], ytable[1][y]) * 2,
323 TQMAX(xtable[2][x], ytable[2][y]) * 2);
325 if (eff == PipeCrossGradient) {
326 rgb = tqRgb(rcb - rSign *
327 TQMIN(xtable[0][x], ytable[0][y]) * 2,
329 TQMIN(xtable[1][x], ytable[1][y]) * 2,
331 TQMIN(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 TQMAX(xtable[0][x], ytable[0][y]) * 2,
570 TQMAX(xtable[1][x], ytable[1][y]) * 2,
572 TQMAX(xtable[2][x], ytable[2][y]) * 2);
574 else if (eff == PipeCrossGradient)
576 scanline[x] = tqRgb(rcb - rSign *
577 TQMIN(xtable[0][x], ytable[0][y]) * 2,
579 TQMIN(xtable[1][x], ytable[1][y]) * 2,
581 TQMIN(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.colorTable();
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");
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.colorTable();
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.colorTable():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);
1082 int pixels = dst.width() * dst.height();
1084 #ifdef USE_SSE2_INLINE_ASM
1086 TQ_UINT16 alpha = TQ_UINT16( ( 1.0 - opacity ) * 256.0 );
1088 KIE8Pack packedalpha = { { alpha, alpha, alpha, 256,
1089 alpha, alpha, alpha, 256 } };
1091 TQ_UINT16 red = TQ_UINT16( clr.red() * 256 * opacity );
1092 TQ_UINT16 green = TQ_UINT16( clr.green() * 256 * opacity );
1093 TQ_UINT16 blue = TQ_UINT16( clr.blue() * 256 * opacity );
1095 KIE8Pack packedcolor = { { blue, green, red, 0,
1096 blue, green, red, 0 } };
1099 __asm__ __volatile__(
1100 "pxor %%xmm7, %%xmm7\n\t"
1101 "movdqu (%0), %%xmm6\n\t"
1102 "movdqu (%1), %%xmm5\n\t"
1103 : :
"r"(&packedalpha),
"r"(&packedcolor),
1104 "m"(packedcolor),
"m"(packedalpha) );
1106 TQ_UINT32 *data =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1109 int offset = (16 - (TQ_UINT32( data ) & 0x0f)) / 4;
1112 int remainder = (pixels - offset) % 8;
1113 pixels -= remainder;
1116 for (
int i = 0; i < offset; i++ ) {
1117 __asm__ __volatile__(
1118 "movd (%0,%1,4), %%xmm0\n\t"
1119 "punpcklbw %%xmm7, %%xmm0\n\t"
1120 "pmullw %%xmm6, %%xmm0\n\t"
1121 "paddw %%xmm5, %%xmm0\n\t"
1122 "psrlw $8, %%xmm0\n\t"
1123 "packuswb %%xmm1, %%xmm0\n\t"
1124 "movd %%xmm0, (%0,%1,4)\n\t"
1125 : :
"r"(data),
"r"(i) );
1129 for (
int i = offset; i < pixels; i += 8 ) {
1132 "movq (%0,%1,4), %%xmm0\n\t"
1133 "movq 8(%0,%1,4), %%xmm1\n\t"
1134 "movq 16(%0,%1,4), %%xmm2\n\t"
1135 "movq 24(%0,%1,4), %%xmm3\n\t"
1138 "prefetchnta 32(%0,%1,4) \n\t"
1141 "punpcklbw %%xmm7, %%xmm0\n\t"
1142 "pmullw %%xmm6, %%xmm0\n\t"
1143 "paddw %%xmm5, %%xmm0\n\t"
1144 "psrlw $8, %%xmm0\n\t"
1147 "punpcklbw %%xmm7, %%xmm1\n\t"
1148 "pmullw %%xmm6, %%xmm1\n\t"
1149 "paddw %%xmm5, %%xmm1\n\t"
1150 "psrlw $8, %%xmm1\n\t"
1153 "punpcklbw %%xmm7, %%xmm2\n\t"
1154 "pmullw %%xmm6, %%xmm2\n\t"
1155 "paddw %%xmm5, %%xmm2\n\t"
1156 "psrlw $8, %%xmm2\n\t"
1159 "punpcklbw %%xmm7, %%xmm3\n\t"
1160 "pmullw %%xmm6, %%xmm3\n\t"
1161 "paddw %%xmm5, %%xmm3\n\t"
1162 "psrlw $8, %%xmm3\n\t"
1165 "packuswb %%xmm1, %%xmm0\n\t"
1166 "packuswb %%xmm3, %%xmm2\n\t"
1169 "movdqa %%xmm0, (%0,%1,4)\n\t"
1170 "movdqa %%xmm2, 16(%0,%1,4)\n\t"
1171 : :
"r"(data),
"r"(i) );
1175 for (
int i = pixels; i < pixels + remainder; i++ ) {
1176 __asm__ __volatile__(
1177 "movd (%0,%1,4), %%xmm0\n\t"
1178 "punpcklbw %%xmm7, %%xmm0\n\t"
1179 "pmullw %%xmm6, %%xmm0\n\t"
1180 "paddw %%xmm5, %%xmm0\n\t"
1181 "psrlw $8, %%xmm0\n\t"
1182 "packuswb %%xmm1, %%xmm0\n\t"
1183 "movd %%xmm0, (%0,%1,4)\n\t"
1184 : :
"r"(data),
"r"(i) );
1189 #ifdef USE_MMX_INLINE_ASM
1191 TQ_UINT16 alpha = TQ_UINT16( ( 1.0 - opacity ) * 256.0 );
1192 KIE4Pack packedalpha = { { alpha, alpha, alpha, 256 } };
1194 TQ_UINT16 red = TQ_UINT16( clr.red() * 256 * opacity );
1195 TQ_UINT16 green = TQ_UINT16( clr.green() * 256 * opacity );
1196 TQ_UINT16 blue = TQ_UINT16( clr.blue() * 256 * opacity );
1198 KIE4Pack packedcolor = { { blue, green, red, 0 } };
1200 __asm__ __volatile__(
1201 "pxor %%mm7, %%mm7\n\t"
1202 "movq (%0), %%mm6\n\t"
1203 "movq (%1), %%mm5\n\t"
1204 : :
"r"(&packedalpha),
"r"(&packedcolor),
"m"(packedcolor),
"m"(packedalpha) );
1206 TQ_UINT32 *data =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1209 int remainder = pixels % 4;
1210 pixels -= remainder;
1213 for (
int i = 0; i < pixels; i += 4 ) {
1214 __asm__ __volatile__(
1216 "movd (%0,%1,4), %%mm0\n\t"
1217 "movd 4(%0,%1,4), %%mm1\n\t"
1218 "movd 8(%0,%1,4), %%mm2\n\t"
1219 "movd 12(%0,%1,4), %%mm3\n\t"
1222 "punpcklbw %%mm7, %%mm0\n\t"
1223 "pmullw %%mm6, %%mm0\n\t"
1224 "paddw %%mm5, %%mm0\n\t"
1225 "psrlw $8, %%mm0\n\t"
1228 "punpcklbw %%mm7, %%mm1\n\t"
1229 "pmullw %%mm6, %%mm1\n\t"
1230 "paddw %%mm5, %%mm1\n\t"
1231 "psrlw $8, %%mm1\n\t"
1234 "punpcklbw %%mm7, %%mm2\n\t"
1235 "pmullw %%mm6, %%mm2\n\t"
1236 "paddw %%mm5, %%mm2\n\t"
1237 "psrlw $8, %%mm2\n\t"
1240 "punpcklbw %%mm7, %%mm3\n\t"
1241 "pmullw %%mm6, %%mm3\n\t"
1242 "paddw %%mm5, %%mm3\n\t"
1243 "psrlw $8, %%mm3\n\t"
1246 "packuswb %%mm1, %%mm0\n\t"
1247 "packuswb %%mm3, %%mm2\n\t"
1250 "movq %%mm0, (%0,%1,4)\n\t"
1251 "movq %%mm2, 8(%0,%1,4)\n\t"
1252 : :
"r"(data),
"r"(i) );
1256 for (
int i = pixels; i < pixels + remainder; i++ ) {
1257 __asm__ __volatile__(
1258 "movd (%0,%1,4), %%mm0\n\t"
1259 "punpcklbw %%mm7, %%mm0\n\t"
1260 "pmullw %%mm6, %%mm0\n\t"
1261 "paddw %%mm5, %%mm0\n\t"
1262 "psrlw $8, %%mm0\n\t"
1263 "packuswb %%mm0, %%mm0\n\t"
1264 "movd %%mm0, (%0,%1,4)\n\t"
1265 : :
"r"(data),
"r"(i) );
1269 __asm__ __volatile__(
"emms");
1274 int rcol, gcol, bcol;
1275 clr.rgb(&rcol, &gcol, &bcol);
1277 #ifdef WORDS_BIGENDIAN
1278 unsigned char *data = (
unsigned char *)dst.bits() + 1;
1280 unsigned char *data = (
unsigned char *)dst.bits();
1283 for (
int i=0; i<pixels; i++)
1285 #ifdef WORDS_BIGENDIAN
1286 *data += (
unsigned char)((rcol - *data) * opacity);
1288 *data += (
unsigned char)((gcol - *data) * opacity);
1290 *data += (
unsigned char)((bcol - *data) * opacity);
1293 *data += (
unsigned char)((bcol - *data) * opacity);
1295 *data += (
unsigned char)((gcol - *data) * opacity);
1297 *data += (
unsigned char)((rcol - *data) * opacity);
1310 if (src.width() <= 0 || src.height() <= 0)
1312 if (dst.width() <= 0 || dst.height() <= 0)
1315 if (src.width() != dst.width() || src.height() != dst.height()) {
1317 std::cerr <<
"WARNING: KImageEffect::blend : src and destination images are not the same size\n";
1322 if (opacity < 0.0 || opacity > 1.0) {
1324 std::cerr <<
"WARNING: KImageEffect::blend : invalid opacity. Range [0, 1]\n";
1329 if (src.depth() != 32) src = src.convertDepth(32);
1330 if (dst.depth() != 32) dst = dst.convertDepth(32);
1332 int pixels = src.width() * src.height();
1334 #ifdef USE_SSE2_INLINE_ASM
1336 TQ_UINT16 alpha = TQ_UINT16( opacity * 256.0 );
1337 KIE8Pack packedalpha = { { alpha, alpha, alpha, 0,
1338 alpha, alpha, alpha, 0 } };
1341 __asm__ __volatile__(
1342 "pxor %%xmm7, %%xmm7\n\t"
1343 "movdqu (%0), %%xmm6\n\t"
1344 : :
"r"(&packedalpha),
"m"(packedalpha) );
1346 TQ_UINT32 *data1 =
reinterpret_cast<TQ_UINT32*
>( src.bits() );
1347 TQ_UINT32 *data2 =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1350 int offset = (16 - (TQ_UINT32( data2 ) & 0x0f)) / 4;
1353 int remainder = (pixels - offset) % 4;
1354 pixels -= remainder;
1357 for (
int i = 0; i < offset; i++ ) {
1358 __asm__ __volatile__(
1359 "movd (%1,%2,4), %%xmm1\n\t"
1360 "punpcklbw %%xmm7, %%xmm1\n\t"
1361 "movd (%0,%2,4), %%xmm0\n\t"
1362 "punpcklbw %%xmm7, %%xmm0\n\t"
1363 "psubw %%xmm1, %%xmm0\n\t"
1364 "pmullw %%xmm6, %%xmm0\n\t"
1365 "psllw $8, %%xmm1\n\t"
1366 "paddw %%xmm1, %%xmm0\n\t"
1367 "psrlw $8, %%xmm0\n\t"
1368 "packuswb %%xmm1, %%xmm0\n\t"
1369 "movd %%xmm0, (%1,%2,4)\n\t"
1370 : :
"r"(data1),
"r"(data2),
"r"(i) );
1374 for (
int i = offset; i < pixels; i += 4 ) {
1375 __asm__ __volatile__(
1377 "movq (%0,%2,4), %%xmm0\n\t"
1378 "movq (%1,%2,4), %%xmm1\n\t"
1379 "movq 8(%0,%2,4), %%xmm2\n\t"
1380 "movq 8(%1,%2,4), %%xmm3\n\t"
1383 "prefetchnta 32(%0,%2,4) \n\t"
1384 "prefetchnta 32(%1,%2,4) \n\t"
1387 "punpcklbw %%xmm7, %%xmm1\n\t"
1388 "punpcklbw %%xmm7, %%xmm0\n\t"
1389 "psubw %%xmm1, %%xmm0\n\t"
1390 "pmullw %%xmm6, %%xmm0\n\t"
1391 "psllw $8, %%xmm1\n\t"
1392 "paddw %%xmm1, %%xmm0\n\t"
1393 "psrlw $8, %%xmm0\n\t"
1396 "punpcklbw %%xmm7, %%xmm3\n\t"
1397 "punpcklbw %%xmm7, %%xmm2\n\t"
1398 "psubw %%xmm3, %%xmm2\n\t"
1399 "pmullw %%xmm6, %%xmm2\n\t"
1400 "psllw $8, %%xmm3\n\t"
1401 "paddw %%xmm3, %%xmm2\n\t"
1402 "psrlw $8, %%xmm2\n\t"
1405 "packuswb %%xmm2, %%xmm0\n\t"
1406 "movdqa %%xmm0, (%1,%2,4)\n\t"
1407 : :
"r"(data1),
"r"(data2),
"r"(i) );
1411 for (
int i = pixels; i < pixels + remainder; i++ ) {
1412 __asm__ __volatile__(
1413 "movd (%1,%2,4), %%xmm1\n\t"
1414 "punpcklbw %%xmm7, %%xmm1\n\t"
1415 "movd (%0,%2,4), %%xmm0\n\t"
1416 "punpcklbw %%xmm7, %%xmm0\n\t"
1417 "psubw %%xmm1, %%xmm0\n\t"
1418 "pmullw %%xmm6, %%xmm0\n\t"
1419 "psllw $8, %%xmm1\n\t"
1420 "paddw %%xmm1, %%xmm0\n\t"
1421 "psrlw $8, %%xmm0\n\t"
1422 "packuswb %%xmm1, %%xmm0\n\t"
1423 "movd %%xmm0, (%1,%2,4)\n\t"
1424 : :
"r"(data1),
"r"(data2),
"r"(i) );
1429 #ifdef USE_MMX_INLINE_ASM
1431 TQ_UINT16 alpha = TQ_UINT16( opacity * 256.0 );
1432 KIE4Pack packedalpha = { { alpha, alpha, alpha, 0 } };
1435 __asm__ __volatile__(
1436 "pxor %%mm7, %%mm7\n\t"
1437 "movq (%0), %%mm6\n\t"
1438 : :
"r"(&packedalpha),
"m"(packedalpha) );
1440 TQ_UINT32 *data1 =
reinterpret_cast<TQ_UINT32*
>( src.bits() );
1441 TQ_UINT32 *data2 =
reinterpret_cast<TQ_UINT32*
>( dst.bits() );
1444 int remainder = pixels % 2;
1445 pixels -= remainder;
1448 for (
int i = 0; i < pixels; i += 2 ) {
1449 __asm__ __volatile__(
1451 "movd (%0,%2,4), %%mm0\n\t"
1452 "movd (%1,%2,4), %%mm1\n\t"
1453 "movd 4(%0,%2,4), %%mm2\n\t"
1454 "movd 4(%1,%2,4), %%mm3\n\t"
1457 "punpcklbw %%mm7, %%mm0\n\t"
1458 "punpcklbw %%mm7, %%mm1\n\t"
1459 "psubw %%mm1, %%mm0\n\t"
1460 "pmullw %%mm6, %%mm0\n\t"
1461 "psllw $8, %%mm1\n\t"
1462 "paddw %%mm1, %%mm0\n\t"
1463 "psrlw $8, %%mm0\n\t"
1466 "punpcklbw %%mm7, %%mm2\n\t"
1467 "punpcklbw %%mm7, %%mm3\n\t"
1468 "psubw %%mm3, %%mm2\n\t"
1469 "pmullw %%mm6, %%mm2\n\t"
1470 "psllw $8, %%mm3\n\t"
1471 "paddw %%mm3, %%mm2\n\t"
1472 "psrlw $8, %%mm2\n\t"
1475 "packuswb %%mm2, %%mm0\n\t"
1476 "movq %%mm0, (%1,%2,4)\n\t"
1477 : :
"r"(data1),
"r"(data2),
"r"(i) );
1482 __asm__ __volatile__(
1483 "movd (%0), %%mm0\n\t"
1484 "punpcklbw %%mm7, %%mm0\n\t"
1485 "movd (%1), %%mm1\n\t"
1486 "punpcklbw %%mm7, %%mm1\n\t"
1487 "psubw %%mm1, %%mm0\n\t"
1488 "pmullw %%mm6, %%mm0\n\t"
1489 "psllw $8, %%mm1\n\t"
1490 "paddw %%mm1, %%mm0\n\t"
1491 "psrlw $8, %%mm0\n\t"
1492 "packuswb %%mm0, %%mm0\n\t"
1493 "movd %%mm0, (%1)\n\t"
1494 : :
"r"(data1 + pixels),
"r"(data2 + pixels) );
1498 __asm__ __volatile__(
"emms");
1503 #ifdef WORDS_BIGENDIAN
1504 unsigned char *data1 = (
unsigned char *)dst.bits() + 1;
1505 unsigned char *data2 = (
unsigned char *)src.bits() + 1;
1507 unsigned char *data1 = (
unsigned char *)dst.bits();
1508 unsigned char *data2 = (
unsigned char *)src.bits();
1511 for (
int i=0; i<pixels; i++)
1513 #ifdef WORDS_BIGENDIAN
1514 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1516 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1518 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1521 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1523 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1525 *data1 += (
unsigned char)((*(data2++) - *data1) * opacity);
1541 if (image.width() == 0 || image.height() == 0 || image.depth()!=32 ) {
1543 std::cerr <<
"WARNING: KImageEffect::blend : invalid image\n";
1548 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
1552 unsigned int xi, xf, yi, yf;
1556 float unaffected = 1;
1557 if (initial_intensity > 1) initial_intensity = 1;
1558 if (initial_intensity < -1) initial_intensity = -1;
1559 if (initial_intensity < 0) {
1560 unaffected = 1. + initial_intensity;
1561 initial_intensity = 0;
1566 float var = 1. - initial_intensity;
1575 unsigned int *data = (
unsigned int *)image.bits();
1577 int image_width = image.width();
1578 int image_height = image.height();
1581 if( eff == VerticalGradient || eff == HorizontalGradient ) {
1584 xi = 0, xf = image_width;
1585 yi = 0, yf = image_height;
1586 if (eff == VerticalGradient) {
1587 if (anti_dir) yf = (int)(image_height * unaffected);
1588 else yi = (int)(image_height * (1 - unaffected));
1591 if (anti_dir) xf = (int)(image_width * unaffected);
1592 else xi = (int)(image_height * (1 - unaffected));
1595 var /= (eff == VerticalGradient?yf-yi:xf-xi);
1598 for (y = yi; y < (int)yf; y++) {
1601 ind_base = image_width * y ;
1602 for (x = xi; x < (int)xf ; x++) {
1603 if (eff == HorizontalGradient)
intensity += var;
1605 r = tqRed (data[ind]) + (int)(
intensity *
1606 (r_bgnd - tqRed (data[ind])));
1607 g = tqGreen(data[ind]) + (int)(
intensity *
1608 (g_bgnd - tqGreen(data[ind])));
1609 b = tqBlue (data[ind]) + (int)(
intensity *
1610 (b_bgnd - tqBlue (data[ind])));
1611 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1612 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1613 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1614 a = tqAlpha(data[ind]);
1615 data[ind] = tqRgba(r, g, b, a);
1619 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
1620 float xvar = var / 2 / image_width;
1621 float yvar = var / 2 / image_height;
1624 for (x = 0; x < image_width ; x++) {
1625 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
1627 for (y = 0; y < image_height ; y++) {
1628 intensity = initial_intensity + tmp + yvar * y;
1630 r = tqRed (data[ind]) + (int)(
intensity *
1631 (r_bgnd - tqRed (data[ind])));
1632 g = tqGreen(data[ind]) + (int)(
intensity *
1633 (g_bgnd - tqGreen(data[ind])));
1634 b = tqBlue (data[ind]) + (int)(
intensity *
1635 (b_bgnd - tqBlue (data[ind])));
1636 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1637 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1638 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1639 a = tqAlpha(data[ind]);
1640 data[ind] = tqRgba(r, g, b, a);
1647 else if (eff == RectangleGradient || eff == EllipticGradient) {
1651 for (x = 0; x < image_width / 2 + image_width % 2; x++) {
1652 xvar = var / image_width * (image_width - x*2/unaffected-1);
1653 for (y = 0; y < image_height / 2 + image_height % 2; y++) {
1654 yvar = var / image_height * (image_height - y*2/unaffected -1);
1656 if (eff == RectangleGradient)
1657 intensity = initial_intensity + TQMAX(xvar, yvar);
1659 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1664 ind = x + image_width * y ;
1665 r = tqRed (data[ind]) + (int)(
intensity *
1666 (r_bgnd - tqRed (data[ind])));
1667 g = tqGreen(data[ind]) + (int)(
intensity *
1668 (g_bgnd - tqGreen(data[ind])));
1669 b = tqBlue (data[ind]) + (int)(
intensity *
1670 (b_bgnd - tqBlue (data[ind])));
1671 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1672 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1673 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1674 a = tqAlpha(data[ind]);
1675 data[ind] = tqRgba(r, g, b, a);
1678 ind = image_width - x - 1 + image_width * y ;
1679 r = tqRed (data[ind]) + (int)(
intensity *
1680 (r_bgnd - tqRed (data[ind])));
1681 g = tqGreen(data[ind]) + (int)(
intensity *
1682 (g_bgnd - tqGreen(data[ind])));
1683 b = tqBlue (data[ind]) + (int)(
intensity *
1684 (b_bgnd - tqBlue (data[ind])));
1685 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1686 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1687 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1688 a = tqAlpha(data[ind]);
1689 data[ind] = tqRgba(r, g, b, a);
1695 for (x = 0; x < image_width / 2; x++) {
1696 xvar = var / image_width * (image_width - x*2/unaffected-1);
1697 for (y = 0; y < image_height / 2; y++) {
1698 yvar = var / image_height * (image_height - y*2/unaffected -1);
1700 if (eff == RectangleGradient)
1701 intensity = initial_intensity + TQMAX(xvar, yvar);
1703 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
1708 ind = x + image_width * (image_height - y -1) ;
1709 r = tqRed (data[ind]) + (int)(
intensity *
1710 (r_bgnd - tqRed (data[ind])));
1711 g = tqGreen(data[ind]) + (int)(
intensity *
1712 (g_bgnd - tqGreen(data[ind])));
1713 b = tqBlue (data[ind]) + (int)(
intensity *
1714 (b_bgnd - tqBlue (data[ind])));
1715 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1716 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1717 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1718 a = tqAlpha(data[ind]);
1719 data[ind] = tqRgba(r, g, b, a);
1722 ind = image_width-x-1 + image_width * (image_height - y - 1) ;
1723 r = tqRed (data[ind]) + (int)(
intensity *
1724 (r_bgnd - tqRed (data[ind])));
1725 g = tqGreen(data[ind]) + (int)(
intensity *
1726 (g_bgnd - tqGreen(data[ind])));
1727 b = tqBlue (data[ind]) + (int)(
intensity *
1728 (b_bgnd - tqBlue (data[ind])));
1729 if (r > 255) r = 255;
if (r < 0 ) r = 0;
1730 if (g > 255) g = 255;
if (g < 0 ) g = 0;
1731 if (b > 255) b = 255;
if (b < 0 ) b = 0;
1732 a = tqAlpha(data[ind]);
1733 data[ind] = tqRgba(r, g, b, a);
1738 else std::cerr <<
"KImageEffect::blend effect not implemented" <<
std::endl;
1748 if (image1.width() == 0 || image1.height() == 0 ||
1749 image2.width() == 0 || image2.height() == 0)
1755 TQColor(0,0,0), TQColor(255,255,255),
1758 return blend(image1,image2,image3,
Red);
1766 if (image1.width() == 0 || image1.height() == 0 ||
1767 image2.width() == 0 || image2.height() == 0 ||
1768 blendImage.width() == 0 || blendImage.height() == 0) {
1770 std::cerr <<
"KImageEffect::blend effect invalid image" <<
std::endl;
1776 int ind1, ind2, ind3;
1778 unsigned int x1, x2, x3, y1, y2, y3;
1784 if (image1.depth()<32) image1 = image1.convertDepth(32);
1785 if (image2.depth()<32) image2 = image2.convertDepth(32);
1788 if (blendImage.depth()<8) blendImage = blendImage.convertDepth(8);
1790 unsigned int *colorTable3 = (blendImage.depth()==8) ?
1791 blendImage.colorTable():0;
1793 unsigned int *data1 = (
unsigned int *)image1.bits();
1794 unsigned int *data2 = (
unsigned int *)image2.bits();
1795 unsigned int *data3 = (
unsigned int *)blendImage.bits();
1796 unsigned char *data3b = (
unsigned char *)blendImage.bits();
1797 unsigned int color3;
1799 x1 = image1.width(); y1 = image1.height();
1800 x2 = image2.width(); y2 = image2.height();
1801 x3 = blendImage.width(); y3 = blendImage.height();
1803 for (y = 0; y < (int)y1; y++) {
1809 while(x < (
int)x1) {
1810 color3 = (colorTable3) ? colorTable3[data3b[ind3]] : data3[ind3];
1812 a = (channel ==
Red) ? tqRed(color3) :
1813 (channel ==
Green) ? tqGreen(color3) :
1814 (channel ==
Blue) ? tqBlue(color3) : tqGray(color3);
1816 r = (a*tqRed(data1[ind1]) + (256-a)*tqRed(data2[ind2]))/256;
1817 g = (a*tqGreen(data1[ind1]) + (256-a)*tqGreen(data2[ind2]))/256;
1818 b = (a*tqBlue(data1[ind1]) + (256-a)*tqBlue(data2[ind2]))/256;
1820 a = tqAlpha(data1[ind1]);
1821 data1[ind1] = tqRgba(r, g, b, a);
1823 ind1++; ind2++; ind3++; x++;
1824 if ( (x%x2) ==0) ind2 -= x2;
1825 if ( (x%x3) ==0) ind3 -= x3;
1838 unsigned int KImageEffect::lHash(
unsigned int c)
1840 unsigned char r = tqRed(c), g = tqGreen(c), b = tqBlue(c), a = tqAlpha(c);
1841 unsigned char nr, ng, nb;
1842 nr =(r >> 1) + (r >> 2); nr = nr > r ? 0 : nr;
1843 ng =(g >> 1) + (g >> 2); ng = ng > g ? 0 : ng;
1844 nb =(b >> 1) + (b >> 2); nb = nb > b ? 0 : nb;
1846 return tqRgba(nr, ng, nb, a);
1852 unsigned int KImageEffect::uHash(
unsigned int c)
1854 unsigned char r = tqRed(c), g = tqGreen(c), b = tqBlue(c), a = tqAlpha(c);
1855 unsigned char nr, ng, nb;
1856 nr = r + (r >> 3); nr = nr < r ? ~0 : nr;
1857 ng = g + (g >> 3); ng = ng < g ? ~0 : ng;
1858 nb = b + (b >> 3); nb = nb < b ? ~0 : nb;
1860 return tqRgba(nr, ng, nb, a);
1868 if (image.width() == 0 || image.height() == 0) {
1870 std::cerr <<
"KImageEffect::hash effect invalid image" <<
std::endl;
1876 unsigned int *data = (
unsigned int *)image.bits();
1882 (unsigned)image.height() < 2+spacing)
return image;
1885 (unsigned)image.height() < 2+spacing)
return image;
1888 for (y = 0 ; y < image.height(); y = y + 2 + spacing) {
1889 for (x = 0; x < image.width(); x++) {
1890 ind = x + image.width() * y;
1891 data[ind] = lite==
NorthLite?uHash(data[ind]):lHash(data[ind]);
1893 ind = ind + image.width();
1894 data[ind] = lite==
NorthLite?lHash(data[ind]):uHash(data[ind]);
1900 for (y = 0 ; y < image.height(); y++) {
1901 for (x = 0; x < image.width(); x = x + 2 + spacing) {
1902 ind = x + image.width() * y;
1903 data[ind] = lite==
EastLite?uHash(data[ind]):lHash(data[ind]);
1906 data[ind] = lite==
EastLite?lHash(data[ind]):uHash(data[ind]);
1912 for (y = 0 ; y < image.height(); y++) {
1914 x < (int)(image.width() - ((y & 1)? 1 : 0) * spacing);
1915 x = x + 2 + spacing) {
1916 ind = x + image.width() * y + ((y & 1)? 1 : 0);
1917 data[ind] = lite==
NWLite?uHash(data[ind]):lHash(data[ind]);
1920 data[ind] = lite==
NWLite?lHash(data[ind]):uHash(data[ind]);
1926 for (y = 0 ; y < image.height(); y++) {
1927 for (x = 0 + ((y & 1)? 1 : 0); x < image.width(); x = x + 2 + spacing) {
1928 ind = x + image.width() * y - ((y & 1)? 1 : 0);
1929 data[ind] = lite==
SWLite?uHash(data[ind]):lHash(data[ind]);
1932 data[ind] = lite==
SWLite?lHash(data[ind]):uHash(data[ind]);
1948 const TQColor &cb,
int ncols)
1950 if (img.width() == 0 || img.height() == 0)
1954 if (img.depth() == 1) {
1955 img.setColor(0, ca.rgb());
1956 img.setColor(1, cb.rgb());
1960 int r1 = ca.red();
int r2 = cb.red();
1961 int g1 = ca.green();
int g2 = cb.green();
1962 int b1 = ca.blue();
int b2 = cb.blue();
1963 int min = 0, max = 255;
1968 if (img.numColors()) {
1970 for (
int i = 0; i < img.numColors(); i++) {
1972 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
1973 min = TQMIN(min, mean);
1974 max = TQMAX(max, mean);
1978 for (
int y=0; y < img.height(); y++)
1979 for (
int x=0; x < img.width(); x++) {
1980 col = img.pixel(x, y);
1981 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
1982 min = TQMIN(min, mean);
1983 max = TQMAX(max, mean);
1988 float sr = ((float) r2 - r1) / (max - min);
1989 float sg = ((float) g2 - g1) / (max - min);
1990 float sb = ((float) b2 - b1) / (max - min);
1994 if (img.numColors()) {
1995 for (
int i=0; i < img.numColors(); i++) {
1997 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
1998 int r = (int) (sr * (mean - min) + r1 + 0.5);
1999 int g = (int) (sg * (mean - min) + g1 + 0.5);
2000 int b = (int) (sb * (mean - min) + b1 + 0.5);
2001 img.setColor(i, tqRgba(r, g, b, tqAlpha(col)));
2004 for (
int y=0; y < img.height(); y++)
2005 for (
int x=0; x < img.width(); x++) {
2006 col = img.pixel(x, y);
2007 int mean = (tqRed(col) + tqGreen(col) + tqBlue(col)) / 3;
2008 int r = (int) (sr * (mean - min) + r1 + 0.5);
2009 int g = (int) (sg * (mean - min) + g1 + 0.5);
2010 int b = (int) (sb * (mean - min) + b1 + 0.5);
2011 img.setPixel(x, y, tqRgba(r, g, b, tqAlpha(col)));
2017 if ( (ncols <= 0) || ((img.numColors() != 0) && (img.numColors() <= ncols)))
2020 if (ncols == 1) ncols++;
2021 if (ncols > 256) ncols = 256;
2023 TQColor *pal =
new TQColor[ncols];
2024 sr = ((float) r2 - r1) / (ncols - 1);
2025 sg = ((float) g2 - g1) / (ncols - 1);
2026 sb = ((float) b2 - b1) / (ncols - 1);
2028 for (
int i=0; i<ncols; i++)
2029 pal[i] = TQColor(r1 +
int(sr*i), g1 + int(sg*i), b1 + int(sb*i));
2046 if (img.width() == 0 || img.height() == 0)
2050 if (img.depth() == 1)
2053 unsigned char tbl[256];
2054 for (
int i=0; i<256; i++)
2055 tbl[i] = (
int) (val * i + 0.5);
2057 int red = color.red();
2058 int green = color.green();
2059 int blue = color.blue();
2062 int r, g, b, cr, cg, cb;
2064 if (img.depth() <= 8) {
2066 for (
int i=0; i<img.numColors(); i++) {
2068 cr = tqRed(col); cg = tqGreen(col); cb = tqBlue(col);
2070 r = cr - tbl[cr - red];
2072 r = cr + tbl[red - cr];
2074 g = cg - tbl[cg - green];
2076 g = cg + tbl[green - cg];
2078 b = cb - tbl[cb - blue];
2080 b = cb + tbl[blue - cb];
2081 img.setColor(i, tqRgba(r, g, b, tqAlpha(col)));
2086 for (
int y=0; y<img.height(); y++) {
2087 TQRgb *data = (TQRgb *) img.scanLine(y);
2088 for (
int x=0; x<img.width(); x++) {
2090 cr = tqRed(col); cg = tqGreen(col); cb = tqBlue(col);
2092 r = cr - tbl[cr - red];
2094 r = cr + tbl[red - cr];
2096 g = cg - tbl[cg - green];
2098 g = cg + tbl[green - cg];
2100 b = cb - tbl[cb - blue];
2102 b = cb + tbl[blue - cb];
2103 *data++ = tqRgba(r, g, b, tqAlpha(col));
2128 if (img.width() == 0 || img.height() == 0)
2132 if (img.depth() == 32) {
2133 uchar * r(img.bits());
2134 uchar * g(img.bits() + 1);
2135 uchar * b(img.bits() + 2);
2137 uchar * end(img.bits() + img.numBytes());
2141 *r = *g = *b = (((*r + *g) >> 1) + *b) >> 1;
2150 for (
int i = 0; i < img.numColors(); i++)
2152 uint r = tqRed(img.color(i));
2153 uint g = tqGreen(img.color(i));
2154 uint b = tqBlue(img.color(i));
2156 uint gray = (((r + g) >> 1) + b) >> 1;
2157 img.setColor(i, tqRgba(gray, gray, gray, tqAlpha(img.color(i))));
2162 int pixels = img.depth() > 8 ? img.width()*img.height() :
2164 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2165 (
unsigned int *)img.colorTable();
2167 for(i=0; i < pixels; ++i){
2168 val = tqGray(data[i]);
2169 data[i] = tqRgba(val, val, val, tqAlpha(data[i]));
2178 if (img.width() == 0 || img.height() == 0)
2181 if (desat < 0) desat = 0.;
2182 if (desat > 1) desat = 1.;
2183 int pixels = img.depth() > 8 ? img.width()*img.height() :
2185 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2186 (
unsigned int *)img.colorTable();
2189 for(i=0; i < pixels; ++i){
2190 clr.setRgb(data[i]);
2191 clr.hsv(&h, &s, &v);
2192 clr.setHsv(h, (
int)(s * (1. - desat)), v);
2193 data[i] = clr.rgb();
2201 if (img.width() == 0 || img.height() == 0)
2208 int pixels = img.depth() > 8 ? img.width()*img.height() :
2210 unsigned int *data = img.depth() > 8 ? (
unsigned int *)img.bits() :
2211 (
unsigned int *)img.colorTable();
2213 for(i=0; i < pixels; ++i){
2215 g = tqGreen(data[i]);
2216 b = tqBlue(data[i]);
2217 if(tqGray(data[i]) <= 127){
2245 data[i] = tqRgba(r, g, b, tqAlpha(data[i]));
2263 if (img.width() == 0 || img.height() == 0 ||
2264 palette == 0 || img.depth() <= 8)
2267 TQImage dImage( img.width(), img.height(), 8, size );
2270 dImage.setNumColors( size );
2271 for ( i = 0; i < size; i++ )
2272 dImage.setColor( i, palette[ i ].rgb() );
2274 int *rerr1 =
new int [ img.width() * 2 ];
2275 int *gerr1 =
new int [ img.width() * 2 ];
2276 int *berr1 =
new int [ img.width() * 2 ];
2278 memset( rerr1, 0,
sizeof(
int ) * img.width() * 2 );
2279 memset( gerr1, 0,
sizeof(
int ) * img.width() * 2 );
2280 memset( berr1, 0,
sizeof(
int ) * img.width() * 2 );
2282 int *rerr2 = rerr1 + img.width();
2283 int *gerr2 = gerr1 + img.width();
2284 int *berr2 = berr1 + img.width();
2286 for (
int j = 0; j < img.height(); j++ )
2288 uint *ip = (uint * )img.scanLine( j );
2289 uchar *dp = dImage.scanLine( j );
2291 for ( i = 0; i < img.width(); i++ )
2293 rerr1[i] = rerr2[i] + tqRed( *ip );
2295 gerr1[i] = gerr2[i] + tqGreen( *ip );
2297 berr1[i] = berr2[i] + tqBlue( *ip );
2302 *dp++ = nearestColor( rerr1[0], gerr1[0], berr1[0], palette, size );
2304 for ( i = 1; i < img.width()-1; i++ )
2306 int indx = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
2309 int rerr = rerr1[i];
2310 rerr -= palette[indx].red();
2311 int gerr = gerr1[i];
2312 gerr -= palette[indx].green();
2313 int berr = berr1[i];
2314 berr -= palette[indx].blue();
2317 rerr1[ i+1 ] += ( rerr * 7 ) >> 4;
2318 rerr2[ i-1 ] += ( rerr * 3 ) >> 4;
2319 rerr2[ i ] += ( rerr * 5 ) >> 4;
2320 rerr2[ i+1 ] += ( rerr ) >> 4;
2323 gerr1[ i+1 ] += ( gerr * 7 ) >> 4;
2324 gerr2[ i-1 ] += ( gerr * 3 ) >> 4;
2325 gerr2[ i ] += ( gerr * 5 ) >> 4;
2326 gerr2[ i+1 ] += ( gerr ) >> 4;
2329 berr1[ i+1 ] += ( berr * 7 ) >> 4;
2330 berr2[ i-1 ] += ( berr * 3 ) >> 4;
2331 berr2[ i ] += ( berr * 5 ) >> 4;
2332 berr2[ i+1 ] += ( berr ) >> 4;
2337 *dp = nearestColor( rerr1[i], gerr1[i], berr1[i], palette, size );
2348 int KImageEffect::nearestColor(
int r,
int g,
int b,
const TQColor *palette,
int size )
2353 int dr = palette[0].red() - r;
2354 int dg = palette[0].green() - g;
2355 int db = palette[0].blue() - b;
2357 int minDist = dr*dr + dg*dg + db*db;
2360 for (
int i = 1; i < size; i++ )
2362 dr = palette[i].red() - r;
2363 dg = palette[i].green() - g;
2364 db = palette[i].blue() - b;
2366 int dist = dr*dr + dg*dg + db*db;
2368 if ( dist < minDist )
2379 const TQImage & upper,
2380 const TQImage & lower,
2385 upper.width() > lower.width() ||
2386 upper.height() > lower.height() ||
2387 upper.depth() != 32 ||
2392 std::cerr <<
"KImageEffect::blend : Sizes not correct\n" ;
2397 output = lower.copy();
2402 int w = upper.width();
2403 int row(upper.height() - 1);
2407 i =
const_cast<TQImage&
>(upper).scanLine(row);
2408 o =
const_cast<TQImage&
>(output).scanLine(row);
2415 while (!(a = i[col]) && (col != 3)) {
2416 --col; --col; --col; --col;
2420 o[col] += ((i[col] - o[col]) * a) >> 8;
2423 o[col] += ((i[col] - o[col]) * a) >> 8;
2426 o[col] += ((i[col] - o[col]) * a) >> 8;
2438 const TQImage & upper,
2439 const TQImage & lower,
2441 const TQRect & destRect
2444 output = lower.copy();
2452 const TQImage & upper,
2453 const TQImage & lower,
2457 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
2459 if ( upper.width() + x > lower.width() ||
2460 upper.height() + y > lower.height() ||
2462 upper.depth() != 32 || lower.depth() != 32 )
2464 if ( x > lower.width() || y > lower.height() )
return false;
2465 if ( upper.width()<=0 || upper.height() <= 0 )
return false;
2466 if ( lower.width()<=0 || lower.height() <= 0 )
return false;
2468 if (x<0) {cx=-x; cw+=x; x=0; };
2469 if (cw + x > lower.width()) { cw=lower.width()-x; };
2470 if (y<0) {cy=-y; ch+=y; y=0; };
2471 if (ch + y > lower.height()) { ch=lower.height()-y; };
2473 if ( cx >= upper.width() || cy >= upper.height() )
return true;
2474 if ( cw <= 0 || ch <= 0 )
return true;
2477 output.create(cw,ch,32);
2485 for (j=0; j<ch; j++)
2487 b=
reinterpret_cast<TQRgb *
>(&
const_cast<TQImage&
>(lower).scanLine(y+j) [ (x+cw) << 2 ]);
2488 i=
reinterpret_cast<TQRgb *
>(&
const_cast<TQImage&
>(upper).scanLine(cy+j)[ (cx+cw) << 2 ]);
2489 o=
reinterpret_cast<TQRgb *
>(&
const_cast<TQImage&
>(output).scanLine(j) [ cw << 2 ]);
2495 while ( !(a=tqAlpha(*i)) && k>0 )
2504 *o = tqRgb(tqRed(*b) + (((tqRed(*i) - tqRed(*b)) * a) >> 8),
2505 tqGreen(*b) + (((tqGreen(*i) - tqGreen(*b)) * a) >> 8),
2506 tqBlue(*b) + (((tqBlue(*i) - tqBlue(*b)) * a) >> 8));
2516 const TQImage & upper,
2517 const TQImage & lower
2520 int cx=0, cy=0, cw=upper.width(), ch=upper.height();
2522 if ( upper.depth() != 32 || lower.depth() != 32 )
return false;
2523 if ( x + cw > lower.width() ||
2524 y + ch > lower.height() ||
2527 if ( x > lower.width() || y > lower.height() )
return true;
2528 if ( upper.width()<=0 || upper.height() <= 0 )
return true;
2529 if ( lower.width()<=0 || lower.height() <= 0 )
return true;
2531 if (x<0) {cx=-x; cw+=x; x=0; };
2532 if (cw + x > lower.width()) { cw=lower.width()-x; };
2533 if (y<0) {cy=-y; ch+=y; y=0; };
2534 if (ch + y > lower.height()) { ch=lower.height()-y; };
2536 if ( cx >= upper.width() || cy >= upper.height() )
return true;
2537 if ( cw <= 0 || ch <= 0 )
return true;
2544 for (
int j=0; j<ch; j++)
2546 b=&
const_cast<TQImage&
>(lower).scanLine(y+j) [ (x+cw) << 2 ];
2547 i=&
const_cast<TQImage&
>(upper).scanLine(cy+j)[ (cx+cw) << 2 ];
2553 #ifndef WORDS_BIGENDIAN
2554 while ( !(a=*i) && k>0 )
2556 while ( !(a=*(i-3)) && k>0 )
2562 #ifndef WORDS_BIGENDIAN
2564 *b += ( ((*i - *b) * a) >> 8 );
2566 *b += ( ((*i - *b) * a) >> 8 );
2568 *b += ( ((*i - *b) * a) >> 8 );
2571 *b += ( ((*i - *b) * a) >> 8 );
2573 *b += ( ((*i - *b) * a) >> 8 );
2575 *b += ( ((*i - *b) * a) >> 8 );
2585 TQImage &lower,
const TQRect &lowerRect)
2588 TQRect lr = lowerRect & lower.rect();
2589 lr.setWidth( TQMIN(lr.width(), upper.width()-upperOffset.x()) );
2590 lr.setHeight( TQMIN(lr.height(), upper.height()-upperOffset.y()) );
2591 if ( !lr.isValid() )
return;
2594 for (
int y = 0; y < lr.height(); y++) {
2595 for (
int x = 0; x < lr.width(); x++) {
2596 TQRgb *b =
reinterpret_cast<TQRgb*
>(
const_cast<TQImage&
>(lower).scanLine(lr.y() + y)+ (lr.x() + x) *
sizeof(TQRgb));
2597 TQRgb *d =
reinterpret_cast<TQRgb*
>(
const_cast<TQImage&
>(upper).scanLine(upperOffset.y() + y) + (upperOffset.x() + x) *
sizeof(TQRgb));
2598 int a = tqAlpha(*d);
2599 *b = tqRgb(tqRed(*b) - (((tqRed(*b) - tqRed(*d)) * a) >> 8),
2600 tqGreen(*b) - (((tqGreen(*b) - tqGreen(*d)) * a) >> 8),
2601 tqBlue(*b) - (((tqBlue(*b) - tqBlue(*d)) * a) >> 8));
2607 TQImage &lower,
const TQRect &lowerRect,
float opacity)
2610 TQRect lr = lowerRect & lower.rect();
2611 lr.setWidth( TQMIN(lr.width(), upper.width()-upperOffset.x()) );
2612 lr.setHeight( TQMIN(lr.height(), upper.height()-upperOffset.y()) );
2613 if ( !lr.isValid() )
return;
2616 for (
int y = 0; y < lr.height(); y++) {
2617 for (
int x = 0; x < lr.width(); x++) {
2618 TQRgb *b =
reinterpret_cast<TQRgb*
>(
const_cast<TQImage&
>(lower).scanLine(lr.y() + y)+ (lr.x() + x) *
sizeof(TQRgb));
2619 TQRgb *d =
reinterpret_cast<TQRgb*
>(
const_cast<TQImage&
>(upper).scanLine(upperOffset.y() + y) + (upperOffset.x() + x) *
sizeof(TQRgb));
2620 int a = tqRound(opacity * tqAlpha(*d));
2621 *b = tqRgb(tqRed(*b) - (((tqRed(*b) - tqRed(*d)) * a) >> 8),
2622 tqGreen(*b) - (((tqGreen(*b) - tqGreen(*d)) * a) >> 8),
2623 tqBlue(*b) - (((tqBlue(*b) - tqBlue(*d)) * a) >> 8));
2631 int w = lowerSize.width();
2632 int h = lowerSize.height();
2633 int ww = upper.width();
2634 int wh = upper.height();
2637 switch (disposition) {
2641 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2644 d.setRect(0, 0, w, h);
2647 d.setCoords(-ww + ((w - ww) / 2) % ww, -wh + ((h - wh) / 2) % wh,
2651 upper = upper.smoothScale(w, h);
2652 d.setRect(0, 0, w, h);
2655 if( ww <= w && wh <= h ) {
2656 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2661 double sx = (double) w / ww;
2662 double sy = (double) h / wh;
2664 ww = (int)(sy * ww);
2667 wh = (int)(sx * wh);
2670 upper = upper.smoothScale(ww, wh);
2671 d.setRect((w - ww) / 2, (h - wh) / 2, ww, wh);
2675 double sx = (double) w / ww;
2676 double sy = (double) h / wh;
2678 ww = (int)(sy * ww);
2681 wh = (int)(sx * wh);
2684 upper = upper.smoothScale(ww, wh);
2685 d.setRect(0, 0, w, h);
2697 for (
int y = r.top(); y<r.bottom(); y += upper.height())
2698 for (
int x = r.left(); x<r.right(); x += upper.width())
2699 blendOnLower(upper, TQPoint(-TQMIN(x, 0), -TQMIN(y, 0)),
2700 lower, TQRect(x, y, upper.width(), upper.height()), opacity);
2707 return blend( col, img, 0.5);
2749 if(w == src.width() && h == src.height())
2752 int depth = src.depth();
2753 TQImage dest(w, h, depth, depth <= 8 ? src.numColors() : 0,
2754 depth == 1 ? TQImage::LittleEndian : TQImage::IgnoreEndian);
2755 int *x_offset = (
int *)malloc(w*
sizeof(
int));
2756 int *y_offset = (
int *)malloc(h*
sizeof(
int));
2757 if(!x_offset || !y_offset){
2759 tqWarning(
"KImageEffect::sample(): Unable to allocate pixel buffer");
2767 for(
int x=0; x < w; ++x)
2768 x_offset[x] = (
int)(x*src.width()/((double)w));
2769 for(
int y=0; y < h; ++y)
2770 y_offset[y] = (
int)(y*src.height()/((double)h));
2773 for(
int y=0; y < h; ++y){
2774 unsigned int *destData = (
unsigned int *)dest.scanLine(y);
2775 unsigned int *srcData = (
unsigned int *)src.scanLine(y_offset[y]);
2776 for(
int x=0; x < w; ++x)
2777 destData[x] = srcData[x_offset[x]];
2780 else if(depth == 1) {
2781 int r = src.bitOrder() == TQImage::LittleEndian;
2782 memcpy(dest.colorTable(), src.colorTable(), src.numColors()*
sizeof(TQRgb));
2783 for(
int y=0; y < h; ++y){
2784 unsigned char *destData = dest.scanLine(y);
2785 unsigned char *srcData = src.scanLine(y_offset[y]);
2786 for(
int x=0; x < w; ++x){
2787 int k = x_offset[x];
2788 int l = r ? (k & 7) : (7 - (k&7));
2789 if(srcData[k >> 3] & (1 << l))
2790 destData[x >> 3] |= 1 << (x & 7);
2792 destData[x >> 3] &= ~(1 << (x & 7));
2797 memcpy(dest.colorTable(), src.colorTable(), src.numColors()*
sizeof(TQRgb));
2798 for(
int y=0; y < h; ++y){
2799 unsigned char *destData = dest.scanLine(y);
2800 unsigned char *srcData = src.scanLine(y_offset[y]);
2801 for(
int x=0; x < w; ++x)
2802 destData[x] = srcData[x_offset[x]];
2814 if(img.depth() > 8){
2815 count = img.width()*img.height();
2816 data = (
unsigned int *)img.bits();
2819 count = img.numColors();
2820 data = (
unsigned int *)img.colorTable();
2822 for(i=0; i < count; ++i)
2823 data[i] = intensityValue(data[i]) <
threshold ? TQColor(TQt::black).rgb() : TQColor(TQt::white).rgb();
2826 void KImageEffect::hull(
const int x_offset,
const int y_offset,
2827 const int polarity,
const int columns,
2829 unsigned int *f,
unsigned int *g)
2833 unsigned int *p, *q, *r, *s;
2835 if(f == NULL || g == NULL)
2839 r=p+(y_offset*(columns+2)+x_offset);
2840 for (y=0; y < rows; y++){
2845 for (x=0; x < columns; x++){
2855 for(x=0; x < columns; x++){
2857 if (v > (
unsigned int) (*r+1))
2870 r=q+(y_offset*(columns+2)+x_offset);
2871 s=q-(y_offset*(columns+2)+x_offset);
2872 for(y=0; y < rows; y++){
2878 for(x=0; x < (int) columns; x++){
2880 if (((
unsigned int) (*s+1) > v) && (*r > v))
2889 for (x=0; x < columns; x++){
2891 if (((
unsigned int) (*s+1) < v) && (*r < v))
2909 unsigned int *blue_channel, *red_channel, *green_channel, *buffer,
2916 unsigned int *destData;
2917 TQImage dest(src.width(), src.height(), 32);
2919 packets = (src.width()+2)*(src.height()+2);
2920 red_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2921 green_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2922 blue_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2923 alpha_channel = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2924 buffer = (
unsigned int *)calloc(packets,
sizeof(
unsigned int));
2925 if(!red_channel || ! green_channel || ! blue_channel || ! alpha_channel ||
2928 free(green_channel);
2930 free(alpha_channel);
2937 if(src.depth() > 8){
2938 unsigned int *srcData;
2939 for(y=0; y < src.height(); ++y){
2940 srcData = (
unsigned int *)src.scanLine(y);
2942 for(x=0; x < src.width(); ++x){
2943 red_channel[j] = tqRed(srcData[x]);
2944 green_channel[j] = tqGreen(srcData[x]);
2945 blue_channel[j] = tqBlue(srcData[x]);
2946 alpha_channel[j] = tqAlpha(srcData[x]);
2953 unsigned char *srcData;
2954 unsigned int *cTable = src.colorTable();
2956 for(y=0; y < src.height(); ++y){
2957 srcData = (
unsigned char *)src.scanLine(y);
2959 for(x=0; x < src.width(); ++x){
2960 pixel = *(cTable+srcData[x]);
2961 red_channel[j] = tqRed(pixel);
2962 green_channel[j] = tqGreen(pixel);
2963 blue_channel[j] = tqBlue(pixel);
2964 alpha_channel[j] = tqAlpha(pixel);
2971 for(i=0; i < 4; i++){
2972 hull(X[i],Y[i],1,src.width(),src.height(),red_channel,buffer);
2973 hull(-X[i],-Y[i],1,src.width(),src.height(),red_channel,buffer);
2974 hull(-X[i],-Y[i],-1,src.width(),src.height(),red_channel,buffer);
2975 hull(X[i],Y[i],-1,src.width(),src.height(),red_channel,buffer);
2978 for (i=0; i < packets; i++)
2980 for (i=0; i < 4; i++){
2981 hull(X[i],Y[i],1,src.width(),src.height(),green_channel,buffer);
2982 hull(-X[i],-Y[i],1,src.width(),src.height(),green_channel,buffer);
2983 hull(-X[i],-Y[i],-1,src.width(),src.height(),green_channel,buffer);
2984 hull(X[i],Y[i],-1,src.width(),src.height(),green_channel,buffer);
2987 for (i=0; i < packets; i++)
2989 for (i=0; i < 4; i++){
2990 hull(X[i],Y[i],1,src.width(),src.height(),blue_channel,buffer);
2991 hull(-X[i],-Y[i],1,src.width(),src.height(),blue_channel,buffer);
2992 hull(-X[i],-Y[i],-1,src.width(),src.height(),blue_channel,buffer);
2993 hull(X[i],Y[i],-1,src.width(),src.height(),blue_channel,buffer);
2997 for(y=0; y < dest.height(); ++y)
2999 destData = (
unsigned int *)dest.scanLine(y);
3001 for (x=0; x < dest.width(); ++x)
3003 destData[x] = tqRgba(red_channel[j], green_channel[j],
3004 blue_channel[j], alpha_channel[j]);
3011 free(green_channel);
3013 free(alpha_channel);
3017 unsigned int KImageEffect::generateNoise(
unsigned int pixel,
3018 NoiseType noise_type)
3020 #define NoiseEpsilon 1.0e-5
3021 #define NoiseMask 0x7fff
3022 #define SigmaUniform 4.0
3023 #define SigmaGaussian 4.0
3024 #define SigmaImpulse 0.10
3025 #define SigmaLaplacian 10.0
3026 #define SigmaMultiplicativeGaussian 0.5
3027 #define SigmaPoisson 0.05
3028 #define TauGaussian 20.0
3030 double alpha, beta, sigma, value;
3031 alpha=(double) (rand() & NoiseMask)/NoiseMask;
3038 value=(double) pixel+SigmaUniform*(alpha-0.5);
3045 beta=(double) (rand() & NoiseMask)/NoiseMask;
3046 sigma=sqrt(-2.0*log(alpha))*cos(2.0*M_PI*beta);
3047 tau=sqrt(-2.0*log(alpha))*sin(2.0*M_PI*beta);
3048 value=(double) pixel+
3049 (sqrt((
double) pixel)*SigmaGaussian*sigma)+(TauGaussian*tau);
3054 if (alpha <= NoiseEpsilon)
3057 sigma=sqrt(-2.0*log(alpha));
3058 beta=(rand() & NoiseMask)/NoiseMask;
3059 value=(double) pixel+
3060 pixel*SigmaMultiplicativeGaussian*sigma*cos(2.0*M_PI*beta);
3065 if (alpha < (SigmaImpulse/2.0))
3068 if (alpha >= (1.0-(SigmaImpulse/2.0)))
3078 if (alpha <= NoiseEpsilon)
3079 value=(double) pixel-MaxRGB;
3081 value=(double) pixel+SigmaLaplacian*log(2.0*alpha);
3085 if (beta <= (0.5*NoiseEpsilon))
3086 value=(
double) pixel+MaxRGB;
3088 value=(double) pixel-SigmaLaplacian*log(2.0*beta);
3096 for (i=0; alpha > exp(-SigmaPoisson*pixel); i++)
3098 beta=(double) (rand() & NoiseMask)/NoiseMask;
3101 value=i/SigmaPoisson;
3109 return((
unsigned int) (value+0.5));
3115 TQImage dest(src.width(), src.height(), 32);
3116 unsigned int *destData;
3118 if(src.depth() > 8){
3119 unsigned int *srcData;
3120 for(y=0; y < src.height(); ++y){
3121 srcData = (
unsigned int *)src.scanLine(y);
3122 destData = (
unsigned int *)dest.scanLine(y);
3123 for(x=0; x < src.width(); ++x){
3124 destData[x] = tqRgba(generateNoise(tqRed(srcData[x]), noise_type),
3125 generateNoise(tqGreen(srcData[x]), noise_type),
3126 generateNoise(tqBlue(srcData[x]), noise_type),
3127 tqAlpha(srcData[x]));
3132 unsigned char *srcData;
3133 unsigned int *cTable = src.colorTable();
3135 for(y=0; y < src.height(); ++y){
3136 srcData = (
unsigned char *)src.scanLine(y);
3137 destData = (
unsigned int *)dest.scanLine(y);
3138 for(x=0; x < src.width(); ++x){
3139 pixel = *(cTable+srcData[x]);
3140 destData[x] = tqRgba(generateNoise(tqRed(pixel), noise_type),
3141 generateNoise(tqGreen(pixel), noise_type),
3142 generateNoise(tqBlue(pixel), noise_type),
3151 unsigned int KImageEffect::interpolateColor(TQImage *image,
double x_offset,
3153 unsigned int background)
3156 unsigned int p, q, r, s;
3161 if((x < -1) || (x >= image->width()) || (y < -1) || (y >= image->height()))
3163 if(image->depth() > 8){
3164 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
3165 unsigned int *t = (
unsigned int *)image->scanLine(y);
3168 r = t[x+image->width()];
3169 s = t[x+image->width()+1];
3172 unsigned int *t = (
unsigned int *)image->scanLine(y);
3174 if((x >= 0) && (y >= 0)){
3178 if(((x+1) < image->width()) && (y >= 0)){
3182 if((x >= 0) && ((y+1) < image->height())){
3183 t = (
unsigned int *)image->scanLine(y+1);
3184 r = t[x+image->width()];
3187 if(((x+1) < image->width()) && ((y+1) < image->height())){
3188 t = (
unsigned int *)image->scanLine(y+1);
3189 s = t[x+image->width()+1];
3195 unsigned int *colorTable = (
unsigned int *)image->colorTable();
3196 if((x >= 0) && (y >= 0) && (x < (image->width()-1)) && (y < (image->height()-1))) {
3198 t = (
unsigned char *)image->scanLine(y);
3199 p = *(colorTable+t[x]);
3200 q = *(colorTable+t[x+1]);
3201 t = (
unsigned char *)image->scanLine(y+1);
3202 r = *(colorTable+t[x]);
3203 s = *(colorTable+t[x+1]);
3208 if((x >= 0) && (y >= 0)){
3209 t = (
unsigned char *)image->scanLine(y);
3210 p = *(colorTable+t[x]);
3213 if(((x+1) < image->width()) && (y >= 0)){
3214 t = (
unsigned char *)image->scanLine(y);
3215 q = *(colorTable+t[x+1]);
3218 if((x >= 0) && ((y+1) < image->height())){
3219 t = (
unsigned char *)image->scanLine(y+1);
3220 r = *(colorTable+t[x]);
3223 if(((x+1) < image->width()) && ((y+1) < image->height())){
3224 t = (
unsigned char *)image->scanLine(y+1);
3225 s = *(colorTable+t[x+1]);
3231 x_offset -= floor(x_offset);
3232 y_offset -= floor(y_offset);
3233 alpha = 1.0-x_offset;
3234 beta = 1.0-y_offset;
3236 return(tqRgba((
unsigned char)(beta*(alpha*tqRed(p)+x_offset*tqRed(q))+y_offset*(alpha*tqRed(r)+x_offset*tqRed(s))),
3237 (
unsigned char)(beta*(alpha*tqGreen(p)+x_offset*tqGreen(q))+y_offset*(alpha*tqGreen(r)+x_offset*tqGreen(s))),
3238 (
unsigned char)(beta*(alpha*tqBlue(p)+x_offset*tqBlue(q))+y_offset*(alpha*tqBlue(r)+x_offset*tqBlue(s))),
3239 (
unsigned char)(beta*(alpha*tqAlpha(p)+x_offset*tqAlpha(q))+y_offset*(alpha*tqAlpha(r)+x_offset*tqAlpha(s)))));
3243 unsigned int background)
3245 double amount, distance, radius;
3246 double x_center, x_distance, x_scale;
3247 double y_center, y_distance, y_scale;
3248 unsigned int *destData;
3251 TQImage dest(src.width(), src.height(), 32);
3256 x_center = (double)0.5*src.width();
3257 y_center = (double)0.5*src.height();
3259 if(src.width() > src.height())
3260 y_scale = (
double)src.width()/src.height();
3261 else if(src.width() < src.height()){
3262 x_scale = (double) src.height()/src.width();
3268 if(src.depth() > 8){
3269 unsigned int *srcData;
3270 for(y=0; y < src.height(); ++y){
3271 srcData = (
unsigned int *)src.scanLine(y);
3272 destData = (
unsigned int *)dest.scanLine(y);
3273 y_distance=y_scale*(y-y_center);
3274 for(x=0; x < src.width(); ++x){
3275 destData[x] = srcData[x];
3276 x_distance = x_scale*(x-x_center);
3277 distance= x_distance*x_distance+y_distance*y_distance;
3278 if(distance < (radius*radius)){
3284 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
3285 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
3286 factor*y_distance/y_scale+y_center,
3293 unsigned char *srcData;
3295 unsigned int *cTable = src.colorTable();
3296 for(y=0; y < src.height(); ++y){
3297 srcData = (
unsigned char *)src.scanLine(y);
3298 destData = (
unsigned int *)dest.scanLine(y);
3299 y_distance=y_scale*(y-y_center);
3300 for(x=0; x < src.width(); ++x){
3302 destData[x] = cTable[idx];
3303 x_distance = x_scale*(x-x_center);
3304 distance= x_distance*x_distance+y_distance*y_distance;
3305 if(distance < (radius*radius)){
3311 pow(sin(0.5000000000000001*M_PI*sqrt(distance)/radius),-amount);
3312 destData[x] = interpolateColor(&src, factor*x_distance/x_scale+x_center,
3313 factor*y_distance/y_scale+y_center,
3327 if(img.depth() > 8){
3328 unsigned int *srcData, *destData;
3331 dest.create(img.height(), img.width(), img.depth());
3332 for(y=0; y < img.height(); ++y){
3333 srcData = (
unsigned int *)img.scanLine(y);
3334 for(x=0; x < img.width(); ++x){
3335 destData = (
unsigned int *)dest.scanLine(x);
3336 destData[img.height()-y-1] = srcData[x];
3341 dest.create(img.width(), img.height(), img.depth());
3342 for(y=0; y < img.height(); ++y){
3343 srcData = (
unsigned int *)img.scanLine(y);
3344 destData = (
unsigned int *)dest.scanLine(img.height()-y-1);
3345 for(x=0; x < img.width(); ++x)
3346 destData[img.width()-x-1] = srcData[x];
3350 dest.create(img.height(), img.width(), img.depth());
3351 for(y=0; y < img.height(); ++y){
3352 srcData = (
unsigned int *)img.scanLine(y);
3353 for(x=0; x < img.width(); ++x){
3354 destData = (
unsigned int *)dest.scanLine(img.width()-x-1);
3355 destData[y] = srcData[x];
3365 unsigned char *srcData, *destData;
3366 unsigned int *srcTable, *destTable;
3369 dest.create(img.height(), img.width(), img.depth());
3370 dest.setNumColors(img.numColors());
3371 srcTable = (
unsigned int *)img.colorTable();
3372 destTable = (
unsigned int *)dest.colorTable();
3373 for(x=0; x < img.numColors(); ++x)
3374 destTable[x] = srcTable[x];
3375 for(y=0; y < img.height(); ++y){
3376 srcData = (
unsigned char *)img.scanLine(y);
3377 for(x=0; x < img.width(); ++x){
3378 destData = (
unsigned char *)dest.scanLine(x);
3379 destData[img.height()-y-1] = srcData[x];
3384 dest.create(img.width(), img.height(), img.depth());
3385 dest.setNumColors(img.numColors());
3386 srcTable = (
unsigned int *)img.colorTable();
3387 destTable = (
unsigned int *)dest.colorTable();
3388 for(x=0; x < img.numColors(); ++x)
3389 destTable[x] = srcTable[x];
3390 for(y=0; y < img.height(); ++y){
3391 srcData = (
unsigned char *)img.scanLine(y);
3392 destData = (
unsigned char *)dest.scanLine(img.height()-y-1);
3393 for(x=0; x < img.width(); ++x)
3394 destData[img.width()-x-1] = srcData[x];
3398 dest.create(img.height(), img.width(), img.depth());
3399 dest.setNumColors(img.numColors());
3400 srcTable = (
unsigned int *)img.colorTable();
3401 destTable = (
unsigned int *)dest.colorTable();
3402 for(x=0; x < img.numColors(); ++x)
3403 destTable[x] = srcTable[x];
3404 for(y=0; y < img.height(); ++y){
3405 srcData = (
unsigned char *)img.scanLine(y);
3406 for(x=0; x < img.width(); ++x){
3407 destData = (
unsigned char *)dest.scanLine(img.width()-x-1);
3408 destData[y] = srcData[x];
3427 threshold = (int)(factor*(MaxRGB+1)/100.0);
3428 if(img.depth() < 32){
3429 data = (
unsigned int *)img.colorTable();
3430 count = img.numColors();
3433 data = (
unsigned int *)img.bits();
3434 count = img.width()*img.height();
3436 for(i=0; i < count; ++i){
3437 data[i] = tqRgba(tqRed(data[i]) >
threshold ? MaxRGB-tqRed(data[i]) : tqRed(data[i]),
3438 tqGreen(data[i]) >
threshold ? MaxRGB-tqGreen(data[i]) : tqGreen(data[i]),
3439 tqBlue(data[i]) >
threshold ? MaxRGB-tqBlue(data[i]) : tqBlue(data[i]),
3447 int x_distance, y_distance;
3448 if(src.width() < 3 || src.height() < 3)
3452 quantum=(amount+1) >> 1;
3453 if(src.depth() > 8){
3454 unsigned int *p, *q;
3455 for(y=0; y < src.height(); y++){
3456 q = (
unsigned int *)dest.scanLine(y);
3457 for(x=0; x < src.width(); x++){
3458 x_distance = x + ((rand() & (amount+1))-quantum);
3459 y_distance = y + ((rand() & (amount+1))-quantum);
3460 x_distance = TQMIN(x_distance, src.width()-1);
3461 y_distance = TQMIN(y_distance, src.height()-1);
3466 p = (
unsigned int *)src.scanLine(y_distance);
3474 unsigned char *p, *q;
3475 for(y=0; y < src.height(); y++){
3476 q = (
unsigned char *)dest.scanLine(y);
3477 for(x=0; x < src.width(); x++){
3478 x_distance = x + ((rand() & (amount+1))-quantum);
3479 y_distance = y + ((rand() & (amount+1))-quantum);
3480 x_distance = TQMIN(x_distance, src.width()-1);
3481 y_distance = TQMIN(y_distance, src.height()-1);
3486 p = (
unsigned char *)src.scanLine(y_distance);
3496 unsigned int background)
3498 double cosine, distance, factor, radius, sine, x_center, x_distance,
3499 x_scale, y_center, y_distance, y_scale;
3502 TQImage dest(src.width(), src.height(), 32);
3505 x_center = src.width()/2.0;
3506 y_center = src.height()/2.0;
3507 radius = TQMAX(x_center,y_center);
3510 if(src.width() > src.height())
3511 y_scale=(double)src.width()/src.height();
3512 else if(src.width() < src.height())
3513 x_scale=(
double)src.height()/src.width();
3514 degrees=DegreesToRadians(degrees);
3516 if(src.depth() > 8){
3518 for(y=0; y < src.height(); y++){
3519 p = (
unsigned int *)src.scanLine(y);
3520 q = (
unsigned int *)dest.scanLine(y);
3521 y_distance = y_scale*(y-y_center);
3522 for(x=0; x < src.width(); x++){
3525 x_distance = x_scale*(x-x_center);
3526 distance = x_distance*x_distance+y_distance*y_distance;
3527 if (distance < (radius*radius)){
3529 factor = 1.0-sqrt(distance)/radius;
3530 sine = sin(degrees*factor*factor);
3531 cosine = cos(degrees*factor*factor);
3532 *q = interpolateColor(&src,
3533 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3534 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3544 unsigned int *cTable = (
unsigned int *)src.colorTable();
3545 for(y=0; y < src.height(); y++){
3546 p = (
unsigned char *)src.scanLine(y);
3547 q = (
unsigned int *)dest.scanLine(y);
3548 y_distance = y_scale*(y-y_center);
3549 for(x=0; x < src.width(); x++){
3551 *q = *(cTable+(*p));
3552 x_distance = x_scale*(x-x_center);
3553 distance = x_distance*x_distance+y_distance*y_distance;
3554 if (distance < (radius*radius)){
3556 factor = 1.0-sqrt(distance)/radius;
3557 sine = sin(degrees*factor*factor);
3558 cosine = cos(degrees*factor*factor);
3559 *q = interpolateColor(&src,
3560 (cosine*x_distance-sine*y_distance)/x_scale+x_center,
3561 (sine*x_distance+cosine*y_distance)/y_scale+y_center,
3574 unsigned int background)
3580 TQImage dest(src.width(), src.height() + (
int)(2*fabs(amplitude)), 32);
3582 sine_map = (
double *)malloc(dest.width()*
sizeof(double));
3585 for(x=0; x < dest.width(); ++x)
3586 sine_map[x]=fabs(amplitude)+amplitude*sin((2*M_PI*x)/wavelength);
3588 for(y=0; y < dest.height(); ++y){
3589 q = (
unsigned int *)dest.scanLine(y);
3590 for (x=0; x < dest.width(); x++){
3591 *q=interpolateColor(&src, x, (
int)(y-sine_map[x]), background);
3614 unsigned long count ;
3615 unsigned long histogram[256];
3618 int x, y, mx, my, sx, sy;
3620 unsigned int *s=0, *q;
3622 if(src.depth() < 32)
3623 src.convertDepth(32);
3627 width = getOptimalKernelWidth(radius, 0.5);
3628 if(src.width() < width){
3629 tqWarning(
"KImageEffect::oilPaintConvolve(): Image is smaller than radius!");
3639 unsigned int **jumpTable = (
unsigned int **)src.jumpTable();
3640 for(y=0; y < dest.height(); ++y){
3642 q = (
unsigned int *)dest.scanLine(y);
3643 for(x=0; x < dest.width(); ++x){
3645 memset(histogram, 0, 256*
sizeof(
unsigned long));
3648 for(mcy=0; mcy < width; ++mcy, ++sy){
3649 my = sy < 0 ? 0 : sy > src.height()-1 ?
3650 src.height()-1 : sy;
3652 for(mcx=0; mcx < width; ++mcx, ++sx){
3653 mx = sx < 0 ? 0 : sx > src.width()-1 ?
3656 k = intensityValue(jumpTable[my][mx]);
3658 tqWarning(
"KImageEffect::oilPaintConvolve(): k is %d",
3663 if(histogram[k] > count){
3664 count = histogram[k];
3665 s = jumpTable[my]+mx;
3685 TQImage img(
edge(src, radius));
3686 img =
blur(img, radius, sigma);
3688 img.invertPixels(
false);
3695 struct double_packet high, low,
intensity, *histogram;
3696 struct short_packet *normalize_map;
3697 TQ_INT64 number_pixels;
3699 unsigned int *p, *q;
3701 unsigned long threshold_intensity;
3702 unsigned char r, g, b, a;
3704 if(image.depth() < 32)
3705 image = image.convertDepth(32);
3707 histogram = (
struct double_packet *)
3708 malloc(256*
sizeof(
struct double_packet));
3709 normalize_map = (
struct short_packet *)
3710 malloc(256*
sizeof(
struct short_packet));
3712 if(!histogram || !normalize_map){
3714 liberateMemory(&histogram);
3716 liberateMemory(&normalize_map);
3717 tqWarning(
"KImageEffect::normalize(): Unable to allocate memory!");
3724 memset(histogram, 0, 256*
sizeof(
struct double_packet));
3725 for(y=0; y < image.height(); ++y){
3726 p = (
unsigned int *)image.scanLine(y);
3727 for(x=0; x < image.width(); ++x){
3728 histogram[(
unsigned char)(tqRed(*p))].red++;
3729 histogram[(
unsigned char)(tqGreen(*p))].green++;
3730 histogram[(
unsigned char)(tqBlue(*p))].blue++;
3731 histogram[(
unsigned char)(tqAlpha(*p))].alpha++;
3739 number_pixels = (TQ_INT64)image.width()*image.height();
3740 threshold_intensity = number_pixels/1000;
3743 memset(&
intensity, 0,
sizeof(
struct double_packet));
3744 memset(&high, 0,
sizeof(
struct double_packet));
3745 memset(&low, 0,
sizeof(
struct double_packet));
3746 for(high.red=255; high.red != 0; high.red--){
3747 intensity.red+=histogram[(
unsigned char)high.red].red;
3751 if(low.red == high.red){
3752 threshold_intensity = 0;
3753 memset(&
intensity, 0,
sizeof(
struct double_packet));
3754 for(low.red=0; low.red < 255; low.red++){
3755 intensity.red+=histogram[(
unsigned char)low.red].red;
3759 memset(&
intensity, 0,
sizeof(
struct double_packet));
3760 for(high.red=255; high.red != 0; high.red--){
3761 intensity.red+=histogram[(
unsigned char)high.red].red;
3768 memset(&
intensity, 0,
sizeof(
struct double_packet));
3769 for(high.green=255; high.green != 0; high.green--){
3770 intensity.green+=histogram[(
unsigned char)high.green].green;
3771 if(
intensity.green > threshold_intensity)
3774 if(low.green == high.green){
3775 threshold_intensity = 0;
3776 memset(&
intensity, 0,
sizeof(
struct double_packet));
3777 for(low.green=0; low.green < 255; low.green++){
3778 intensity.green+=histogram[(
unsigned char)low.green].green;
3779 if(
intensity.green > threshold_intensity)
3782 memset(&
intensity,0,
sizeof(
struct double_packet));
3783 for(high.green=255; high.green != 0; high.green--){
3784 intensity.green+=histogram[(
unsigned char)high.green].green;
3785 if(
intensity.green > threshold_intensity)
3791 memset(&
intensity, 0,
sizeof(
struct double_packet));
3792 for(high.blue=255; high.blue != 0; high.blue--){
3793 intensity.blue+=histogram[(
unsigned char)high.blue].blue;
3794 if(
intensity.blue > threshold_intensity)
3797 if(low.blue == high.blue){
3798 threshold_intensity = 0;
3799 memset(&
intensity, 0,
sizeof(
struct double_packet));
3800 for(low.blue=0; low.blue < 255; low.blue++){
3801 intensity.blue+=histogram[(
unsigned char)low.blue].blue;
3802 if(
intensity.blue > threshold_intensity)
3805 memset(&
intensity,0,
sizeof(
struct double_packet));
3806 for(high.blue=255; high.blue != 0; high.blue--){
3807 intensity.blue+=histogram[(
unsigned char)high.blue].blue;
3808 if(
intensity.blue > threshold_intensity)
3814 memset(&
intensity, 0,
sizeof(
struct double_packet));
3815 for(high.alpha=255; high.alpha != 0; high.alpha--){
3816 intensity.alpha+=histogram[(
unsigned char)high.alpha].alpha;
3817 if(
intensity.alpha > threshold_intensity)
3820 if(low.alpha == high.alpha){
3821 threshold_intensity = 0;
3822 memset(&
intensity, 0,
sizeof(
struct double_packet));
3823 for(low.alpha=0; low.alpha < 255; low.alpha++){
3824 intensity.alpha+=histogram[(
unsigned char)low.alpha].alpha;
3825 if(
intensity.alpha > threshold_intensity)
3828 memset(&
intensity,0,
sizeof(
struct double_packet));
3829 for(high.alpha=255; high.alpha != 0; high.alpha--){
3830 intensity.alpha+=histogram[(
unsigned char)high.alpha].alpha;
3831 if(
intensity.alpha > threshold_intensity)
3835 liberateMemory(&histogram);
3842 memset(normalize_map, 0 ,256*
sizeof(
struct short_packet));
3843 for(i=0; i <= (long) 255; i++){
3844 if(i < (
long) low.red)
3845 normalize_map[i].red=0;
3846 else if (i > (
long) high.red)
3847 normalize_map[i].red=65535;
3848 else if (low.red != high.red)
3849 normalize_map[i].red =
3850 (
unsigned short)((65535*(i-low.red))/(high.red-low.red));
3852 if(i < (
long) low.green)
3853 normalize_map[i].green=0;
3854 else if (i > (
long) high.green)
3855 normalize_map[i].green=65535;
3856 else if (low.green != high.green)
3857 normalize_map[i].green =
3858 (
unsigned short)((65535*(i-low.green))/(high.green-low.green));
3860 if(i < (
long) low.blue)
3861 normalize_map[i].blue=0;
3862 else if (i > (
long) high.blue)
3863 normalize_map[i].blue=65535;
3864 else if (low.blue != high.blue)
3865 normalize_map[i].blue =
3866 (
unsigned short)((65535*(i-low.blue))/(high.blue-low.blue));
3868 if(i < (
long) low.alpha)
3869 normalize_map[i].alpha=0;
3870 else if (i > (
long) high.alpha)
3871 normalize_map[i].alpha=65535;
3872 else if (low.alpha != high.alpha)
3873 normalize_map[i].alpha =
3874 (
unsigned short)((65535*(i-low.alpha))/(high.alpha-low.alpha));
3878 for(y=0; y < image.height(); ++y){
3879 q = (
unsigned int *)image.scanLine(y);
3880 for(x=0; x < image.width(); ++x){
3881 if(low.red != high.red)
3882 r = (normalize_map[(
unsigned short)(tqRed(q[x]))].red)/257;
3885 if(low.green != high.green)
3886 g = (normalize_map[(
unsigned short)(tqGreen(q[x]))].green)/257;
3889 if(low.blue != high.blue)
3890 b = (normalize_map[(
unsigned short)(tqBlue(q[x]))].blue)/257;
3893 if(low.alpha != high.alpha)
3894 a = (normalize_map[(
unsigned short)(tqAlpha(q[x]))].alpha)/257;
3897 q[x] = tqRgba(r, g, b, a);
3900 liberateMemory(&normalize_map);
3905 struct double_packet high, low,
intensity, *map, *histogram;
3906 struct short_packet *equalize_map;
3908 unsigned int *p, *q;
3910 unsigned char r, g, b, a;
3912 if(image.depth() < 32)
3913 image = image.convertDepth(32);
3915 histogram=(
struct double_packet *) malloc(256*
sizeof(
struct double_packet));
3916 map=(
struct double_packet *) malloc(256*
sizeof(
struct double_packet));
3917 equalize_map=(
struct short_packet *)malloc(256*
sizeof(
struct short_packet));
3918 if(!histogram || !map || !equalize_map){
3920 liberateMemory(&histogram);
3922 liberateMemory(&map);
3924 liberateMemory(&equalize_map);
3925 tqWarning(
"KImageEffect::equalize(): Unable to allocate memory!");
3932 memset(histogram, 0, 256*
sizeof(
struct double_packet));
3933 for(y=0; y < image.height(); ++y){
3934 p = (
unsigned int *)image.scanLine(y);
3935 for(x=0; x < image.width(); ++x){
3936 histogram[(
unsigned char)(tqRed(*p))].red++;
3937 histogram[(
unsigned char)(tqGreen(*p))].green++;
3938 histogram[(
unsigned char)(tqBlue(*p))].blue++;
3939 histogram[(
unsigned char)(tqAlpha(*p))].alpha++;
3946 memset(&
intensity, 0 ,
sizeof(
struct double_packet));
3947 for(i=0; i <= 255; ++i){
3956 memset(equalize_map, 0, 256*
sizeof(short_packet));
3957 for(i=0; i <= 255; ++i){
3958 if(high.red != low.red)
3959 equalize_map[i].red=(
unsigned short)
3960 ((65535*(map[i].red-low.red))/(high.red-low.red));
3961 if(high.green != low.green)
3962 equalize_map[i].green=(
unsigned short)
3963 ((65535*(map[i].green-low.green))/(high.green-low.green));
3964 if(high.blue != low.blue)
3965 equalize_map[i].blue=(
unsigned short)
3966 ((65535*(map[i].blue-low.blue))/(high.blue-low.blue));
3967 if(high.alpha != low.alpha)
3968 equalize_map[i].alpha=(
unsigned short)
3969 ((65535*(map[i].alpha-low.alpha))/(high.alpha-low.alpha));
3971 liberateMemory(&histogram);
3972 liberateMemory(&map);
3977 for(y=0; y < image.height(); ++y){
3978 q = (
unsigned int *)image.scanLine(y);
3979 for(x=0; x < image.width(); ++x){
3980 if(low.red != high.red)
3981 r = (equalize_map[(
unsigned short)(tqRed(q[x]))].red/257);
3984 if(low.green != high.green)
3985 g = (equalize_map[(
unsigned short)(tqGreen(q[x]))].green/257);
3988 if(low.blue != high.blue)
3989 b = (equalize_map[(
unsigned short)(tqBlue(q[x]))].blue/257);
3992 if(low.alpha != high.alpha)
3993 a = (equalize_map[(
unsigned short)(tqAlpha(q[x]))].alpha/257);
3996 q[x] = tqRgba(r, g, b, a);
3999 liberateMemory(&equalize_map);
4017 width = getOptimalKernelWidth(radius, 0.5);
4018 if(image.width() < width || image.height() < width){
4019 tqWarning(
"KImageEffect::edge(): Image is smaller than radius!");
4022 kernel= (
double *)malloc(width*width*
sizeof(
double));
4024 tqWarning(
"KImageEffect::edge(): Unable to allocate memory!");
4027 for(i=0; i < (width*width); i++)
4029 kernel[i/2]=width*width-1.0;
4030 convolveImage(&image, &dest, width, kernel);
4038 return(
emboss(src, 0, 1));
4043 double alpha, *kernel;
4049 tqWarning(
"KImageEffect::emboss(): Zero sigma is not permitted!");
4053 width = getOptimalKernelWidth(radius, sigma);
4054 if(image.width() < width || image.height() < width){
4055 tqWarning(
"KImageEffect::emboss(): Image is smaller than radius!");
4058 kernel= (
double *)malloc(width*width*
sizeof(
double));
4060 tqWarning(
"KImageEffect::emboss(): Unable to allocate memory!");
4063 if(image.depth() < 32)
4064 image = image.convertDepth(32);
4068 for(v=(-width/2); v <= (width/2); v++){
4069 for(u=(-width/2); u <= (width/2); u++){
4070 alpha=exp(-((
double) u*u+v*v)/(2.0*sigma*sigma));
4071 kernel[i]=((u < 0) || (v < 0) ? -8.0 : 8.0)*alpha/
4072 (2.0*MagickPI*sigma*sigma);
4079 convolveImage(&image, &dest, width, kernel);
4080 liberateMemory(&kernel);
4086 void KImageEffect::blurScanLine(
double *kernel,
int width,
4087 unsigned int *src,
unsigned int *dest,
4094 double red, green, blue, alpha;
4097 if(width > columns){
4098 for(x=0; x < columns; ++x){
4100 red = blue = green = alpha = 0.0;
4103 for(i=0; i < columns; ++i){
4104 if((i >= (x-width/2)) && (i <= (x+width/2))){
4105 red += (*p)*(tqRed(*q)*257);
4106 green += (*p)*(tqGreen(*q)*257);
4107 blue += (*p)*(tqBlue(*q)*257);
4108 alpha += (*p)*(tqAlpha(*q)*257);
4110 if(((i+width/2-x) >= 0) && ((i+width/2-x) < width))
4111 scale+=kernel[i+width/2-x];
4116 red = scale*(red+0.5);
4117 green = scale*(green+0.5);
4118 blue = scale*(blue+0.5);
4119 alpha = scale*(alpha+0.5);
4121 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4122 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4123 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4124 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4126 dest[x] = tqRgba((
unsigned char)(red/257UL),
4127 (
unsigned char)(green/257UL),
4128 (
unsigned char)(blue/257UL),
4129 (
unsigned char)(alpha/257UL));
4134 for(x=0; x < width/2; ++x){
4136 red = blue = green = alpha = 0.0;
4137 p = kernel+width/2-x;
4139 for(i=width/2-x; i < width; ++i){
4140 red += (*p)*(tqRed(*q)*257);
4141 green += (*p)*(tqGreen(*q)*257);
4142 blue += (*p)*(tqBlue(*q)*257);
4143 alpha += (*p)*(tqAlpha(*q)*257);
4150 red = scale*(red+0.5);
4151 green = scale*(green+0.5);
4152 blue = scale*(blue+0.5);
4153 alpha = scale*(alpha+0.5);
4155 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4156 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4157 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4158 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4160 dest[x] = tqRgba((
unsigned char)(red/257UL),
4161 (
unsigned char)(green/257UL),
4162 (
unsigned char)(blue/257UL),
4163 (
unsigned char)(alpha/257UL));
4166 for(; x < columns-width/2; ++x){
4167 red = blue = green = alpha = 0.0;
4169 q = src+(x-width/2);
4170 for (i=0; i < (long) width; ++i){
4171 red += (*p)*(tqRed(*q)*257);
4172 green += (*p)*(tqGreen(*q)*257);
4173 blue += (*p)*(tqBlue(*q)*257);
4174 alpha += (*p)*(tqAlpha(*q)*257);
4178 red = scale*(red+0.5);
4179 green = scale*(green+0.5);
4180 blue = scale*(blue+0.5);
4181 alpha = scale*(alpha+0.5);
4183 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4184 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4185 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4186 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4188 dest[x] = tqRgba((
unsigned char)(red/257UL),
4189 (
unsigned char)(green/257UL),
4190 (
unsigned char)(blue/257UL),
4191 (
unsigned char)(alpha/257UL));
4194 for(; x < columns; ++x){
4195 red = blue = green = alpha = 0.0;
4198 q = src+(x-width/2);
4199 for(i=0; i < columns-x+width/2; ++i){
4200 red += (*p)*(tqRed(*q)*257);
4201 green += (*p)*(tqGreen(*q)*257);
4202 blue += (*p)*(tqBlue(*q)*257);
4203 alpha += (*p)*(tqAlpha(*q)*257);
4209 red = scale*(red+0.5);
4210 green = scale*(green+0.5);
4211 blue = scale*(blue+0.5);
4212 alpha = scale*(alpha+0.5);
4214 red = red < 0 ? 0 : red > 65535 ? 65535 : red;
4215 green = green < 0 ? 0 : green > 65535 ? 65535 : green;
4216 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue;
4217 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha;
4219 dest[x] = tqRgba((
unsigned char)(red/257UL),
4220 (
unsigned char)(green/257UL),
4221 (
unsigned char)(blue/257UL),
4222 (
unsigned char)(alpha/257UL));
4226 int KImageEffect::getBlurKernel(
int width,
double sigma,
double **kernel)
4228 #define KernelRank 3
4233 assert(sigma != 0.0);
4236 *kernel=(
double *)malloc(width*
sizeof(
double));
4237 if(*kernel == (
double *)NULL)
4239 memset(*kernel, 0, width*
sizeof(
double));
4240 bias = KernelRank*width/2;
4241 for(i=(-bias); i <= bias; i++){
4242 alpha=exp(-((
double) i*i)/(2.0*KernelRank*KernelRank*sigma*sigma));
4243 (*kernel)[(i+bias)/KernelRank]+=alpha/(MagickSQ2PI*sigma);
4246 for(i=0; i < width; i++)
4248 for(i=0; i < width; i++)
4257 return(
blur(src, 0, 1));
4266 unsigned int *scanline, *temp;
4267 unsigned int *p, *q;
4270 tqWarning(
"KImageEffect::blur(): Zero sigma is not permitted!");
4273 if(src.depth() < 32)
4274 src = src.convertDepth(32);
4276 kernel=(
double *) NULL;
4278 width=getBlurKernel((
int) (2*ceil(radius)+1),sigma,&kernel);
4280 double *last_kernel;
4281 last_kernel=(
double *) NULL;
4282 width=getBlurKernel(3,sigma,&kernel);
4284 while ((
long) (MaxRGB*kernel[0]) > 0){
4285 if(last_kernel != (
double *)NULL){
4286 liberateMemory(&last_kernel);
4289 kernel = (
double *)NULL;
4290 width = getBlurKernel(width+2, sigma, &kernel);
4292 if(last_kernel != (
double *) NULL){
4293 liberateMemory(&kernel);
4295 kernel = last_kernel;
4300 tqWarning(
"KImageEffect::blur(): Kernel radius is too small!");
4301 liberateMemory(&kernel);
4305 dest.create(src.width(), src.height(), 32);
4308 scanline = (
unsigned int *)malloc(
sizeof(
unsigned int)*src.height());
4309 temp = (
unsigned int *)malloc(
sizeof(
unsigned int)*src.height());
4310 for(y=0; y < src.height(); ++y){
4311 p = (
unsigned int *)src.scanLine(y);
4312 q = (
unsigned int *)dest.scanLine(y);
4313 blurScanLine(kernel, width, p, q, src.width());
4316 TQImage partial = dest;
4319 unsigned int **srcTable = (
unsigned int **)partial.jumpTable();
4320 unsigned int **destTable = (
unsigned int **)dest.jumpTable();
4321 for(x=0; x < partial.width(); ++x){
4322 for(y=0; y < partial.height(); ++y){
4323 scanline[y] = srcTable[y][x];
4325 blurScanLine(kernel, width, scanline, temp, partial.height());
4326 for(y=0; y < partial.height(); ++y){
4327 destTable[y][x] = temp[y];
4336 bool KImageEffect::convolveImage(TQImage *image, TQImage *dest,
4337 const unsigned int order,
4338 const double *kernel)
4341 double red, green, blue, alpha;
4345 int x, y, mx, my, sx, sy;
4350 if((width % 2) == 0){
4351 tqWarning(
"KImageEffect: Kernel width must be an odd number!");
4354 normal_kernel = (
double *)malloc(width*width*
sizeof(
double));
4356 tqWarning(
"KImageEffect: Unable to allocate memory!");
4360 dest->create(image->width(), image->height(), 32);
4361 if(image->depth() < 32)
4362 *image = image->convertDepth(32);
4365 for(i=0; i < (width*width); i++)
4370 for(i=0; i < (width*width); i++)
4373 unsigned int **jumpTable = (
unsigned int **)image->jumpTable();
4374 for(y=0; y < dest->height(); ++y){
4376 q = (
unsigned int *)dest->scanLine(y);
4377 for(x=0; x < dest->width(); ++x){
4379 red = green = blue = alpha = 0;
4381 for(mcy=0; mcy < width; ++mcy, ++sy){
4382 my = sy < 0 ? 0 : sy > image->height()-1 ?
4383 image->height()-1 : sy;
4385 for(mcx=0; mcx < width; ++mcx, ++sx){
4386 mx = sx < 0 ? 0 : sx > image->width()-1 ?
4387 image->width()-1 : sx;
4388 red += (*k)*(tqRed(jumpTable[my][mx])*257);
4389 green += (*k)*(tqGreen(jumpTable[my][mx])*257);
4390 blue += (*k)*(tqBlue(jumpTable[my][mx])*257);
4391 alpha += (*k)*(tqAlpha(jumpTable[my][mx])*257);
4396 red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
4397 green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
4398 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
4399 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
4401 *q++ = tqRgba((
unsigned char)(red/257UL),
4402 (
unsigned char)(green/257UL),
4403 (
unsigned char)(blue/257UL),
4404 (
unsigned char)(alpha/257UL));
4407 free(normal_kernel);
4412 int KImageEffect::getOptimalKernelWidth(
double radius,
double sigma)
4418 assert(sigma != 0.0);
4420 return((
int)(2.0*ceil(radius)+1.0));
4423 for(u=(-width/2); u <= (width/2); u++)
4424 normalize+=exp(-((
double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma);
4426 value=exp(-((
double) u*u)/(2.0*sigma*sigma))/(MagickSQ2PI*sigma)/
normalize;
4427 if((
long)(65535*value) <= 0)
4431 return((
int)width-2);
4448 tqWarning(
"KImageEffect::sharpen(): Zero sigma is not permitted!");
4451 width = getOptimalKernelWidth(radius, sigma);
4452 if(image.width() < width){
4453 tqWarning(
"KImageEffect::sharpen(): Image is smaller than radius!");
4456 kernel = (
double *)malloc(width*width*
sizeof(
double));
4458 tqWarning(
"KImageEffect::sharpen(): Unable to allocate memory!");
4464 for(v=(-width/2); v <= (width/2); v++){
4465 for(u=(-width/2); u <= (width/2); u++){
4466 alpha=exp(-((
double) u*u+v*v)/(2.0*sigma*sigma));
4467 kernel[i]=alpha/(2.0*MagickPI*sigma*sigma);
4473 convolveImage(&image, &dest, width, kernel);
4487 double distance, normal_distance,
shade;
4490 struct PointInfo light, normal;
4494 TQImage dest(src.width(), src.height(), 32);
4496 azimuth = DegreesToRadians(azimuth);
4497 elevation = DegreesToRadians(elevation);
4498 light.x = MaxRGB*cos(azimuth)*cos(elevation);
4499 light.y = MaxRGB*sin(azimuth)*cos(elevation);
4500 light.z = MaxRGB*sin(elevation);
4503 if(src.depth() > 8){
4504 unsigned int *p, *s0, *s1, *s2;
4505 for(y=0; y < src.height(); ++y){
4506 p = (
unsigned int *)src.scanLine(TQMIN(TQMAX(y-1,0),src.height()-3));
4507 q = (
unsigned int *)dest.scanLine(y);
4509 *q++=(*(p+src.width()));
4512 s1 = p + src.width();
4513 s2 = p + 2*src.width();
4514 for(x=1; x < src.width()-1; ++x){
4516 normal.x=intensityValue(*(s0-1))+intensityValue(*(s1-1))+intensityValue(*(s2-1))-
4517 (double) intensityValue(*(s0+1))-(
double) intensityValue(*(s1+1))-
4518 (double) intensityValue(*(s2+1));
4519 normal.y=intensityValue(*(s2-1))+intensityValue(*s2)+intensityValue(*(s2+1))-
4520 (double) intensityValue(*(s0-1))-(
double) intensityValue(*s0)-
4521 (double) intensityValue(*(s0+1));
4522 if((normal.x == 0) && (normal.y == 0))
4526 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4527 if (distance > 0.0){
4529 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
4530 if(fabs(normal_distance) > 0.0000001)
4531 shade=distance/sqrt(normal_distance);
4535 *q = tqRgba((
unsigned char)(
shade),
4536 (
unsigned char)(
shade),
4537 (
unsigned char)(
shade),
4541 *q = tqRgba((
unsigned char)((
shade*tqRed(*s1))/(MaxRGB+1)),
4542 (
unsigned char)((
shade*tqGreen(*s1))/(MaxRGB+1)),
4543 (
unsigned char)((
shade*tqBlue(*s1))/(MaxRGB+1)),
4555 unsigned char *p, *s0, *s1, *s2;
4557 unsigned int *cTable = (
unsigned int *)src.colorTable();
4558 for(y=0; y < src.height(); ++y){
4559 scanLineIdx = TQMIN(TQMAX(y-1,0),src.height()-3);
4560 p = (
unsigned char *)src.scanLine(scanLineIdx);
4561 q = (
unsigned int *)dest.scanLine(y);
4564 s1 = (
unsigned char *) src.scanLine(scanLineIdx+1);
4565 s2 = (
unsigned char *) src.scanLine(scanLineIdx+2);
4566 *q++=(*(cTable+(*s1)));
4571 for(x=1; x < src.width()-1; ++x){
4573 normal.x=intensityValue(*(cTable+(*(s0-1))))+intensityValue(*(cTable+(*(s1-1))))+intensityValue(*(cTable+(*(s2-1))))-
4574 (double) intensityValue(*(cTable+(*(s0+1))))-(
double) intensityValue(*(cTable+(*(s1+1))))-
4575 (double) intensityValue(*(cTable+(*(s2+1))));
4576 normal.y=intensityValue(*(cTable+(*(s2-1))))+intensityValue(*(cTable+(*s2)))+intensityValue(*(cTable+(*(s2+1))))-
4577 (double) intensityValue(*(cTable+(*(s0-1))))-(
double) intensityValue(*(cTable+(*s0)))-
4578 (double) intensityValue(*(cTable+(*(s0+1))));
4579 if((normal.x == 0) && (normal.y == 0))
4583 distance=normal.x*light.x+normal.y*light.y+normal.z*light.z;
4584 if (distance > 0.0){
4586 normal.x*normal.x+normal.y*normal.y+normal.z*normal.z;
4587 if(fabs(normal_distance) > 0.0000001)
4588 shade=distance/sqrt(normal_distance);
4592 *q = tqRgba((
unsigned char)(
shade),
4593 (
unsigned char)(
shade),
4594 (
unsigned char)(
shade),
4595 tqAlpha(*(cTable+(*s1))));
4598 *q = tqRgba((
unsigned char)((
shade*tqRed(*(cTable+(*s1))))/(MaxRGB+1)),
4599 (
unsigned char)((
shade*tqGreen(*(cTable+(*s1))))/(MaxRGB+1)),
4600 (
unsigned char)((
shade*tqBlue(*(cTable+(*s1))))/(MaxRGB+1)),
4608 *q++=(*(cTable+(*s1)));
4623 double brightness, scale, theta;
4628 scale=0.5000000000000001;
4629 if(img.depth() > 8){
4630 count = img.width()*img.height();
4631 data = (
unsigned int *)img.bits();
4634 count = img.numColors();
4635 data = (
unsigned int *)img.colorTable();
4637 for(i=0; i < count; ++i){
4640 brightness = v/255.0;
4641 theta=(brightness-0.5)*M_PI;
4642 brightness+=scale*(((scale*((sin(theta)+1.0)))-brightness)*sign);
4643 if (brightness > 1.0)
4648 v = (int)(brightness*255);
4650 data[i] = tqRgba(c.red(), c.green(), c.blue(), tqAlpha(data[i]));
4655 struct BumpmapParams {
4656 BumpmapParams(
double bm_azimuth,
double bm_elevation,
4660 double azimuth = DegreesToRadians( bm_azimuth );
4661 double elevation = DegreesToRadians( bm_elevation );
4664 lx = (int)( cos(azimuth) * cos(elevation) * 255.0 );
4665 ly = (int)( sin(azimuth) * cos(elevation) * 255.0 );
4666 int lz = (int)( sin(elevation) * 255.0 );
4669 int nz = (6 * 255) / bm_depth;
4677 compensation = sin(elevation);
4680 for (
int i = 0; i < 256; i++)
4685 case KImageEffect::Spherical:
4686 n = i / 255.0 - 1.0;
4687 lut[i] = (int) (255.0 * sqrt(1.0 - n * n) + 0.5);
4690 case KImageEffect::Sinuosidal:
4692 lut[i] = (int) (255.0 * (sin((-M_PI / 2.0) + M_PI * n) + 1.0) /
4696 case KImageEffect::Linear:
4702 lut[i] = 255 - lut[i];
4708 double compensation;
4713 static void bumpmap_convert_row( uint *row,
4724 has_alpha = has_alpha ? 1 : 0;
4727 for (; width; width--)
4730 unsigned int idx = (
unsigned int)(intensityValue( *row ) + 0.5);
4731 *p++ = lut[(
unsigned int) ( waterlevel +
4733 waterlevel) * tqBlue( *row )) / 255.0 )];
4735 unsigned int idx = (
unsigned int)(intensityValue( *row ) + 0.5);
4743 static void bumpmap_row( uint *src,
4754 bool row_in_bumpmap,
4757 BumpmapParams *params )
4759 int xofs1, xofs2, xofs3;
4767 xofs2 = MOD(tmp, bm_width);
4769 for (x = 0; x < width; x++)
4773 if (tiled || (row_in_bumpmap &&
4774 x >= - tmp && x < - tmp + bm_width)) {
4776 xofs1 = MOD(xofs2 - 1, bm_width);
4777 xofs3 = MOD(xofs2 + 1, bm_width);
4779 xofs1 = FXCLAMP(xofs2 - 1, 0, bm_width - 1);
4780 xofs3 = FXCLAMP(xofs2 + 1, 0, bm_width - 1);
4782 nx = (bm_row1[xofs1] + bm_row2[xofs1] + bm_row3[xofs1] -
4783 bm_row1[xofs3] - bm_row2[xofs3] - bm_row3[xofs3]);
4784 ny = (bm_row3[xofs1] + bm_row3[xofs2] + bm_row3[xofs3] -
4785 bm_row1[xofs1] - bm_row1[xofs2] - bm_row1[xofs3]);
4792 if ((nx == 0) && (ny == 0))
4793 shade = params->background;
4795 ndotl = nx * params->lx + ny * params->ly + params->nzlz;
4798 shade = (int)( params->compensation * ambient );
4800 shade = (int)( ndotl / sqrt(
double(nx * nx + ny * ny + params->nz2)) );
4802 shade = (int)( shade + TQMAX(0.0, (255 * params->compensation - shade)) *
4814 int red = (int)((tqRed( *src ) * shade) / (params->compensation * 255));
4815 int green = (int)((tqGreen( *src ) * shade) / (params->compensation * 255));
4816 int blue = (int)((tqBlue( *src ) * shade) / (params->compensation * 255));
4817 int alpha = (int)((tqAlpha( *src ) * shade) / (params->compensation * 255));
4819 *dest++ = tqRgba( red, green, blue, alpha );
4821 int red = tqRed( *src ) * shade / 255;
4822 int green = tqGreen( *src ) * shade / 255;
4823 int blue = tqBlue( *src ) * shade / 255;
4824 int alpha = tqAlpha( *src ) * shade / 255;
4826 *dest++ = tqRgba( red, green, blue, alpha );
4831 if (++xofs2 == bm_width)
4856 int depth,
int xofs,
int yofs,
int waterlevel,
4857 int ambient,
bool compensate,
bool invert,
4862 if ( img.depth() != 32 || img.depth() != 32 ) {
4863 tqWarning(
"Bump-mapping effect works only with 32 bit images");
4867 dst.create( img.width(), img.height(), img.depth() );
4868 int bm_width = map.width();
4869 int bm_height = map.height();
4870 int bm_bpp = map.depth();
4871 int bm_has_alpha = map.hasAlphaBuffer();
4873 int yofs1, yofs2, yofs3;
4876 yofs2 = MOD( yofs, bm_height );
4877 yofs1 = MOD( yofs2 - 1, bm_height);
4878 yofs3 = MOD( yofs2 + 1, bm_height);
4882 yofs3 = FXCLAMP( yofs2+1, 0, bm_height - 1 );
4885 BumpmapParams params( azimuth, elevation, depth, type, invert );
4887 uint* bm_row1 = (
unsigned int*)map.scanLine( yofs1 );
4888 uint* bm_row2 = (
unsigned int*)map.scanLine( yofs2 );
4889 uint* bm_row3 = (
unsigned int*)map.scanLine( yofs3 );
4891 bumpmap_convert_row( bm_row1, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4892 bumpmap_convert_row( bm_row2, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4893 bumpmap_convert_row( bm_row3, bm_width, bm_bpp, bm_has_alpha, params.lut, waterlevel );
4895 for (
int y = 0; y < img.height(); ++y)
4897 int row_in_bumpmap = (y >= - yofs && y < - yofs + bm_height);
4899 uint* src_row = (
unsigned int*)img.scanLine( y );
4900 uint* dest_row = (
unsigned int*)dst.scanLine( y );
4902 bumpmap_row( src_row, dest_row, img.width(), img.depth(), img.hasAlphaBuffer(),
4903 bm_row1, bm_row2, bm_row3, bm_width, xofs,
4905 row_in_bumpmap, ambient, compensate,
4910 if (tiled || row_in_bumpmap)
4912 uint* bm_tmprow = bm_row1;
4915 bm_row3 = bm_tmprow;
4917 if (++yofs2 == bm_height)
4921 yofs3 = MOD(yofs2 + 1, bm_height);
4923 yofs3 = FXCLAMP(yofs2 + 1, 0, bm_height - 1);
4925 bm_row3 = (
unsigned int*)map.scanLine( yofs3 );
4926 bumpmap_convert_row( bm_row3, bm_width, bm_bpp, bm_has_alpha,
4927 params.lut, waterlevel );
4942 TQImage alphaImage = input;
4943 if (!alphaImage.isNull()) alphaImage = alphaImage.convertDepth( 32 );
4945 int w = alphaImage.width();
4946 int h = alphaImage.height();
4955 for (
int y = 0; y < h; ++y) {
4956 ls = (TQRgb *)alphaImage.scanLine( y );
4957 for (
int x = 0; x < w; ++x) {
4959 alpha_adjust = (tqAlpha( l )/255.0);
4960 r = int( tqRed( l ) * alpha_adjust );
4961 g = int( tqGreen( l ) * alpha_adjust );
4962 b = int( tqBlue( l ) * alpha_adjust );
4963 a = int( tqAlpha( l ) * 1.0 );
4964 ls[x] = tqRgba( r, g, b, a );
static bool haveExtension(unsigned int extension)
Returns true if the processor supports extension, and false otherwise.
@ IntelSSE2
Intel's SSE2 instructions.
@ IntelMMX
Intel's MMX instructions.
static TQImage shade(TQImage &src, bool color_shading=true, double azimuth=30.0, double elevation=30.0)
Shades the image using a distance light source.
NoiseType
This enum provides a noise type specification.
@ GaussianNoise
Gaussian distribution.
@ MultiplicativeGaussianNoise
Multiplicative Gaussian distribution.
@ ImpulseNoise
Impulse distribution.
@ PoissonNoise
Poisson distribution.
@ UniformNoise
Uniform distribution.
@ LaplacianNoise
Laplacian distribution.
static TQImage edge(TQImage &src, double radius)
Detects edges in an image using pixel neighborhoods and an edge detection mask.
static void equalize(TQImage &img)
Performs histogram equalisation on the reference image.
static void threshold(TQImage &img, unsigned int value=128)
Thresholds the reference image.
static TQImage & dither(TQImage &image, const TQColor *palette, int size)
Dither an image using Floyd-Steinberg dithering for low-color situations.
static TQRect computeDestinationRect(const TQSize &lowerSize, Disposition disposition, TQImage &upper)
Compute the destination rectangle where to draw the upper image on top of another image using the giv...
static TQImage & blend(const TQColor &clr, TQImage &dst, float opacity)
Blends a color into the destination image, using an opacity value for blending one into another.
static TQImage emboss(TQImage &src, double radius, double sigma)
Embosses the source image.
static TQImage & channelIntensity(TQImage &image, float percent, RGBComponent channel)
Modifies the intensity of a pixmap's RGB channel component.
static TQImage swirl(TQImage &src, double degrees=50.0, unsigned int background=0xFFFFFFFF)
Swirls the image by a specified amount.
static TQImage & fade(TQImage &image, float val, const TQColor &color)
Fade an image to a certain background color.
static TQImage charcoal(TQImage &src, double radius, double sigma)
Produces a neat little "charcoal" effect.
ModulationType
This enum provides a modulation type specification.
@ Saturation
Modulate image saturation.
@ Contrast
Modulate image contrast.
@ HueShift
Modulate image hue.
@ Intensity
Modulate image intensity.
GradientType
This enum provides a gradient type specification.
RotateDirection
This enum provides a rotation specification.
@ Rotate270
Rotate 90 degrees to the left.
@ Rotate90
Rotate 90 degrees to the right.
@ Rotate180
Rotate 180 degrees.
static TQImage gradient(const TQSize &size, const TQColor &ca, const TQColor &cb, GradientType type, int ncols=3)
Create a gradient from color a to color b of the specified type.
static TQImage oilPaintConvolve(TQImage &src, double radius)
Produces an oil painting effect.
static TQImage sample(TQImage &src, int w, int h)
Scales an image using simple pixel sampling.
static TQImage implode(TQImage &src, double factor=30.0, unsigned int background=0xFFFFFFFF)
Implodes an image by a specified percent.
Disposition
Disposition of a source image on top of a destination image.
@ CenteredAutoFit
Center and scale or scale aspect.
@ CenterTiled
Center and tile top image on bottom image.
@ CenteredMaxpect
Center and scale aspect.
@ Centered
Center top image on botton image.
@ TiledMaxpect
Tile and scale aspect.
@ Tiled
Tile top image on bottom image.
static TQImage bumpmap(TQImage &img, TQImage &map, double azimuth, double elevation, int depth, int xofs, int yofs, int waterlevel, int ambient, bool compensate, bool invert, BumpmapType type, bool tiled)
A bumpmapping algorithm.
static TQImage & modulate(TQImage &image, TQImage &modImage, bool reverse, ModulationType type, int factor, RGBComponent channel)
Modulate the image with a color channel of another image.
static TQImage & desaturate(TQImage &image, float desat=0.3)
Desaturate an image evenly.
static TQImage & flatten(TQImage &image, const TQColor &ca, const TQColor &cb, int ncols=0)
This recolors a pixmap.
Lighting
This enum provides a lighting direction specification.
@ NELite
Lighting from the top right of the image.
@ NorthLite
Lighting from the top of the image.
@ SWLite
Lighting from the bottom left of the image.
@ NWLite
Lighting from the top left of the image.
@ EastLite
Lighting from the right of the image.
@ SELite
Lighting from the bottom right of the image.
@ WestLite
Lighting from the left of the image.
@ SouthLite
Lighting from the bottom of the image.
static TQImage & toGray(TQImage &image, bool fast=false)
Convert an image to grayscale.
static TQImage rotate(TQImage &src, RotateDirection r)
Rotates the image by the specified amount.
static TQImage spread(TQImage &src, unsigned int amount=3)
Randomly displaces pixels.
static void solarize(TQImage &img, double factor=50.0)
Produces a 'solarization' effect seen when exposing a photographic film to light during the developme...
static TQImage sharpen(TQImage &src, double radius, double sigma)
Sharpens the pixels in the image using pixel neighborhoods.
static TQImage convertToPremultipliedAlpha(TQImage input)
Convert an image with standard alpha to premultiplied alpha.
static TQImage wave(TQImage &src, double amplitude=25.0, double frequency=150.0, unsigned int background=0xFFFFFFFF)
Modifies the pixels along a sine wave.
static TQImage oilPaint(TQImage &src, int radius=3)
This is provided for binary compatability only! Use the above method instead!
static TQImage & contrast(TQImage &image, int c)
Fast, but low quality contrast of an image.
static TQImage addNoise(TQImage &src, NoiseType type=GaussianNoise)
Adds noise to an image.
BumpmapType
This enum lists possible bumpmapping implementations.
RGBComponent
This enum provides a RGB channel specification.
static TQImage & selectedImage(TQImage &img, const TQColor &col)
Calculate the image for a selected image, for instance a selected icon on the desktop.
static TQImage & hash(TQImage &image, Lighting lite=NorthLite, unsigned int spacing=0)
Build a hash on any given TQImage.
static void normalize(TQImage &img)
Normalises the pixel values to span the full range of color values.
static TQImage blur(TQImage &src, double radius, double sigma)
Blurs an image by convolving pixel neighborhoods.
static TQImage & intensity(TQImage &image, float percent)
Either brighten or dim the image by a specified percent.
static TQImage unbalancedGradient(const TQSize &size, const TQColor &ca, const TQColor &cb, GradientType type, int xfactor=100, int yfactor=100, int ncols=3)
Create an unbalanced gradient.
static void contrastHSV(TQImage &img, bool sharpen=true)
High quality, expensive HSV contrast.
static bool blendOnLower(int x, int y, const TQImage &upper, const TQImage &lower)
Blend an image into another one, using alpha in the expected way and over coordinates x and y with re...
static TQImage despeckle(TQImage &src)
Minimizes speckle noise in the source image using the 8 hull algorithm.
kndbgstream & endl(kndbgstream &s)