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 
16 #include <QCoreApplication>
17 #include <QPainter>
18 
20 {
21  m_fps = 15;
22 
23  for (unsigned int i = 255; i > 0; i--)
24  {
25  m_intense1[i] = cos(((double)(255 - i) * M_PI) / 512.0);
26  m_intense2[i] = pow(m_intense1[i], 250) * 150;
27  }
28  m_intense1[0] = m_intense1[1];
29  m_intense2[0] = m_intense2[1];
30 }
31 
33 {
34  delete [] m_rgbBuf;
35  delete m_image;
36  for (auto & dat : m_phongDat)
37  dat.resize(0);
38  m_phongDat.resize(0);
39 }
40 
41 void BumpScope::resize(const QSize &newsize)
42 {
43  m_size = newsize;
44 
45  m_size.setHeight((m_size.height() / 2) * 2);
46  m_size.setWidth((m_size.width() / 4) * 4);
47 
48  delete [] m_rgbBuf;
49 
50  int bufsize = (m_size.height() + 2) * (m_size.width() + 2);
51 
52  m_rgbBuf = new unsigned char[bufsize];
53 
54  m_bpl = m_size.width() + 2;
55 
56  delete m_image;
57  m_image = new QImage(m_size.width(), m_size.height(), QImage::Format_Indexed8);
58 
59  m_width = m_size.width();
60  m_height = m_size.height();
62 
63  m_x = m_width / 2;
64  m_y = m_height;
65 
66  m_phongDat.resize(m_phongRad * 2);
67  for (auto & dat : m_phongDat)
68  dat.resize(m_phongRad * 2);
69 
72 }
73 
74 void BumpScope::blur_8(unsigned char *ptr, int w, int h, int bpl)
75 {
76  (void)w;
77 
78  uchar *iptr = ptr + bpl + 1;
79  uint i = bpl * h;
80 
81  while (i--)
82  {
83  uint sum = (iptr[-bpl] + iptr[-1] + iptr[1] + iptr[bpl]) >> 2;
84  if (sum > 2)
85  sum -= 2;
86  *(iptr++) = sum;
87  }
88 }
89 
90 void BumpScope::generate_cmap(unsigned int color)
91 {
92  if (m_image)
93  {
94  uint red = color / 0x10000;
95  uint green = (color % 0x10000) / 0x100;
96  uint blue = color % 0x100;
97 
98  for (uint i = 255; i > 0; i--)
99  {
100  uint r = (unsigned int)((100 * static_cast<double>(red) / 255)
101  * m_intense1[i] + m_intense2[i]);
102  if (r > 255)
103  r = 255;
104  uint g = (unsigned int)((100 * static_cast<double>(green) / 255)
105  * m_intense1[i] + m_intense2[i]);
106  if (g > 255)
107  g = 255;
108  uint b = (unsigned int)((100 * static_cast<double>(blue) / 255)
109  * m_intense1[i] + m_intense2[i]);
110  if (b > 255)
111  b = 255;
112 
113  m_image->setColor(i, qRgba(r, g, b, 255));
114  }
115 
116  m_image->setColor(0, m_image->color(1));
117  }
118 }
119 
121 {
122  unsigned int PHONGRES = m_phongRad * 2;
123 
124  for (uint y = 0; y < m_phongRad; y++)
125  {
126  for (uint x = 0; x < m_phongRad; x++)
127  {
128  double i = (double)x / ((double)m_phongRad) - 1;
129  double i2 = (double)y / ((double)m_phongRad) - 1;
130 
131  //if (m_diamond)
132  i = 1 - pow(i*i2,.75) - i*i - i2*i2;
133  //else
134  // i = 1 - i*i - i2*i2;
135 
136  if (i >= 0)
137  {
138  //if (m_diamond)
139  i = i*i*i * 255.0;
140  //else
141  // i = i*i*i * 255.0;
142 
143  if (i > 255)
144  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  buffer[((y1 + 1) * m_bpl) + x + 1] = 0xff;
237 }
238 
239 void BumpScope::render_light(int lx, int ly)
240 {
241  int dx = 0;
242  int dy = 0;
243  unsigned int PHONGRES = m_phongRad * 2;
244  unsigned int i = 0;
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  for (dx = (-lx) + (PHONGRES / 2), i = 0; i < m_width; i++, dx++,
255  prev_y++, out_y++)
256  {
257  int xp = (m_rgbBuf[prev_y - 1] - m_rgbBuf[prev_y + 1]) + dx;
258  int yp = (m_rgbBuf[prev_y - m_bpl] - m_rgbBuf[prev_y + m_bpl]) + dy;
259 
260  if (yp < 0 || yp >= (int)PHONGRES ||
261  xp < 0 || xp >= (int)PHONGRES)
262  {
263  outputbuf[out_y] = 0;
264  continue;
265  }
266 
267  outputbuf[out_y] = m_phongDat[yp][xp];
268  }
269  }
270 }
271 
272 void BumpScope::rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
273 {
274  double r = (double)(color>>16) / 255.0;
275  double g = (double)((color>>8)&0xff) / 255.0;
276  double b = (double)(color&0xff) / 255.0;
277 
278  double max = r;
279  if (g > max) max = g;
280  if (b > max) max = b;
281 
282  double min = r;
283  if (g < min) min = g;
284  if (b < min) min = b;
285 
286  *v = max;
287 
288  if (max != 0.0) *s = (max - min) / max;
289  else *s = 0.0;
290 
291  if (*s == 0.0) *h = 0.0;
292  else
293  {
294  double delta = max - min;
295 
296  if (r == max) *h = (g - b) / delta;
297  else if (g == max) *h = 2.0 + (b - r) / delta;
298  else if (b == max) *h = 4.0 + (r - g) / delta;
299 
300  *h = *h * 60.0;
301 
302  if (*h < 0.0) *h = *h + 360;
303  }
304 }
305 
306 void BumpScope::hsv_to_rgb(double h, double s, double v, unsigned int *color)
307 {
308  double r = NAN;
309  double g = NAN;
310  double b = NAN;
311 
312  if (s == 0.0)
313  s = 0.000001;
314 
315  if (h == -1.0)
316  {
317  r = v; g = v; b = v;
318  }
319  else
320  {
321  if (h == 360.0) h = 0.0;
322  h = h / 60.0;
323  int i = (int) h;
324  double f = h - i;
325  double w = v * (1.0 - s);
326  double q = v * (1.0 - (s * f));
327  double t = v * (1.0 - (s * (1.0 - f)));
328 
329  switch (i)
330  {
331  case 0: r = v; g = t; b = w; break;
332  case 1: r = q; g = v; b = w; break;
333  case 2: r = w; g = v; b = t; break;
334  case 3: r = w; g = q; b = v; break;
335  case 4: r = t; g = w; b = v; break;
336  /*case 5: use default to keep gcc from complaining */
337  default: r = v; g = w; b = q; break;
338  }
339  }
340 
341  *color = ((unsigned int)(r*255)<<16) | ((unsigned int)(g*255)<<8) | ((unsigned int)(b*255));
342 }
343 
345 {
346  if (!node || node->m_length == 0 || !m_image)
347  return false;
348 
349  int numSamps = 512;
350  if (node->m_length < 512)
351  numSamps = node->m_length;
352 
353  int prev_y = (int)m_height / 2 +
354  ((int)node->m_left[0] * (int)m_height) / 0x10000;
355 
356  if (prev_y < 0)
357  prev_y = 0;
358  if (prev_y >= (int)m_height) prev_y = m_height - 1;
359 
360  for (uint i = 0; i < m_width; i++)
361  {
362  int y = (i * numSamps) / (m_width - 1);
363  y = (int)m_height / 2 +
364  ((int)node->m_left[y] * (int)m_height) / 0x10000;
365 
366  if (y < 0)
367  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, 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  (void)back;
389 
390  m_ilx = m_x;
391  m_ily = m_y;
392 
393  if (m_movingLight)
394  {
395  if (!m_wasMoving)
396  {
398  m_wasMoving = 1;
399  }
400 
401  m_ilx = (int)(m_width / 2.0F + cosf(m_iangle * (M_PI / 180.0)) * m_ixo);
402  m_ily = (int)(m_height / 2.0F + sinf(m_iangle * (M_PI / 180.0)) * m_iyo);
403 
404  m_iangle += 2;
405  if (m_iangle >= 360)
406  m_iangle = 0;
407 
408  m_ixo += m_ixd;
409  if (m_ixo > ((int)m_width / 2) || m_ixo < -((int)m_width / 2))
410  {
411  m_ixo = (m_ixo > 0) ? (m_width / 2) : -(m_width / 2);
412  if (random() & 1)
413  {
414  m_ixd = (m_ixd > 0) ? -1 : 1;
415  m_iyd = 0;
416  }
417  else
418  {
419  m_iyd = (m_iyd > 0) ? -1 : 1;
420  m_ixd = 0;
421  }
422  }
423 
424  m_iyo += m_iyd;
425  if (m_iyo > ((int)m_height / 2) || m_iyo < -((int)m_height / 2))
426  {
427  m_iyo = (m_iyo > 0) ? (m_height / 2) : -(m_height / 2);
428  if (random() & 1)
429  {
430  m_ixd = (m_ixd > 0) ? -1 : 1;
431  m_iyd = 0;
432  }
433  else
434  {
435  m_iyd = (m_iyd > 0) ? -1 : 1;
436  m_ixd = 0;
437  }
438  }
439  }
440 
441  if (m_colorCycle)
442  {
443  if (!m_wasColor)
444  {
446  m_wasColor = 1;
447 
448  if (random() & 1)
449  {
450  m_ihd = (random() & 1) * 2 - 1;
451  m_isd = 0;
452  }
453  else
454  {
455  m_isd = 0.01 * ((random() & 1) * 2 - 1);
456  m_ihd = 0;
457  }
458  }
459 
461 
463 
464  if (m_ihd)
465  {
466  m_ih += m_ihd;
467  if (m_ih >= 360)
468  m_ih = 0;
469  if (m_ih < 0)
470  m_ih = 359;
471  if ((random() % 150) == 0)
472  {
473  if (random() & 1)
474  {
475  m_ihd = (random() & 1) * 2 - 1;
476  m_isd = 0;
477  }
478  else
479  {
480  m_isd = 0.01 * ((random() & 1) * 2 - 1);
481  m_ihd = 0;
482  }
483  }
484  }
485  else
486  {
487  m_is += m_isd;
488 
489  if (m_is <= 0 || m_is >= 0.5)
490  {
491  if (m_is < 0)
492  m_is = 0;
493  if (m_is > 0.52)
494  m_isd = -0.01;
495  else if (m_is == 0)
496  {
497  m_ihd = random() % 360;
498  m_isd = 0.01;
499  }
500  else
501  {
502  if (random() & 1)
503  {
504  m_ihd = (random() & 1) * 2 - 1;
505  m_isd = 0;
506  }
507  else
508  {
509  m_isd = 0.01 * ((random() & 1) * 2 - 1);
510  m_ihd = 0;
511  }
512  }
513  }
514  }
515  }
516 
518 
519  p->drawImage(0, 0, *m_image);
520 
521  return true;
522 }
523 
524 static class BumpScopeFactory : public VisFactory
525 {
526  public:
527  const QString &name(void) const override // VisFactory
528  {
529  static QString s_name = QCoreApplication::translate("Visualizers",
530  "BumpScope");
531  return s_name;
532  }
533 
534  uint plugins(QStringList *list) const override // VisFactory
535  {
536  *list << name();
537  return 1;
538  }
539 
540  VisualBase *create(MainVisual *parent, const QString &pluginName) const override // VisFactory
541  {
542  (void)parent;
543  (void)pluginName;
544  return new BumpScope();
545  }
BumpScope::~BumpScope
~BumpScope() override
Definition: bumpscope.cpp:32
BumpScope::m_y
unsigned int m_y
Definition: bumpscope.h:44
BumpScopeFactory::name
const QString & name(void) const override
Definition: bumpscope.cpp:527
BumpScope::m_wasMoving
int m_wasMoving
Definition: bumpscope.h:67
HEIGHT
unsigned int HEIGHT
Definition: graphic.cpp:13
BumpScope::m_image
QImage * m_image
Definition: bumpscope.h:38
BumpScope::generate_phongdat
void generate_phongdat(void)
Definition: bumpscope.cpp:120
BumpScopeFactory
BumpScopeFactory BumpScopeFactory
back
static guint32 * back
Definition: goom_core.cpp:30
VisualNode
Definition: videovisual.h:24
BumpScope::m_phongDat
std::vector< std::vector< unsigned char > > m_phongDat
Definition: bumpscope.h:55
BumpScope::m_isd
double m_isd
Definition: bumpscope.h:72
BumpScope::m_ilx
int m_ilx
Definition: bumpscope.h:65
BumpScope::m_is
double m_is
Definition: bumpscope.h:70
WIDTH
unsigned int WIDTH
Definition: graphic.cpp:14
BumpScope::m_movingLight
bool m_movingLight
Definition: bumpscope.h:50
VisualBase
Definition: visualize.h:72
BumpScope::m_iyd
int m_iyd
Definition: bumpscope.h:64
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
BumpScope::BumpScope
BumpScope()
Definition: bumpscope.cpp:19
VisualNode::m_left
short * m_left
Definition: videovisual.h:36
BumpScopeFactory::create
VisualBase * create(MainVisual *parent, const QString &pluginName) const override
Definition: bumpscope.cpp:540
BumpScope::m_height
unsigned int m_height
Definition: bumpscope.h:46
mythlogging.h
M_PI
#define M_PI
Definition: goom_tools.h:5
BumpScope::process
bool process(VisualNode *node) override
Definition: bumpscope.cpp:344
BumpScope::m_ih
double m_ih
Definition: bumpscope.h:69
BumpScope::rgb_to_hsv
static void rgb_to_hsv(unsigned int color, double *h, double *s, double *v)
Definition: bumpscope.cpp:272
hardwareprofile.config.p
p
Definition: config.py:33
hardwareprofile.i18n.t
t
Definition: i18n.py:36
compat.h
VisFactory
Definition: visualize.h:101
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:45
BumpScope::draw
bool draw(QPainter *p, const QColor &back) override
Definition: bumpscope.cpp:380
BumpScope::m_ixo
int m_ixo
Definition: bumpscope.h:61
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:603
BumpScopeFactory
Definition: bumpscope.cpp:524
BumpScope::m_wasColor
int m_wasColor
Definition: bumpscope.h:68
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:74
BumpScope::m_iangle
int m_iangle
Definition: bumpscope.h:60
BumpScope::m_size
QSize m_size
Definition: bumpscope.h:40
BumpScope::m_colorCycle
bool m_colorCycle
Definition: bumpscope.h:49
BumpScopeFactory::plugins
uint plugins(QStringList *list) const override
Definition: bumpscope.cpp:534
BumpScope::m_iv
double m_iv
Definition: bumpscope.h:71
MainVisual
Definition: mainvisual.h:32
BumpScope::m_phongRad
unsigned int m_phongRad
Definition: bumpscope.h:47
BumpScope::m_x
unsigned int m_x
Definition: bumpscope.h:43
VisualNode::m_length
long m_length
Definition: videovisual.h:38
VisualBase::m_fps
int m_fps
Definition: visualize.h:97
BumpScope::m_color
unsigned int m_color
Definition: bumpscope.h:42
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:306
mainvisual.h
BumpScope::m_ily
int m_ily
Definition: bumpscope.h:66
BumpScope
Definition: bumpscope.h:11
BumpScope::m_iyo
int m_iyo
Definition: bumpscope.h:62
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:56
BumpScope::m_bpl
int m_bpl
Definition: bumpscope.h:53
BumpScope::m_icolor
unsigned int m_icolor
Definition: bumpscope.h:74
BumpScope::m_intense2
std::array< double, 256 > m_intense2
Definition: bumpscope.h:58
BumpScope::m_intense1
std::array< double, 256 > m_intense1
Definition: bumpscope.h:57
M_PI_F
#define M_PI_F
Definition: bumpscope.cpp:163
BumpScope::m_ixd
int m_ixd
Definition: bumpscope.h:63
BumpScope::render_light
void render_light(int lx, int ly)
Definition: bumpscope.cpp:239
BumpScope::generate_cmap
void generate_cmap(unsigned int color)
Definition: bumpscope.cpp:90
BumpScope::m_ihd
int m_ihd
Definition: bumpscope.h:73
BumpScope::resize
void resize(const QSize &size) override
Definition: bumpscope.cpp:41