|
MythTV
0.26-pre
|
00001 #include "mainvisual.h" 00002 #include "bumpscope.h" 00003 00004 #include <compat.h> 00005 #include <mythlogging.h> 00006 00007 // This was: 00008 // Bump Scope - Visualization Plugin for XMMS 00009 // Copyright (C) 1999-2001 Zinx Verituse 00010 00011 #include <cmath> 00012 #include <cstdlib> 00013 00014 #include <iostream> 00015 using namespace std; 00016 00017 #include <QCoreApplication> 00018 #include <QPainter> 00019 00020 BumpScope::BumpScope() : 00021 m_image(NULL), 00022 00023 m_size(0,0), 00024 00025 m_color(0x2050FF), 00026 m_x(0), m_y(0), m_width(800), m_height(600), 00027 m_phongrad(800), 00028 00029 m_color_cycle(true), 00030 m_moving_light(true), 00031 //m_diamond(true), 00032 00033 m_bpl(0), 00034 00035 m_rgb_buf(NULL), 00036 00037 m_iangle(0), m_ixo(0), m_iyo(0), m_ixd(0), m_iyd(0), m_ilx(0), m_ily(0), 00038 m_was_moving(0), m_was_color(0), 00039 m_ih(0.0), m_is(0.0), m_iv(0.0), m_isd(0.0), m_ihd(0), 00040 m_icolor(0) 00041 { 00042 m_fps = 15; 00043 00044 for (unsigned int i = 255; i > 0; i--) 00045 { 00046 m_intense1[i] = cos(((double)(255 - i) * M_PI) / 512.0); 00047 m_intense2[i] = pow(m_intense1[i], 250) * 150; 00048 } 00049 m_intense1[0] = m_intense1[1]; 00050 m_intense2[0] = m_intense2[1]; 00051 } 00052 00053 BumpScope::~BumpScope() 00054 { 00055 if (m_rgb_buf) 00056 delete [] m_rgb_buf; 00057 00058 if (m_image) 00059 delete m_image; 00060 00061 for (unsigned int i = 0; i < m_phongdat.size(); i++) 00062 m_phongdat[i].resize(0); 00063 m_phongdat.resize(0); 00064 } 00065 00066 void BumpScope::resize(const QSize &newsize) 00067 { 00068 m_size = newsize; 00069 00070 m_size.setHeight((m_size.height() / 2) * 2); 00071 m_size.setWidth((m_size.width() / 4) * 4); 00072 00073 if (m_rgb_buf) 00074 delete [] m_rgb_buf; 00075 00076 int bufsize = (m_size.height() + 2) * (m_size.width() + 2); 00077 00078 m_rgb_buf = new unsigned char[bufsize]; 00079 00080 m_bpl = m_size.width() + 2; 00081 00082 if (m_image) 00083 delete m_image; 00084 00085 m_image = new QImage(m_size.width(), m_size.height(), QImage::Format_Indexed8); 00086 00087 m_width = m_size.width(); 00088 m_height = m_size.height(); 00089 m_phongrad = m_width; 00090 00091 m_x = m_width / 2; 00092 m_y = m_height; 00093 00094 m_phongdat.resize(m_phongrad * 2); 00095 for (unsigned int i = 0; i < m_phongdat.size(); i++) 00096 m_phongdat[i].resize(m_phongrad * 2); 00097 00098 generate_phongdat(); 00099 generate_cmap(m_color); 00100 } 00101 00102 void BumpScope::blur_8(unsigned char *ptr, int w, int h, int bpl) 00103 { 00104 (void)w; 00105 00106 register unsigned int i, sum; 00107 register unsigned char *iptr; 00108 00109 iptr = ptr + bpl + 1; 00110 i = bpl * h; 00111 00112 while (i--) 00113 { 00114 sum = (iptr[-bpl] + iptr[-1] + iptr[1] + iptr[bpl]) >> 2; 00115 if (sum > 2) 00116 sum -= 2; 00117 *(iptr++) = sum; 00118 } 00119 } 00120 00121 void BumpScope::generate_cmap(unsigned int color) 00122 { 00123 unsigned int i, red, blue, green, r, g, b; 00124 00125 if (m_image) 00126 { 00127 red = (unsigned int)(color / 0x10000); 00128 green = (unsigned int)((color % 0x10000) / 0x100); 00129 blue = (unsigned int)(color % 0x100); 00130 00131 for (i = 255; i > 0; i--) 00132 { 00133 r = (unsigned int)(((double)(100 * red / 255) * m_intense1[i] + m_intense2[i])); 00134 if (r > 255) 00135 r = 255; 00136 g = (unsigned int)(((double)(100 * green / 255) * m_intense1[i] + m_intense2[i])); 00137 if (g > 255) 00138 g = 255; 00139 b = (unsigned int)(((double)(100 * blue / 255) * m_intense1[i] + m_intense2[i])); 00140 if (b > 255) 00141 b = 255; 00142 00143 m_image->setColor(i, qRgba(r, g, b, 255)); 00144 } 00145 00146 m_image->setColor(0, m_image->color(1)); 00147 } 00148 } 00149 00150 void BumpScope::generate_phongdat(void) 00151 { 00152 unsigned int y, x; 00153 double i, i2; 00154 00155 unsigned int PHONGRES = m_phongrad * 2; 00156 00157 for (y = 0; y < m_phongrad; y++) 00158 { 00159 for (x = 0; x < m_phongrad; x++) 00160 { 00161 i = (double)x / ((double)m_phongrad) - 1; 00162 i2 = (double)y / ((double)m_phongrad) - 1; 00163 00164 //if (m_diamond) 00165 i = 1 - pow(i*i2,.75) - i*i - i2*i2; 00166 //else 00167 // i = 1 - i*i - i2*i2; 00168 00169 if (i >= 0) 00170 { 00171 //if (m_diamond) 00172 i = i*i*i * 255.0; 00173 //else 00174 // i = i*i*i * 255.0; 00175 00176 if (i > 255) 00177 i = 255; 00178 unsigned char uci = (unsigned char)i; 00179 00180 m_phongdat[y][x] = uci; 00181 m_phongdat[(PHONGRES-1)-y][x] = uci; 00182 m_phongdat[y][(PHONGRES-1)-x] = uci; 00183 m_phongdat[(PHONGRES-1)-y][(PHONGRES-1)-x] = uci; 00184 } 00185 else 00186 { 00187 m_phongdat[y][x] = 0; 00188 m_phongdat[(PHONGRES-1)-y][x] = 0; 00189 m_phongdat[y][(PHONGRES-1)-x] = 0; 00190 m_phongdat[(PHONGRES-1)-y][(PHONGRES-1)-x] = 0; 00191 } 00192 } 00193 } 00194 } 00195 00196 void BumpScope::translate(int x, int y, int *xo, int *yo, int *xd, int *yd, 00197 int *angle) 00198 { 00199 unsigned int HEIGHT = m_height; 00200 unsigned int WIDTH = m_width; 00201 00202 int wd2 = (int)(WIDTH / 2); 00203 int hd2 = (int)(HEIGHT / 2); 00204 00205 /* try setting y to both maxes */ 00206 *yo = HEIGHT/2; 00207 *angle = (int)(asin((float)(y-(HEIGHT/2))/(float)*yo)/(M_PI/180.0)); 00208 *xo = (int)((x-(WIDTH/2))/cos(*angle*(M_PI/180.0))); 00209 00210 if (*xo >= -wd2 && *xo <= wd2) { 00211 *xd = (*xo>0)?-1:1; 00212 *yd = 0; 00213 return; 00214 } 00215 00216 *yo = -*yo; 00217 *angle = (int)(asin((float)(y-(HEIGHT/2))/(float)*yo)/(M_PI/180.0)); 00218 *xo = (int)((x-(WIDTH/2))/cos(*angle*(M_PI/180.0))); 00219 00220 if (*xo >= -wd2 && *xo <= wd2) { 00221 *xd = (*xo>0)?-1:1; 00222 *yd = 0; 00223 return; 00224 } 00225 00226 /* try setting x to both maxes */ 00227 *xo = WIDTH/2; 00228 *angle = (int)(acos((float)(x-(WIDTH/2))/(float)*xo)/(M_PI/180.0)); 00229 *yo = (int)((y-(HEIGHT/2))/sin(*angle*(M_PI/180.0))); 00230 00231 if (*yo >= -hd2 && *yo <= hd2) { 00232 *yd = (*yo>0)?-1:1; 00233 *xd = 0; 00234 return; 00235 } 00236 00237 *xo = -*xo; 00238 *angle = (int)(acos((float)(x-(WIDTH/2))/(float)*xo)/(M_PI/180.0)); 00239 *yo = (int)((y-(HEIGHT/2))/sin(*angle*(M_PI/180.0))); 00240 00241 /* if this isn't right, it's out of our range and we don't care */ 00242 *yd = (*yo>0)?-1:1; 00243 *xd = 0; 00244 } 00245 00246 inline void BumpScope::draw_vert_line(unsigned char *buffer, int x, int y1, 00247 int y2) 00248 { 00249 int y; 00250 unsigned char *p; 00251 00252 if (y1 < y2) 00253 { 00254 p = buffer + ((y1 + 1) * m_bpl) + x + 1; 00255 for (y = y1; y <= y2; y++) 00256 { 00257 *p = 0xff; 00258 p += m_bpl; 00259 } 00260 } 00261 else if (y2 < y1) 00262 { 00263 p = buffer + ((y2 + 1) * m_bpl) + x + 1; 00264 for (y = y2; y <= y1; y++) 00265 { 00266 *p = 0xff; 00267 p += m_bpl; 00268 } 00269 } 00270 else 00271 buffer[((y1 + 1) * m_bpl) + x + 1] = 0xff; 00272 } 00273 00274 void BumpScope::render_light(int lx, int ly) 00275 { 00276 int prev_y, out_y, dy, dx, xp, yp; 00277 unsigned int PHONGRES = m_phongrad * 2; 00278 unsigned int i, j; 00279 00280 prev_y = m_bpl + 1; 00281 out_y = 0; 00282 unsigned char *outputbuf = (unsigned char *)(m_image->bits()); 00283 00284 for (dy = (-ly) + (PHONGRES / 2), j = 0; j < m_height; j++, dy++, 00285 prev_y += m_bpl - m_width) 00286 { 00287 for (dx = (-lx) + (PHONGRES / 2), i = 0; i < m_width; i++, dx++, 00288 prev_y++, out_y++) 00289 { 00290 xp = (m_rgb_buf[prev_y - 1] - m_rgb_buf[prev_y + 1]) + dx; 00291 yp = (m_rgb_buf[prev_y - m_bpl] - m_rgb_buf[prev_y + m_bpl]) + dy; 00292 00293 if (yp < 0 || yp >= (int)PHONGRES || 00294 xp < 0 || xp >= (int)PHONGRES) 00295 { 00296 outputbuf[out_y] = 0; 00297 continue; 00298 } 00299 00300 outputbuf[out_y] = m_phongdat[yp][xp]; 00301 } 00302 } 00303 } 00304 00305 void BumpScope::rgb_to_hsv(unsigned int color, double *h, double *s, double *v) 00306 { 00307 double max, min, delta, r, g, b; 00308 00309 r = (double)(color>>16) / 255.0; 00310 g = (double)((color>>8)&0xff) / 255.0; 00311 b = (double)(color&0xff) / 255.0; 00312 00313 max = r; 00314 if (g > max) max = g; 00315 if (b > max) max = b; 00316 00317 min = r; 00318 if (g < min) min = g; 00319 if (b < min) min = b; 00320 00321 *v = max; 00322 00323 if (max != 0.0) *s = (max - min) / max; 00324 else *s = 0.0; 00325 00326 if (*s == 0.0) *h = 0.0; 00327 else 00328 { 00329 delta = max - min; 00330 00331 if (r == max) *h = (g - b) / delta; 00332 else if (g == max) *h = 2.0 + (b - r) / delta; 00333 else if (b == max) *h = 4.0 + (r - g) / delta; 00334 00335 *h = *h * 60.0; 00336 00337 if (*h < 0.0) *h = *h + 360; 00338 } 00339 } 00340 00341 void BumpScope::hsv_to_rgb(double h, double s, double v, unsigned int *color) 00342 { 00343 int i; 00344 double f, w, q, t, r, g, b; 00345 00346 if (s == 0.0) 00347 s = 0.000001; 00348 00349 if (h == -1.0) 00350 { 00351 r = v; g = v; b = v; 00352 } 00353 else 00354 { 00355 if (h == 360.0) h = 0.0; 00356 h = h / 60.0; 00357 i = (int) h; 00358 f = h - i; 00359 w = v * (1.0 - s); 00360 q = v * (1.0 - (s * f)); 00361 t = v * (1.0 - (s * (1.0 - f))); 00362 00363 switch (i) 00364 { 00365 case 0: r = v; g = t; b = w; break; 00366 case 1: r = q; g = v; b = w; break; 00367 case 2: r = w; g = v; b = t; break; 00368 case 3: r = w; g = q; b = v; break; 00369 case 4: r = t; g = w; b = v; break; 00370 /*case 5: use default to keep gcc from complaining */ 00371 default: r = v; g = w; b = q; break; 00372 } 00373 } 00374 00375 *color = ((unsigned int)((double)r*255)<<16) | ((unsigned int)((double)g*255)<<8) | ((unsigned int)((double)b*255)); 00376 } 00377 00378 bool BumpScope::process(VisualNode *node) 00379 { 00380 if (!node || node->length == 0 || !m_image) 00381 return false; 00382 00383 int numSamps = 512; 00384 if (node->length < 512) 00385 numSamps = node->length; 00386 00387 unsigned int i; 00388 int y, prev_y; 00389 00390 prev_y = (int)m_height / 2 + ((int)node->left[0] * (int)m_height) / 00391 (int)0x10000; 00392 00393 if (prev_y < 0) 00394 prev_y = 0; 00395 if (prev_y >= (int)m_height) prev_y = m_height - 1; 00396 00397 for (i = 0; i < m_width; i++) 00398 { 00399 y = (i * numSamps) / (m_width - 1); 00400 y = (int)m_height / 2 + ((int)node->left[y] * (int)m_height) / 00401 (int)0x10000; 00402 00403 if (y < 0) 00404 y = 0; 00405 if (y >= (int)m_height) 00406 y = m_height - 1; 00407 00408 draw_vert_line(m_rgb_buf, i, prev_y, y); 00409 prev_y = y; 00410 } 00411 00412 blur_8(m_rgb_buf, m_width, m_height, m_bpl); 00413 00414 return false; 00415 } 00416 00417 bool BumpScope::draw(QPainter *p, const QColor &back) 00418 { 00419 if (!m_image || m_image->isNull()) 00420 { 00421 LOG(VB_GENERAL, LOG_ERR, "BumpScope::draw: Bad image"); 00422 return false; 00423 } 00424 00425 (void)back; 00426 00427 m_ilx = m_x; 00428 m_ily = m_y; 00429 00430 if (m_moving_light) 00431 { 00432 if (!m_was_moving) 00433 { 00434 translate(m_ilx, m_ily, &m_ixo, &m_iyo, &m_ixd, &m_iyd, &m_iangle); 00435 m_was_moving = 1; 00436 } 00437 00438 m_ilx = (int)(m_width / 2 + cos(m_iangle * (M_PI / 180.0)) * m_ixo); 00439 m_ily = (int)(m_height / 2 + sin(m_iangle * (M_PI / 180.0)) * m_iyo); 00440 00441 m_iangle += 2; 00442 if (m_iangle >= 360) 00443 m_iangle = 0; 00444 00445 m_ixo += m_ixd; 00446 if ((int)m_ixo > ((int)m_width / 2) || (int)m_ixo < -((int)m_width / 2)) 00447 { 00448 m_ixo = (m_ixo > 0) ? (m_width / 2) : -(m_width / 2); 00449 if (random() & 1) 00450 { 00451 m_ixd = (m_ixd > 0) ? -1 : 1; 00452 m_iyd = 0; 00453 } 00454 else 00455 { 00456 m_iyd = (m_iyd > 0) ? -1 : 1; 00457 m_ixd = 0; 00458 } 00459 } 00460 00461 m_iyo += m_iyd; 00462 if ((int)m_iyo > ((int)m_height / 2) || (int)m_iyo < -((int)m_height / 2)) 00463 { 00464 m_iyo = (m_iyo > 0) ? (m_height / 2) : -(m_height / 2); 00465 if (random() & 1) 00466 { 00467 m_ixd = (m_ixd > 0) ? -1 : 1; 00468 m_iyd = 0; 00469 } 00470 else 00471 { 00472 m_iyd = (m_iyd > 0) ? -1 : 1; 00473 m_ixd = 0; 00474 } 00475 } 00476 } 00477 00478 if (m_color_cycle) 00479 { 00480 if (!m_was_color) 00481 { 00482 rgb_to_hsv(m_color, &m_ih, &m_is, &m_iv); 00483 m_was_color = 1; 00484 00485 if (random() & 1) 00486 { 00487 m_ihd = (random() & 1) * 2 - 1; 00488 m_isd = 0; 00489 } 00490 else 00491 { 00492 m_isd = 0.01 * ((random() & 1) * 2 - 1); 00493 m_ihd = 0; 00494 } 00495 } 00496 00497 hsv_to_rgb(m_ih, m_is, m_iv, &m_icolor); 00498 00499 generate_cmap(m_icolor); 00500 00501 if (m_ihd) 00502 { 00503 m_ih += m_ihd; 00504 if (m_ih >= 360) 00505 m_ih = 0; 00506 if (m_ih < 0) 00507 m_ih = 359; 00508 if ((random() % 150) == 0) 00509 { 00510 if (random() & 1) 00511 { 00512 m_ihd = (random() & 1) * 2 - 1; 00513 m_isd = 0; 00514 } 00515 else 00516 { 00517 m_isd = 0.01 * ((random() & 1) * 2 - 1); 00518 m_ihd = 0; 00519 } 00520 } 00521 } 00522 else 00523 { 00524 m_is += m_isd; 00525 00526 if (m_is <= 0 || m_is >= 0.5) 00527 { 00528 if (m_is < 0) 00529 m_is = 0; 00530 if (m_is > 0.52) 00531 m_isd = -0.01; 00532 else if (m_is == 0) 00533 { 00534 m_ihd = random() % 360; 00535 m_isd = 0.01; 00536 } 00537 else 00538 { 00539 if (random() & 1) 00540 { 00541 m_ihd = (random() & 1) * 2 - 1; 00542 m_isd = 0; 00543 } 00544 else 00545 { 00546 m_isd = 0.01 * ((random() & 1) * 2 - 1); 00547 m_ihd = 0; 00548 } 00549 } 00550 } 00551 } 00552 } 00553 00554 render_light(m_ilx, m_ily); 00555 00556 p->drawImage(0, 0, *m_image); 00557 00558 return true; 00559 } 00560 00561 static class BumpScopeFactory : public VisFactory 00562 { 00563 public: 00564 const QString &name(void) const 00565 { 00566 static QString name = QCoreApplication::translate("Visualizers", 00567 "BumpScope"); 00568 return name; 00569 } 00570 00571 uint plugins(QStringList *list) const 00572 { 00573 *list << name(); 00574 return 1; 00575 } 00576 00577 VisualBase *create(MainVisual *parent, const QString &pluginName) const 00578 { 00579 (void)parent; 00580 (void)pluginName; 00581 return new BumpScope(); 00582 } 00583 }BumpScopeFactory;
1.7.6.1