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