MythTV  master
bumpscope.cpp
Go to the documentation of this file.
1 // This was:
2 // Bump Scope - Visualization Plugin for XMMS
3 // Copyright (C) 1999-2001 Zinx Verituse
4 
5 // C++ headers
6 #include <cmath>
7 #include <cstdlib>
8 #include <iostream>
9 
10 // QT headers
11 #include <QCoreApplication>
12 #include <QPainter>
13 
14 // MythTV headers
15 #include <libmythbase/compat.h>
17 #include <libmythbase/mythrandom.h>
19 
20 // Mythmusic Headers
21 #include "bumpscope.h"
22 #include "mainvisual.h"
23 
25 {
26  m_fps = 15;
27 
28  for (unsigned int i = 255; i > 0; i--)
29  {
30  m_intense1[i] = cos(((double)(255 - i) * M_PI) / 512.0);
31  m_intense2[i] = pow(m_intense1[i], 250) * 150;
32  }
33  m_intense1[0] = m_intense1[1];
34  m_intense2[0] = m_intense2[1];
35 }
36 
38 {
39  delete [] m_rgbBuf;
40  delete m_image;
41  for (auto & dat : m_phongDat)
42  dat.resize(0);
43  m_phongDat.resize(0);
44 }
45 
46 void BumpScope::resize(const QSize &newsize)
47 {
48  m_size = newsize;
49 
50  m_size.setHeight((m_size.height() / 2) * 2);
51  m_size.setWidth((m_size.width() / 4) * 4);
52 
53  delete [] m_rgbBuf;
54 
55  int bufsize = (m_size.height() + 2) * (m_size.width() + 2);
56 
57  m_rgbBuf = new unsigned char[bufsize];
58 
59  m_bpl = m_size.width() + 2;
60 
61  delete m_image;
62  m_image = new QImage(m_size.width(), m_size.height(), QImage::Format_Indexed8);
63 
64  m_width = m_size.width();
65  m_height = m_size.height();
67 
68  m_x = m_width / 2;
69  m_y = m_height;
70 
71  m_phongDat.resize(m_phongRad * 2_UZ);
72  for (auto & dat : m_phongDat)
73  dat.resize(m_phongRad * 2_UZ);
74 
77 }
78 
79 void BumpScope::blur_8(unsigned char *ptr, int w, int h, ptrdiff_t bpl)
80 {
81  (void)w;
82 
83  uchar *iptr = ptr + bpl + 1;
84  uint i = bpl * h;
85 
86  while (i--)
87  {
88  uint sum = (iptr[-bpl] + iptr[-1] + iptr[1] + iptr[bpl]) >> 2;
89  if (sum > 2)
90  sum -= 2;
91  *(iptr++) = sum;
92  }
93 }
94 
95 void BumpScope::generate_cmap(unsigned int color)
96 {
97  if (m_image)
98  {
99  uint red = color / 0x10000;
100  uint green = (color % 0x10000) / 0x100;
101  uint blue = color % 0x100;
102 
103  for (uint i = 255; i > 0; i--)
104  {
105  uint r = (unsigned int)((100 * static_cast<double>(red) / 255)
106  * m_intense1[i] + m_intense2[i]);
107  if (r > 255)
108  r = 255;
109  uint g = (unsigned int)((100 * static_cast<double>(green) / 255)
110  * m_intense1[i] + m_intense2[i]);
111  if (g > 255)
112  g = 255;
113  uint b = (unsigned int)((100 * static_cast<double>(blue) / 255)
114  * m_intense1[i] + m_intense2[i]);
115  if (b > 255)
116  b = 255;
117 
118  m_image->setColor(i, qRgba(r, g, b, 255));
119  }
120 
121  m_image->setColor(0, m_image->color(1));
122  }
123 }
124 
126 {
127  unsigned int PHONGRES = m_phongRad * 2;
128 
129  for (uint y = 0; y < m_phongRad; y++)
130  {
131  for (uint x = 0; x < m_phongRad; x++)
132  {
133  double i = (double)x / ((double)m_phongRad) - 1;
134  double i2 = (double)y / ((double)m_phongRad) - 1;
135 
136  //if (m_diamond)
137  i = 1 - pow(i*i2,.75) - i*i - i2*i2;
138  //else
139  // i = 1 - i*i - i2*i2;
140 
141  if (i >= 0)
142  {
143  //if (m_diamond)
144  i = i*i*i * 255.0;
145  //else
146  // i = i*i*i * 255.0;
147 
148  if (i > 255)
149  i = 255;
150  auto uci = (unsigned char)i;
151 
152  m_phongDat[y][x] = uci;
153  m_phongDat[(PHONGRES-1)-y][x] = uci;
154  m_phongDat[y][(PHONGRES-1)-x] = uci;
155  m_phongDat[(PHONGRES-1)-y][(PHONGRES-1)-x] = uci;
156  }
157  else
158  {
159  m_phongDat[y][x] = 0;
160  m_phongDat[(PHONGRES-1)-y][x] = 0;
161  m_phongDat[y][(PHONGRES-1)-x] = 0;
162  m_phongDat[(PHONGRES-1)-y][(PHONGRES-1)-x] = 0;
163  }
164  }
165  }
166 }
167 
168 #define M_PI_F static_cast<float>(M_PI)
169 void BumpScope::translate(int x, int y, int *xo, int *yo, int *xd, int *yd,
170  int *angle) const
171 {
172  unsigned int HEIGHT = m_height;
173  unsigned int WIDTH = m_width;
174 
175  int wd2 = (int)(WIDTH / 2);
176  int hd2 = (int)(HEIGHT / 2);
177 
178  /* try setting y to both maxes */
179  *yo = HEIGHT/2;
180  *angle = (int)(asinf((float)(y-(HEIGHT/2.0F))/(float)*yo)/(M_PI_F/180.0F));
181  *xo = (int)((x-(WIDTH/2.0F))/cosf(*angle*(M_PI/180.0)));
182 
183  if (*xo >= -wd2 && *xo <= wd2) {
184  *xd = (*xo>0)?-1:1;
185  *yd = 0;
186  return;
187  }
188 
189  *yo = -*yo;
190  *angle = (int)(asinf((float)(y-(HEIGHT/2.0F))/(float)*yo)/(M_PI_F/180.0F));
191  *xo = (int)((x-(WIDTH/2.0F))/cosf(*angle*(M_PI/180.0)));
192 
193  if (*xo >= -wd2 && *xo <= wd2) {
194  *xd = (*xo>0)?-1:1;
195  *yd = 0;
196  return;
197  }
198 
199  /* try setting x to both maxes */
200  *xo = WIDTH/2;
201  *angle = (int)(acosf((float)(x-(WIDTH/2.0F))/(float)*xo)/(M_PI_F/180.0F));
202  *yo = (int)((y-(HEIGHT/2.0F))/sinf(*angle*(M_PI/180.0)));
203 
204  if (*yo >= -hd2 && *yo <= hd2) {
205  *yd = (*yo>0)?-1:1;
206  *xd = 0;
207  return;
208  }
209 
210  *xo = -*xo;
211  *angle = (int)(acosf((float)(x-(WIDTH/2.0F))/(float)*xo)/(M_PI_F/180.0F));
212  *yo = (int)((y-(HEIGHT/2.0F))/sinf(*angle*(M_PI/180.0)));
213 
214  /* if this isn't right, it's out of our range and we don't care */
215  *yd = (*yo>0)?-1:1;
216  *xd = 0;
217 }
218 
219 inline void BumpScope::draw_vert_line(unsigned char *buffer, int x, int y1,
220  int y2) const
221 {
222  if (y1 < y2)
223  {
224  uchar *p = buffer + ((y1 + 1) * m_bpl) + x + 1;
225  for (int y = y1; y <= y2; y++)
226  {
227  *p = 0xff;
228  p += m_bpl;
229  }
230  }
231  else if (y2 < y1)
232  {
233  uchar *p = buffer + ((y2 + 1) * m_bpl) + x + 1;
234  for (int y = y2; y <= y1; y++)
235  {
236  *p = 0xff;
237  p += m_bpl;
238  }
239  }
240  else
241  buffer[((y1 + 1) * m_bpl) + x + 1] = 0xff;
242 }
243 
244 void BumpScope::render_light(int lx, int ly)
245 {
246  int dy = 0;
247  unsigned int PHONGRES = m_phongRad * 2;
248  unsigned int j = 0;
249 
250  int prev_y = m_bpl + 1;
251  int out_y = 0;
252  unsigned char *outputbuf = m_image->bits();
253 
254  for (dy = (-ly) + (PHONGRES / 2), j = 0; j < m_height; j++, dy++,
255  prev_y += m_bpl - m_width)
256  {
257  int dx = 0;
258  unsigned int i = 0;
259  for (dx = (-lx) + (PHONGRES / 2), i = 0; i < m_width; i++, dx++,
260  prev_y++, out_y++)
261  {
262  int xp = (m_rgbBuf[prev_y - 1] - m_rgbBuf[prev_y + 1]) + dx;
263  int yp = (m_rgbBuf[prev_y - m_bpl] - m_rgbBuf[prev_y + m_bpl]) + dy;
264 
265  if (yp < 0 || yp >= (int)PHONGRES ||
266  xp < 0 || xp >= (int)PHONGRES)
267  {
268  outputbuf[out_y] = 0;
269  continue;
270  }
271 
272  outputbuf[out_y] = m_phongDat[yp][xp];
273  }
274  }
275 }
276 
277 void BumpScope::rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
278 {
279  double r = (double)(color>>16) / 255.0;
280  double g = (double)((color>>8)&0xff) / 255.0;
281  double b = (double)(color&0xff) / 255.0;
282 
283  double max = r;
284  if (g > max) max = g;
285  if (b > max) max = b;
286 
287  double min = r;
288  if (g < min) min = g;
289  if (b < min) min = b;
290 
291  *v = max;
292 
293  if (max != 0.0) *s = (max - min) / max;
294  else *s = 0.0;
295 
296  if (*s == 0.0) *h = 0.0;
297  else
298  {
299  double delta = max - min;
300 
301  if (r == max) *h = (g - b) / delta;
302  else if (g == max) *h = 2.0 + (b - r) / delta;
303  else if (b == max) *h = 4.0 + (r - g) / delta;
304 
305  *h = *h * 60.0;
306 
307  if (*h < 0.0) *h = *h + 360;
308  }
309 }
310 
311 void BumpScope::hsv_to_rgb(double h, double s, double v, unsigned int *color)
312 {
313  double r = NAN;
314  double g = NAN;
315  double b = NAN;
316 
317  if (s == 0.0)
318  s = 0.000001;
319 
320  if (h == -1.0)
321  {
322  r = v; g = v; b = v;
323  }
324  else
325  {
326  if (h == 360.0) h = 0.0;
327  h = h / 60.0;
328  int i = (int) h;
329  double f = h - i;
330  double w = v * (1.0 - s);
331  double q = v * (1.0 - (s * f));
332  double t = v * (1.0 - (s * (1.0 - f)));
333 
334  switch (i)
335  {
336  case 0: r = v; g = t; b = w; break;
337  case 1: r = q; g = v; b = w; break;
338  case 2: r = w; g = v; b = t; break;
339  case 3: r = w; g = q; b = v; break;
340  case 4: r = t; g = w; b = v; break;
341  /*case 5: use default to keep gcc from complaining */
342  default: r = v; g = w; b = q; break;
343  }
344  }
345 
346  *color = ((unsigned int)(r*255)<<16) | ((unsigned int)(g*255)<<8) | ((unsigned int)(b*255));
347 }
348 
350 {
351  if (!node || node->m_length == 0 || !m_image)
352  return false;
353 
354  int numSamps = 512;
355  if (node->m_length < 512)
356  numSamps = node->m_length;
357 
358  int prev_y = (int)m_height / 2 +
359  ((int)node->m_left[0] * (int)m_height) / 0x10000;
360 
361  if (prev_y < 0)
362  prev_y = 0;
363  if (prev_y >= (int)m_height) prev_y = m_height - 1;
364 
365  for (uint i = 0; i < m_width; i++)
366  {
367  int y = (i * numSamps) / (m_width - 1);
368  y = (int)m_height / 2 +
369  ((int)node->m_left[y] * (int)m_height) / 0x10000;
370 
371  if (y < 0)
372  y = 0;
373  if (y >= (int)m_height)
374  y = m_height - 1;
375 
376  draw_vert_line(m_rgbBuf, i, prev_y, y);
377  prev_y = y;
378  }
379 
381 
382  return false;
383 }
384 
385 bool BumpScope::draw(QPainter *p, const QColor &back)
386 {
387  if (!m_image || m_image->isNull())
388  {
389  LOG(VB_GENERAL, LOG_ERR, "BumpScope::draw: Bad image");
390  return false;
391  }
392 
393  (void)back;
394 
395  m_ilx = m_x;
396  m_ily = m_y;
397 
398  if (m_movingLight)
399  {
400  if (!m_wasMoving)
401  {
403  m_wasMoving = 1;
404  }
405 
406  m_ilx = (int)(m_width / 2.0F + cosf(m_iangle * (M_PI / 180.0)) * m_ixo);
407  m_ily = (int)(m_height / 2.0F + sinf(m_iangle * (M_PI / 180.0)) * m_iyo);
408 
409  m_iangle += 2;
410  if (m_iangle >= 360)
411  m_iangle = 0;
412 
413  m_ixo += m_ixd;
414  if (m_ixo > ((int)m_width / 2) || m_ixo < -((int)m_width / 2))
415  {
416  m_ixo = (m_ixo > 0) ? (m_width / 2) : -(m_width / 2);
417  if (rand_bool())
418  {
419  m_ixd = (m_ixd > 0) ? -1 : 1;
420  m_iyd = 0;
421  }
422  else
423  {
424  m_iyd = (m_iyd > 0) ? -1 : 1;
425  m_ixd = 0;
426  }
427  }
428 
429  m_iyo += m_iyd;
430  if (m_iyo > ((int)m_height / 2) || m_iyo < -((int)m_height / 2))
431  {
432  m_iyo = (m_iyo > 0) ? (m_height / 2) : -(m_height / 2);
433  if (rand_bool())
434  {
435  m_ixd = (m_ixd > 0) ? -1 : 1;
436  m_iyd = 0;
437  }
438  else
439  {
440  m_iyd = (m_iyd > 0) ? -1 : 1;
441  m_ixd = 0;
442  }
443  }
444  }
445 
446  if (m_colorCycle)
447  {
448  if (!m_wasColor)
449  {
451  m_wasColor = 1;
452 
453  if (rand_bool())
454  {
455  m_ihd = rand_bool() ? -1 : 1;
456  m_isd = 0;
457  }
458  else
459  {
460  m_isd = rand_bool() ? -0.01 : 0.01;
461  m_ihd = 0;
462  }
463  }
464 
466 
468 
469  if (m_ihd)
470  {
471  m_ih += m_ihd;
472  if (m_ih >= 360)
473  m_ih = 0;
474  if (m_ih < 0)
475  m_ih = 359;
476  if (rand_bool(150))
477  {
478  if (rand_bool())
479  {
480  m_ihd = rand_bool() ? -1 : 1;
481  m_isd = 0;
482  }
483  else
484  {
485  m_isd = rand_bool() ? -0.01 : 0.01;
486  m_ihd = 0;
487  }
488  }
489  }
490  else
491  {
492  m_is += m_isd;
493 
494  if (m_is <= 0 || m_is >= 0.5)
495  {
496  if (m_is < 0)
497  m_is = 0;
498  if (m_is > 0.52)
499  m_isd = -0.01;
500  else if (m_is == 0)
501  {
502  m_ihd = MythRandom(0, 360 - 1);
503  m_isd = 0.01;
504  }
505  else
506  {
507  if (rand_bool())
508  {
509  m_ihd = rand_bool() ? -1 : 1;
510  m_isd = 0;
511  }
512  else
513  {
514  m_isd = rand_bool() ? -0.01 : 0.01;
515  m_ihd = 0;
516  }
517  }
518  }
519  }
520  }
521 
523 
524  p->drawImage(0, 0, *m_image);
525 
526  return true;
527 }
528 
529 static class BumpScopeFactory : public VisFactory
530 {
531  public:
532  const QString &name(void) const override // VisFactory
533  {
534  static QString s_name = QCoreApplication::translate("Visualizers",
535  "BumpScope");
536  return s_name;
537  }
538 
539  uint plugins(QStringList *list) const override // VisFactory
540  {
541  *list << name();
542  return 1;
543  }
544 
545  VisualBase *create(MainVisual *parent, const QString &pluginName) const override // VisFactory
546  {
547  (void)parent;
548  (void)pluginName;
549  return new BumpScope();
550  }
BumpScope::~BumpScope
~BumpScope() override
Definition: bumpscope.cpp:37
BumpScope::m_y
unsigned int m_y
Definition: bumpscope.h:41
BumpScopeFactory::name
const QString & name(void) const override
Definition: bumpscope.cpp:532
BumpScope::m_wasMoving
int m_wasMoving
Definition: bumpscope.h:64
HEIGHT
unsigned int HEIGHT
Definition: graphic.cpp:13
BumpScope::m_image
QImage * m_image
Definition: bumpscope.h:35
BumpScope::generate_phongdat
void generate_phongdat(void)
Definition: bumpscope.cpp:125
BumpScopeFactory
BumpScopeFactory BumpScopeFactory
back
static guint32 * back
Definition: goom_core.cpp:25
mythrandom.h
VisualNode
Definition: videovisual.h:25
BumpScope::m_phongDat
std::vector< std::vector< unsigned char > > m_phongDat
Definition: bumpscope.h:52
BumpScope::m_isd
double m_isd
Definition: bumpscope.h:69
BumpScope::m_ilx
int m_ilx
Definition: bumpscope.h:62
BumpScope::m_is
double m_is
Definition: bumpscope.h:67
WIDTH
unsigned int WIDTH
Definition: graphic.cpp:14
BumpScope::m_movingLight
bool m_movingLight
Definition: bumpscope.h:47
VisualBase
Definition: visualize.h:62
BumpScope::m_iyd
int m_iyd
Definition: bumpscope.h:61
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
BumpScope::blur_8
static void blur_8(unsigned char *ptr, int w, int h, ptrdiff_t bpl)
Definition: bumpscope.cpp:79
BumpScope::BumpScope
BumpScope()
Definition: bumpscope.cpp:24
VisualNode::m_left
short * m_left
Definition: videovisual.h:37
MythRandomStd::rand_bool
bool rand_bool(uint32_t chance=2)
return a random bool with P(true) = 1/chance
Definition: mythrandom.h:75
BumpScopeFactory::create
VisualBase * create(MainVisual *parent, const QString &pluginName) const override
Definition: bumpscope.cpp:545
BumpScope::m_height
unsigned int m_height
Definition: bumpscope.h:43
mythlogging.h
BumpScope::process
bool process(VisualNode *node) override
Definition: bumpscope.cpp:349
BumpScope::m_ih
double m_ih
Definition: bumpscope.h:66
BumpScope::rgb_to_hsv
static void rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
Definition: bumpscope.cpp:277
hardwareprofile.config.p
p
Definition: config.py:33
hardwareprofile.i18n.t
t
Definition: i18n.py:36
compat.h
VisFactory
Definition: visualize.h:91
BumpScope::translate
void translate(int x, int y, int *xo, int *yo, int *xd, int *yd, int *angle) const
Definition: bumpscope.cpp:169
BumpScope::m_width
unsigned int m_width
Definition: bumpscope.h:42
BumpScope::draw
bool draw(QPainter *p, const QColor &back) override
Definition: bumpscope.cpp:385
BumpScope::m_ixo
int m_ixo
Definition: bumpscope.h:58
BumpScopeFactory
Definition: bumpscope.cpp:529
BumpScope::m_wasColor
int m_wasColor
Definition: bumpscope.h:65
sizetliteral.h
uint
unsigned int uint
Definition: compat.h:81
bumpscope.h
BumpScope::m_iangle
int m_iangle
Definition: bumpscope.h:57
BumpScope::m_size
QSize m_size
Definition: bumpscope.h:37
BumpScope::m_colorCycle
bool m_colorCycle
Definition: bumpscope.h:46
BumpScopeFactory::plugins
uint plugins(QStringList *list) const override
Definition: bumpscope.cpp:539
BumpScope::m_iv
double m_iv
Definition: bumpscope.h:68
MainVisual
Definition: mainvisual.h:34
BumpScope::m_phongRad
unsigned int m_phongRad
Definition: bumpscope.h:44
BumpScope::m_x
unsigned int m_x
Definition: bumpscope.h:40
VisualNode::m_length
long m_length
Definition: videovisual.h:39
VisualBase::m_fps
int m_fps
Definition: visualize.h:87
BumpScope::m_color
unsigned int m_color
Definition: bumpscope.h:39
BumpScope::hsv_to_rgb
static void hsv_to_rgb(double h, double s, double v, unsigned int *color)
Definition: bumpscope.cpp:311
mainvisual.h
BumpScope::m_ily
int m_ily
Definition: bumpscope.h:63
BumpScope
Definition: bumpscope.h:8
BumpScope::m_iyo
int m_iyo
Definition: bumpscope.h:59
BumpScope::draw_vert_line
void draw_vert_line(unsigned char *buffer, int x, int y1, int y2) const
Definition: bumpscope.cpp:219
BumpScope::m_rgbBuf
unsigned char * m_rgbBuf
Definition: bumpscope.h:53
BumpScope::m_icolor
unsigned int m_icolor
Definition: bumpscope.h:71
BumpScope::m_intense2
std::array< double, 256 > m_intense2
Definition: bumpscope.h:55
BumpScope::m_intense1
std::array< double, 256 > m_intense1
Definition: bumpscope.h:54
M_PI_F
#define M_PI_F
Definition: bumpscope.cpp:168
BumpScope::m_ixd
int m_ixd
Definition: bumpscope.h:60
MythRandomStd::MythRandom
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20
BumpScope::render_light
void render_light(int lx, int ly)
Definition: bumpscope.cpp:244
BumpScope::generate_cmap
void generate_cmap(unsigned int color)
Definition: bumpscope.cpp:95
BumpScope::m_ihd
int m_ihd
Definition: bumpscope.h:70
M_PI
static constexpr double M_PI
Definition: goom_tools.h:9
BumpScope::m_bpl
ptrdiff_t m_bpl
Definition: bumpscope.h:50
BumpScope::resize
void resize(const QSize &size) override
Definition: bumpscope.cpp:46