00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "ogfxeffect.h"
00011
00012
00013 #include <opie2/odebug.h>
00014 #include <qpe/qmath.h>
00015
00016
00017 #include <qimage.h>
00018 #include <qpainter.h>
00019
00020
00021 #include <cstdlib>
00022 #include <cmath>
00023
00024
00025
00026
00027
00028
00029
00030
00031 QPixmap& OGfxEffect::gradient(QPixmap &pixmap, const QColor &ca,
00032 const QColor &cb, GradientType eff, int ncols)
00033 {
00034 if ( !pixmap. isNull ( )) {
00035 QImage image = gradient(pixmap.size(), ca, cb, eff, ncols);
00036 pixmap.convertFromImage(image);
00037 }
00038 return pixmap;
00039 }
00040
00041 QImage OGfxEffect::gradient(const QSize &size, const QColor &ca,
00042 const QColor &cb, GradientType eff, int )
00043 {
00044 int rDiff, gDiff, bDiff;
00045 int rca, gca, bca, rcb, gcb, bcb;
00046
00047 QImage image(size, 32);
00048
00049 if (size.width() == 0 || size.height() == 0) {
00050 odebug << "WARNING: OGfxEffect::gradient: invalid image" << oendl;
00051 return image;
00052 }
00053
00054 register int x, y;
00055
00056 rDiff = (rcb = cb.red()) - (rca = ca.red());
00057 gDiff = (gcb = cb.green()) - (gca = ca.green());
00058 bDiff = (bcb = cb.blue()) - (bca = ca.blue());
00059
00060 if( eff == VerticalGradient || eff == HorizontalGradient ){
00061
00062 uint *p;
00063 uint rgb;
00064
00065 register int rl = rca << 16;
00066 register int gl = gca << 16;
00067 register int bl = bca << 16;
00068
00069 if( eff == VerticalGradient ) {
00070
00071 int rcdelta = ((1<<16) / size.height()) * rDiff;
00072 int gcdelta = ((1<<16) / size.height()) * gDiff;
00073 int bcdelta = ((1<<16) / size.height()) * bDiff;
00074
00075 for ( y = 0; y < size.height(); y++ ) {
00076 p = (uint *) image.scanLine(y);
00077
00078 rl += rcdelta;
00079 gl += gcdelta;
00080 bl += bcdelta;
00081
00082 rgb = qRgb( (rl>>16), (gl>>16), (bl>>16) );
00083
00084 for( x = 0; x < size.width(); x++ ) {
00085 *p = rgb;
00086 p++;
00087 }
00088 }
00089
00090 }
00091 else {
00092
00093 unsigned int *o_src = (unsigned int *)image.scanLine(0);
00094 unsigned int *src = o_src;
00095
00096 int rcdelta = ((1<<16) / size.width()) * rDiff;
00097 int gcdelta = ((1<<16) / size.width()) * gDiff;
00098 int bcdelta = ((1<<16) / size.width()) * bDiff;
00099
00100 for( x = 0; x < size.width(); x++) {
00101
00102 rl += rcdelta;
00103 gl += gcdelta;
00104 bl += bcdelta;
00105
00106 *src++ = qRgb( (rl>>16), (gl>>16), (bl>>16));
00107 }
00108
00109 src = o_src;
00110
00111
00112
00113
00114
00115 for (y = 1; y < size.height(); ++y) {
00116
00117 p = (unsigned int *)image.scanLine(y);
00118 src = o_src;
00119 for(x=0; x < size.width(); ++x)
00120 *p++ = *src++;
00121 }
00122 }
00123 }
00124
00125 else {
00126
00127 float rfd, gfd, bfd;
00128 float rd = rca, gd = gca, bd = bca;
00129
00130 unsigned char *xtable[3];
00131 unsigned char *ytable[3];
00132
00133 unsigned int w = size.width(), h = size.height();
00134 xtable[0] = new unsigned char[w];
00135 xtable[1] = new unsigned char[w];
00136 xtable[2] = new unsigned char[w];
00137 ytable[0] = new unsigned char[h];
00138 ytable[1] = new unsigned char[h];
00139 ytable[2] = new unsigned char[h];
00140 w*=2, h*=2;
00141
00142 if ( eff == DiagonalGradient || eff == CrossDiagonalGradient) {
00143
00144
00145
00146
00147 rfd = (float)rDiff/w;
00148 gfd = (float)gDiff/w;
00149 bfd = (float)bDiff/w;
00150
00151 int dir;
00152 for (x = 0; x < size.width(); x++, rd+=rfd, gd+=gfd, bd+=bfd) {
00153 dir = eff == DiagonalGradient? x : size.width() - x - 1;
00154 xtable[0][dir] = (unsigned char) rd;
00155 xtable[1][dir] = (unsigned char) gd;
00156 xtable[2][dir] = (unsigned char) bd;
00157 }
00158 rfd = (float)rDiff/h;
00159 gfd = (float)gDiff/h;
00160 bfd = (float)bDiff/h;
00161 rd = gd = bd = 0;
00162 for (y = 0; y < size.height(); y++, rd+=rfd, gd+=gfd, bd+=bfd) {
00163 ytable[0][y] = (unsigned char) rd;
00164 ytable[1][y] = (unsigned char) gd;
00165 ytable[2][y] = (unsigned char) bd;
00166 }
00167
00168 for (y = 0; y < size.height(); y++) {
00169 unsigned int *scanline = (unsigned int *)image.scanLine(y);
00170 for (x = 0; x < size.width(); x++) {
00171 scanline[x] = qRgb(xtable[0][x] + ytable[0][y],
00172 xtable[1][x] + ytable[1][y],
00173 xtable[2][x] + ytable[2][y]);
00174 }
00175 }
00176 }
00177
00178 else if (eff == RectangleGradient ||
00179 eff == PyramidGradient ||
00180 eff == PipeCrossGradient ||
00181 eff == EllipticGradient)
00182 {
00183 int rSign = rDiff>0? 1: -1;
00184 int gSign = gDiff>0? 1: -1;
00185 int bSign = bDiff>0? 1: -1;
00186
00187 rfd = (float)rDiff / size.width();
00188 gfd = (float)gDiff / size.width();
00189 bfd = (float)bDiff / size.width();
00190
00191 rd = (float)rDiff/2;
00192 gd = (float)gDiff/2;
00193 bd = (float)bDiff/2;
00194
00195 for (x = 0; x < size.width(); x++, rd-=rfd, gd-=gfd, bd-=bfd)
00196 {
00197 xtable[0][x] = (unsigned char) abs((int)rd);
00198 xtable[1][x] = (unsigned char) abs((int)gd);
00199 xtable[2][x] = (unsigned char) abs((int)bd);
00200 }
00201
00202 rfd = (float)rDiff/size.height();
00203 gfd = (float)gDiff/size.height();
00204 bfd = (float)bDiff/size.height();
00205
00206 rd = (float)rDiff/2;
00207 gd = (float)gDiff/2;
00208 bd = (float)bDiff/2;
00209
00210 for (y = 0; y < size.height(); y++, rd-=rfd, gd-=gfd, bd-=bfd)
00211 {
00212 ytable[0][y] = (unsigned char) abs((int)rd);
00213 ytable[1][y] = (unsigned char) abs((int)gd);
00214 ytable[2][y] = (unsigned char) abs((int)bd);
00215 }
00216 unsigned int rgb;
00217 int h = (size.height()+1)>>1;
00218 for (y = 0; y < h; y++) {
00219 unsigned int *sl1 = (unsigned int *)image.scanLine(y);
00220 unsigned int *sl2 = (unsigned int *)image.scanLine(QMAX(size.height()-y-1, y));
00221
00222 int w = (size.width()+1)>>1;
00223 int x2 = size.width()-1;
00224
00225 for (x = 0; x < w; x++, x2--) {
00226 rgb = 0;
00227 if (eff == PyramidGradient) {
00228 rgb = qRgb(rcb-rSign*(xtable[0][x]+ytable[0][y]),
00229 gcb-gSign*(xtable[1][x]+ytable[1][y]),
00230 bcb-bSign*(xtable[2][x]+ytable[2][y]));
00231 }
00232 if (eff == RectangleGradient) {
00233 rgb = qRgb(rcb - rSign *
00234 QMAX(xtable[0][x], ytable[0][y]) * 2,
00235 gcb - gSign *
00236 QMAX(xtable[1][x], ytable[1][y]) * 2,
00237 bcb - bSign *
00238 QMAX(xtable[2][x], ytable[2][y]) * 2);
00239 }
00240 if (eff == PipeCrossGradient) {
00241 rgb = qRgb(rcb - rSign *
00242 QMIN(xtable[0][x], ytable[0][y]) * 2,
00243 gcb - gSign *
00244 QMIN(xtable[1][x], ytable[1][y]) * 2,
00245 bcb - bSign *
00246 QMIN(xtable[2][x], ytable[2][y]) * 2);
00247 }
00248 if (eff == EllipticGradient) {
00249 rgb = qRgb(rcb - rSign *
00250 (int)sqrt((xtable[0][x]*xtable[0][x] +
00251 ytable[0][y]*ytable[0][y])*2.0),
00252 gcb - gSign *
00253 (int)sqrt((xtable[1][x]*xtable[1][x] +
00254 ytable[1][y]*ytable[1][y])*2.0),
00255 bcb - bSign *
00256 (int)sqrt((xtable[2][x]*xtable[2][x] +
00257 ytable[2][y]*ytable[2][y])*2.0));
00258 }
00259
00260 sl1[x] = sl2[x] = rgb;
00261 sl1[x2] = sl2[x2] = rgb;
00262 }
00263 }
00264 }
00265
00266 delete [] xtable[0];
00267 delete [] xtable[1];
00268 delete [] xtable[2];
00269 delete [] ytable[0];
00270 delete [] ytable[1];
00271 delete [] ytable[2];
00272 }
00273 return image;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 QPixmap& OGfxEffect::blend(QPixmap &pixmap, float initial_intensity,
00285 const QColor &bgnd, GradientType eff,
00286 bool anti_dir, int )
00287 {
00288 if ( !pixmap. isNull ( )) {
00289 QImage image = pixmap.convertToImage();
00290 OGfxEffect::blend(image, initial_intensity, bgnd, eff, anti_dir);
00291
00292 if ( pixmap. depth ( ) <= 8 )
00293 image. convertDepth ( pixmap. depth ( ));
00294
00295 pixmap.convertFromImage(image);
00296 }
00297 return pixmap;
00298 }
00299
00300
00301 QImage& OGfxEffect::blend(QImage &image, float initial_intensity,
00302 const QColor &bgnd, GradientType eff,
00303 bool anti_dir)
00304 {
00305 if (image.width() == 0 || image.height() == 0) {
00306 odebug << "Invalid image" << oendl;
00307 return image;
00308 }
00309
00310 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
00311 int r, g, b;
00312 int ind;
00313
00314 unsigned int xi, xf, yi, yf;
00315 unsigned int a;
00316
00317
00318 float unaffected = 1;
00319 if (initial_intensity > 1) initial_intensity = 1;
00320 if (initial_intensity < -1) initial_intensity = -1;
00321 if (initial_intensity < 0) {
00322 unaffected = 1. + initial_intensity;
00323 initial_intensity = 0;
00324 }
00325
00326
00327 float intensity = initial_intensity;
00328 float var = 1. - initial_intensity;
00329
00330 if (anti_dir) {
00331 initial_intensity = intensity = 1.;
00332 var = -var;
00333 }
00334
00335 register int x, y;
00336
00337 unsigned int *data = (unsigned int *)image.bits();
00338
00339 if( eff == VerticalGradient || eff == HorizontalGradient ) {
00340
00341
00342 xi = 0, xf = image.width();
00343 yi = 0, yf = image.height();
00344 if (eff == VerticalGradient) {
00345 if (anti_dir) yf = (int)(image.height() * unaffected);
00346 else yi = (int)(image.height() * (1 - unaffected));
00347 }
00348 else {
00349 if (anti_dir) xf = (int)(image.width() * unaffected);
00350 else xi = (int)(image.height() * (1 - unaffected));
00351 }
00352
00353 var /= (eff == VerticalGradient?yf-yi:xf-xi);
00354
00355 for (y = yi; y < (int)yf; y++) {
00356 intensity = eff == VerticalGradient? intensity + var :
00357 initial_intensity;
00358 for (x = xi; x < (int)xf ; x++) {
00359 if (eff == HorizontalGradient) intensity += var;
00360 ind = x + image.width() * y ;
00361 r = qRed (data[ind]) + (int)(intensity *
00362 (r_bgnd - qRed (data[ind])));
00363 g = qGreen(data[ind]) + (int)(intensity *
00364 (g_bgnd - qGreen(data[ind])));
00365 b = qBlue (data[ind]) + (int)(intensity *
00366 (b_bgnd - qBlue (data[ind])));
00367 if (r > 255) r = 255; if (r < 0 ) r = 0;
00368 if (g > 255) g = 255; if (g < 0 ) g = 0;
00369 if (b > 255) b = 255; if (b < 0 ) b = 0;
00370 a = qAlpha(data[ind]);
00371 data[ind] = qRgba(r, g, b, a);
00372 }
00373 }
00374 }
00375 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
00376 float xvar = var / 2 / image.width();
00377 float yvar = var / 2 / image.height();
00378 float tmp;
00379
00380 for (x = 0; x < image.width() ; x++) {
00381 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
00382 for (y = 0; y < image.height() ; y++) {
00383 intensity = initial_intensity + tmp + yvar * y;
00384 ind = x + image.width() * y ;
00385 r = qRed (data[ind]) + (int)(intensity *
00386 (r_bgnd - qRed (data[ind])));
00387 g = qGreen(data[ind]) + (int)(intensity *
00388 (g_bgnd - qGreen(data[ind])));
00389 b = qBlue (data[ind]) + (int)(intensity *
00390 (b_bgnd - qBlue (data[ind])));
00391 if (r > 255) r = 255; if (r < 0 ) r = 0;
00392 if (g > 255) g = 255; if (g < 0 ) g = 0;
00393 if (b > 255) b = 255; if (b < 0 ) b = 0;
00394 a = qAlpha(data[ind]);
00395 data[ind] = qRgba(r, g, b, a);
00396 }
00397 }
00398 }
00399
00400 else if (eff == RectangleGradient || eff == EllipticGradient) {
00401 float xvar;
00402 float yvar;
00403
00404 for (x = 0; x < image.width() / 2 + image.width() % 2; x++) {
00405 xvar = var / image.width() * (image.width() - x*2/unaffected-1);
00406 for (y = 0; y < image.height() / 2 + image.height() % 2; y++) {
00407 yvar = var / image.height() * (image.height() - y*2/unaffected -1);
00408
00409 if (eff == RectangleGradient)
00410 intensity = initial_intensity + QMAX(xvar, yvar);
00411 else
00412 intensity = initial_intensity + qSqrt(xvar * xvar + yvar * yvar);
00413 if (intensity > 1) intensity = 1;
00414 if (intensity < 0) intensity = 0;
00415
00416
00417 ind = x + image.width() * y ;
00418 r = qRed (data[ind]) + (int)(intensity *
00419 (r_bgnd - qRed (data[ind])));
00420 g = qGreen(data[ind]) + (int)(intensity *
00421 (g_bgnd - qGreen(data[ind])));
00422 b = qBlue (data[ind]) + (int)(intensity *
00423 (b_bgnd - qBlue (data[ind])));
00424 if (r > 255) r = 255; if (r < 0 ) r = 0;
00425 if (g > 255) g = 255; if (g < 0 ) g = 0;
00426 if (b > 255) b = 255; if (b < 0 ) b = 0;
00427 a = qAlpha(data[ind]);
00428 data[ind] = qRgba(r, g, b, a);
00429
00430
00431 ind = image.width() - x - 1 + image.width() * y ;
00432 r = qRed (data[ind]) + (int)(intensity *
00433 (r_bgnd - qRed (data[ind])));
00434 g = qGreen(data[ind]) + (int)(intensity *
00435 (g_bgnd - qGreen(data[ind])));
00436 b = qBlue (data[ind]) + (int)(intensity *
00437 (b_bgnd - qBlue (data[ind])));
00438 if (r > 255) r = 255; if (r < 0 ) r = 0;
00439 if (g > 255) g = 255; if (g < 0 ) g = 0;
00440 if (b > 255) b = 255; if (b < 0 ) b = 0;
00441 a = qAlpha(data[ind]);
00442 data[ind] = qRgba(r, g, b, a);
00443 }
00444 }
00445
00446
00447
00448 for (x = 0; x < image.width() / 2; x++) {
00449 xvar = var / image.width() * (image.width() - x*2/unaffected-1);
00450 for (y = 0; y < image.height() / 2; y++) {
00451 yvar = var / image.height() * (image.height() - y*2/unaffected -1);
00452
00453 if (eff == RectangleGradient)
00454 intensity = initial_intensity + QMAX(xvar, yvar);
00455 else
00456 intensity = initial_intensity + qSqrt(xvar * xvar + yvar * yvar);
00457 if (intensity > 1) intensity = 1;
00458 if (intensity < 0) intensity = 0;
00459
00460
00461 ind = x + image.width() * (image.height() - y -1) ;
00462 r = qRed (data[ind]) + (int)(intensity *
00463 (r_bgnd - qRed (data[ind])));
00464 g = qGreen(data[ind]) + (int)(intensity *
00465 (g_bgnd - qGreen(data[ind])));
00466 b = qBlue (data[ind]) + (int)(intensity *
00467 (b_bgnd - qBlue (data[ind])));
00468 if (r > 255) r = 255; if (r < 0 ) r = 0;
00469 if (g > 255) g = 255; if (g < 0 ) g = 0;
00470 if (b > 255) b = 255; if (b < 0 ) b = 0;
00471 a = qAlpha(data[ind]);
00472 data[ind] = qRgba(r, g, b, a);
00473
00474
00475 ind = image.width()-x-1 + image.width() * (image.height() - y - 1) ;
00476 r = qRed (data[ind]) + (int)(intensity *
00477 (r_bgnd - qRed (data[ind])));
00478 g = qGreen(data[ind]) + (int)(intensity *
00479 (g_bgnd - qGreen(data[ind])));
00480 b = qBlue (data[ind]) + (int)(intensity *
00481 (b_bgnd - qBlue (data[ind])));
00482 if (r > 255) r = 255; if (r < 0 ) r = 0;
00483 if (g > 255) g = 255; if (g < 0 ) g = 0;
00484 if (b > 255) b = 255; if (b < 0 ) b = 0;
00485 a = qAlpha(data[ind]);
00486 data[ind] = qRgba(r, g, b, a);
00487 }
00488 }
00489 }
00490
00491 else
00492 odebug << "not implemented" << oendl;
00493
00494 return image;
00495 }
00496
00497 #if 0
00498
00499
00500 QImage& KQGfxEffect::blend(QImage &image1, QImage &image2,
00501 GradientType gt, int xf, int yf)
00502 {
00503 if (image1.width() == 0 || image1.height() == 0 ||
00504 image2.width() == 0 || image2.height() == 0)
00505 return image1;
00506
00507 QImage image3;
00508
00509 image3 = KQGfxEffect::unbalancedGradient(image1.size(),
00510 QColor(0,0,0), QColor(255,255,255),
00511 gt, xf, yf, 0);
00512
00513 return blend(image1,image2,image3, Red);
00514 }
00515 #endif