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