MythTV  master
bumpscope.cpp
Go to the documentation of this file.
1 #include "mainvisual.h"
2 #include "bumpscope.h"
3 
4 #include <compat.h>
5 #include <mythlogging.h>
6 
7 // This was:
8 // Bump Scope - Visualization Plugin for XMMS
9 // Copyright (C) 1999-2001 Zinx Verituse
10 
11 #include <cmath>
12 #include <cstdlib>
13 
14 #include <iostream>
15 using namespace std;
16 
17 #include <QCoreApplication>
18 #include <QPainter>
19 
21 {
22  m_fps = 15;
23 
24  for (unsigned int i = 255; i > 0; i--)
25  {
26  m_intense1[i] = cos(((double)(255 - i) * M_PI) / 512.0);
27  m_intense2[i] = pow(m_intense1[i], 250) * 150;
28  }
29  m_intense1[0] = m_intense1[1];
30  m_intense2[0] = m_intense2[1];
31 }
32 
34 {
35  delete [] m_rgbBuf;
36  delete m_image;
37  for (auto & dat : m_phongDat)
38  dat.resize(0);
39  m_phongDat.resize(0);
40 }
41 
42 void BumpScope::resize(const QSize &newsize)
43 {
44  m_size = newsize;
45 
46  m_size.setHeight((m_size.height() / 2) * 2);
47  m_size.setWidth((m_size.width() / 4) * 4);
48 
49  delete [] m_rgbBuf;
50 
51  int bufsize = (m_size.height() + 2) * (m_size.width() + 2);
52 
53  m_rgbBuf = new unsigned char[bufsize];
54 
55  m_bpl = m_size.width() + 2;
56 
57  delete m_image;
58  m_image = new QImage(m_size.width(), m_size.height(), QImage::Format_Indexed8);
59 
60  m_width = m_size.width();
61  m_height = m_size.height();
62  m_phongRad = m_width;
63 
64  m_x = m_width / 2;
65  m_y = m_height;
66 
67  m_phongDat.resize(m_phongRad * 2);
68  for (auto & dat : m_phongDat)
69  dat.resize(m_phongRad * 2);
70 
71  generate_phongdat();
72  generate_cmap(m_color);
73 }
74 
75 void BumpScope::blur_8(unsigned char *ptr, int w, int h, int bpl)
76 {
77  (void)w;
78 
79  uchar *iptr = ptr + bpl + 1;
80  uint i = bpl * h;
81 
82  while (i--)
83  {
84  uint sum = (iptr[-bpl] + iptr[-1] + iptr[1] + iptr[bpl]) >> 2;
85  if (sum > 2)
86  sum -= 2;
87  *(iptr++) = sum;
88  }
89 }
90 
91 void BumpScope::generate_cmap(unsigned int color)
92 {
93  if (m_image)
94  {
95  uint red = color / 0x10000;
96  uint green = (color % 0x10000) / 0x100;
97  uint blue = color % 0x100;
98 
99  for (uint i = 255; i > 0; i--)
100  {
101  uint r = (unsigned int)((100 * static_cast<double>(red) / 255)
102  * m_intense1[i] + m_intense2[i]);
103  if (r > 255)
104  r = 255;
105  uint g = (unsigned int)((100 * static_cast<double>(green) / 255)
106  * m_intense1[i] + m_intense2[i]);
107  if (g > 255)
108  g = 255;
109  uint b = (unsigned int)((100 * static_cast<double>(blue) / 255)
110  * m_intense1[i] + m_intense2[i]);
111  if (b > 255)
112  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  if (i > 255)
145  i = 255;
146  auto uci = (unsigned char)i;
147 
148  m_phongDat[y][x] = uci;
149  m_phongDat[(PHONGRES-1)-y][x] = uci;
150  m_phongDat[y][(PHONGRES-1)-x] = uci;
151  m_phongDat[(PHONGRES-1)-y][(PHONGRES-1)-x] = uci;
152  }
153  else
154  {
155  m_phongDat[y][x] = 0;
156  m_phongDat[(PHONGRES-1)-y][x] = 0;
157  m_phongDat[y][(PHONGRES-1)-x] = 0;
158  m_phongDat[(PHONGRES-1)-y][(PHONGRES-1)-x] = 0;
159  }
160  }
161  }
162 }
163 
164 #define M_PI_F static_cast<float>(M_PI)
165 void BumpScope::translate(int x, int y, int *xo, int *yo, int *xd, int *yd,
166  int *angle) const
167 {
168  unsigned int HEIGHT = m_height;
169  unsigned int WIDTH = m_width;
170 
171  int wd2 = (int)(WIDTH / 2);
172  int hd2 = (int)(HEIGHT / 2);
173 
174  /* try setting y to both maxes */
175  *yo = HEIGHT/2;
176  *angle = (int)(asinf((float)(y-(HEIGHT/2.0F))/(float)*yo)/(M_PI_F/180.0F));
177  *xo = (int)((x-(WIDTH/2.0F))/cosf(*angle*(M_PI/180.0)));
178 
179  if (*xo >= -wd2 && *xo <= wd2) {
180  *xd = (*xo>0)?-1:1;
181  *yd = 0;
182  return;
183  }
184 
185  *yo = -*yo;
186  *angle = (int)(asin((float)(y-(HEIGHT/2.0F))/(float)*yo)/(M_PI_F/180.0F));
187  *xo = (int)((x-(WIDTH/2.0F))/cosf(*angle*(M_PI/180.0)));
188 
189  if (*xo >= -wd2 && *xo <= wd2) {
190  *xd = (*xo>0)?-1:1;
191  *yd = 0;
192  return;
193  }
194 
195  /* try setting x to both maxes */
196  *xo = WIDTH/2;
197  *angle = (int)(acosf((float)(x-(WIDTH/2.0F))/(float)*xo)/(M_PI_F/180.0F));
198  *yo = (int)((y-(HEIGHT/2.0F))/sinf(*angle*(M_PI/180.0)));
199 
200  if (*yo >= -hd2 && *yo <= hd2) {
201  *yd = (*yo>0)?-1:1;
202  *xd = 0;
203  return;
204  }
205 
206  *xo = -*xo;
207  *angle = (int)(acosf((float)(x-(WIDTH/2.0F))/(float)*xo)/(M_PI_F/180.0F));
208  *yo = (int)((y-(HEIGHT/2.0F))/sinf(*angle*(M_PI/180.0)));
209 
210  /* if this isn't right, it's out of our range and we don't care */
211  *yd = (*yo>0)?-1:1;
212  *xd = 0;
213 }
214 
215 inline void BumpScope::draw_vert_line(unsigned char *buffer, int x, int y1,
216  int y2) const
217 {
218  if (y1 < y2)
219  {
220  uchar *p = buffer + ((y1 + 1) * m_bpl) + x + 1;
221  for (int y = y1; y <= y2; y++)
222  {
223  *p = 0xff;
224  p += m_bpl;
225  }
226  }
227  else if (y2 < y1)
228  {
229  uchar *p = buffer + ((y2 + 1) * m_bpl) + x + 1;
230  for (int y = y2; y <= y1; y++)
231  {
232  *p = 0xff;
233  p += m_bpl;
234  }
235  }
236  else
237  buffer[((y1 + 1) * m_bpl) + x + 1] = 0xff;
238 }
239 
240 void BumpScope::render_light(int lx, int ly)
241 {
242  int dx = 0;
243  int dy = 0;
244  unsigned int PHONGRES = m_phongRad * 2;
245  unsigned int i = 0;
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  for (dx = (-lx) + (PHONGRES / 2), i = 0; i < m_width; i++, dx++,
256  prev_y++, out_y++)
257  {
258  int xp = (m_rgbBuf[prev_y - 1] - m_rgbBuf[prev_y + 1]) + dx;
259  int yp = (m_rgbBuf[prev_y - m_bpl] - m_rgbBuf[prev_y + m_bpl]) + dy;
260 
261  if (yp < 0 || yp >= (int)PHONGRES ||
262  xp < 0 || xp >= (int)PHONGRES)
263  {
264  outputbuf[out_y] = 0;
265  continue;
266  }
267 
268  outputbuf[out_y] = m_phongDat[yp][xp];
269  }
270  }
271 }
272 
273 void BumpScope::rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
274 {
275  double r = (double)(color>>16) / 255.0;
276  double g = (double)((color>>8)&0xff) / 255.0;
277  double b = (double)(color&0xff) / 255.0;
278 
279  double max = r;
280  if (g > max) max = g;
281  if (b > max) max = b;
282 
283  double min = r;
284  if (g < min) min = g;
285  if (b < min) min = b;
286 
287  *v = max;
288 
289  if (max != 0.0) *s = (max - min) / max;
290  else *s = 0.0;
291 
292  if (*s == 0.0) *h = 0.0;
293  else
294  {
295  double delta = max - min;
296 
297  if (r == max) *h = (g - b) / delta;
298  else if (g == max) *h = 2.0 + (b - r) / delta;
299  else if (b == max) *h = 4.0 + (r - g) / delta;
300 
301  *h = *h * 60.0;
302 
303  if (*h < 0.0) *h = *h + 360;
304  }
305 }
306 
307 void BumpScope::hsv_to_rgb(double h, double s, double v, unsigned int *color)
308 {
309  double r = NAN;
310  double g = NAN;
311  double b = NAN;
312 
313  if (s == 0.0)
314  s = 0.000001;
315 
316  if (h == -1.0)
317  {
318  r = v; g = v; b = v;
319  }
320  else
321  {
322  if (h == 360.0) h = 0.0;
323  h = h / 60.0;
324  int i = (int) h;
325  double f = h - i;
326  double w = v * (1.0 - s);
327  double q = v * (1.0 - (s * f));
328  double t = v * (1.0 - (s * (1.0 - f)));
329 
330  switch (i)
331  {
332  case 0: r = v; g = t; b = w; break;
333  case 1: r = q; g = v; b = w; break;
334  case 2: r = w; g = v; b = t; break;
335  case 3: r = w; g = q; b = v; break;
336  case 4: r = t; g = w; b = v; break;
337  /*case 5: use default to keep gcc from complaining */
338  default: r = v; g = w; b = q; break;
339  }
340  }
341 
342  *color = ((unsigned int)(r*255)<<16) | ((unsigned int)(g*255)<<8) | ((unsigned int)(b*255));
343 }
344 
346 {
347  if (!node || node->m_length == 0 || !m_image)
348  return false;
349 
350  int numSamps = 512;
351  if (node->m_length < 512)
352  numSamps = node->m_length;
353 
354  int prev_y = (int)m_height / 2 +
355  ((int)node->m_left[0] * (int)m_height) / 0x10000;
356 
357  if (prev_y < 0)
358  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  if (y < 0)
368  y = 0;
369  if (y >= (int)m_height)
370  y = m_height - 1;
371 
372  draw_vert_line(m_rgbBuf, i, prev_y, y);
373  prev_y = y;
374  }
375 
376  blur_8(m_rgbBuf, m_width, m_height, m_bpl);
377 
378  return false;
379 }
380 
381 bool BumpScope::draw(QPainter *p, const QColor &back)
382 {
383  if (!m_image || m_image->isNull())
384  {
385  LOG(VB_GENERAL, LOG_ERR, "BumpScope::draw: Bad image");
386  return false;
387  }
388 
389  (void)back;
390 
391  m_ilx = m_x;
392  m_ily = m_y;
393 
394  if (m_movingLight)
395  {
396  if (!m_wasMoving)
397  {
398  translate(m_ilx, m_ily, &m_ixo, &m_iyo, &m_ixd, &m_iyd, &m_iangle);
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 (random() & 1)
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 (random() & 1)
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  {
446  rgb_to_hsv(m_color, &m_ih, &m_is, &m_iv);
447  m_wasColor = 1;
448 
449  if (random() & 1)
450  {
451  m_ihd = (random() & 1) * 2 - 1;
452  m_isd = 0;
453  }
454  else
455  {
456  m_isd = 0.01 * ((random() & 1) * 2 - 1);
457  m_ihd = 0;
458  }
459  }
460 
461  hsv_to_rgb(m_ih, m_is, m_iv, &m_icolor);
462 
463  generate_cmap(m_icolor);
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 ((random() % 150) == 0)
473  {
474  if (random() & 1)
475  {
476  m_ihd = (random() & 1) * 2 - 1;
477  m_isd = 0;
478  }
479  else
480  {
481  m_isd = 0.01 * ((random() & 1) * 2 - 1);
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 = random() % 360;
499  m_isd = 0.01;
500  }
501  else
502  {
503  if (random() & 1)
504  {
505  m_ihd = (random() & 1) * 2 - 1;
506  m_isd = 0;
507  }
508  else
509  {
510  m_isd = 0.01 * ((random() & 1) * 2 - 1);
511  m_ihd = 0;
512  }
513  }
514  }
515  }
516  }
517 
518  render_light(m_ilx, m_ily);
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(MainVisual *parent, const QString &pluginName) const override // VisFactory
542  {
543  (void)parent;
544  (void)pluginName;
545  return new BumpScope();
546  }
BumpScope::~BumpScope
~BumpScope() override
Definition: bumpscope.cpp:33
BumpScopeFactory::name
const QString & name(void) const override
Definition: bumpscope.cpp:528
HEIGHT
unsigned int HEIGHT
Definition: graphic.cpp:13
BumpScope::generate_phongdat
void generate_phongdat(void)
Definition: bumpscope.cpp:121
BumpScopeFactory
BumpScopeFactory BumpScopeFactory
back
static guint32 * back
Definition: goom_core.cpp:29
VisualNode
Definition: videovisual.h:23
WIDTH
unsigned int WIDTH
Definition: graphic.cpp:14
VisualBase
Definition: visualize.h:73
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
BumpScope::BumpScope
BumpScope()
Definition: bumpscope.cpp:20
VisualNode::m_left
short * m_left
Definition: videovisual.h:34
BumpScopeFactory::create
VisualBase * create(MainVisual *parent, const QString &pluginName) const override
Definition: bumpscope.cpp:541
mythlogging.h
M_PI
#define M_PI
Definition: goom_tools.h:5
BumpScope::process
bool process(VisualNode *node) override
Definition: bumpscope.cpp:345
BumpScope::rgb_to_hsv
static void rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
Definition: bumpscope.cpp:273
hardwareprofile.config.p
p
Definition: config.py:33
hardwareprofile.i18n.t
t
Definition: i18n.py:36
compat.h
VisFactory
Definition: visualize.h:102
BumpScope::translate
void translate(int x, int y, int *xo, int *yo, int *xd, int *yd, int *angle) const
Definition: bumpscope.cpp:165
BumpScope::draw
bool draw(QPainter *p, const QColor &back) override
Definition: bumpscope.cpp:381
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:600
BumpScopeFactory
Definition: bumpscope.cpp:526
uint
unsigned int uint
Definition: compat.h:140
bumpscope.h
BumpScope::blur_8
static void blur_8(unsigned char *ptr, int w, int h, int bpl)
Definition: bumpscope.cpp:75
BumpScopeFactory::plugins
uint plugins(QStringList *list) const override
Definition: bumpscope.cpp:535
MainVisual
Definition: mainvisual.h:34
VisualNode::m_length
long m_length
Definition: videovisual.h:36
random
static long int random(void)
Definition: compat.h:149
BumpScope::hsv_to_rgb
static void hsv_to_rgb(double h, double s, double v, unsigned int *color)
Definition: bumpscope.cpp:307
mainvisual.h
BumpScope
Definition: bumpscope.h:13
BumpScope::draw_vert_line
void draw_vert_line(unsigned char *buffer, int x, int y1, int y2) const
Definition: bumpscope.cpp:215
M_PI_F
#define M_PI_F
Definition: bumpscope.cpp:164
BumpScope::render_light
void render_light(int lx, int ly)
Definition: bumpscope.cpp:240
BumpScope::generate_cmap
void generate_cmap(unsigned int color)
Definition: bumpscope.cpp:91
BumpScope::resize
void resize(const QSize &size) override
Definition: bumpscope.cpp:42