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