TTKMusicPlayer  4.1.3.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
imagewrapper.cpp
Go to the documentation of this file.
1 #include "imagewrapper.h"
2 #include "random.h"
3 
4 #include <qmath.h>
5 #include <QPainter>
6 
7 namespace QAlgorithm
8 {
12 class ImageRenderPrivate : public TTKPrivate<ImageRender>
13 {
14 public:
15  QRect m_rectangle;
16 };
17 
18 
21 {
22 
23 }
24 
26 {
27  TTK_INIT_PRIVATE_D(pvt);
28 }
29 
30 void ImageRender::input(const QRect &region)
31 {
33  d->m_rectangle = region;
34 }
35 
38  : ImageRender()
39 {
40 
41 }
42 
43 QPixmap GaussBlur::render(const QPixmap &pixmap, int value)
44 {
46  QImage image = pixmap.copy(d->m_rectangle).toImage();
47 
48  const float sigma = 1.0 * value / 2.57;
49  const float deno = 1.0 / (sigma * sqrt(2.0 * M_PI));
50  const float nume = -1.0 / (2.0 * sigma * sigma);
51 
52  float* gaussMatrix = (float*)malloc(sizeof(float)* (value + value + 1));
53  float gaussSum = 0.0;
54  for(int i = 0, x = -value; x <= value; ++x, ++i)
55  {
56  float g = deno * exp(1.0 * nume * x * x);
57 
58  gaussMatrix[i] = g;
59  gaussSum += g;
60  }
61 
62  const int len = value + value + 1;
63  for(int i = 0; i < len; ++i)
64  {
65  gaussMatrix[i] /= gaussSum;
66  }
67 
68  const int width = image.width();
69  const int height = image.height();
70  int *pix = (int*)image.bits();
71  int *rowData = (int*)malloc(width * sizeof(int));
72  int *listData = (int*)malloc(height * sizeof(int));
73 
74  for(int y = 0; y < height; ++y)
75  {
76  memcpy(rowData, pix + y * width, sizeof(int) *width);
77 
78  for(int x = 0; x < width; ++x)
79  {
80  float r = 0, g = 0, b = 0;
81  gaussSum = 0;
82 
83  for(int i = -value; i <= value; ++i)
84  {
85  int k = x + i;
86 
87  if(0 <= k && k <= width)
88  {
89  int color = rowData[k];
90  int cr = (color & 0x00ff0000) >> 16;
91  int cg = (color & 0x0000ff00) >> 8;
92  int cb = (color & 0x000000ff);
93 
94  r += cr * gaussMatrix[i + value];
95  g += cg * gaussMatrix[i + value];
96  b += cb * gaussMatrix[i + value];
97 
98  gaussSum += gaussMatrix[i + value];
99  }
100  }
101 
102  int cr = (int)(r / gaussSum);
103  int cg = (int)(g / gaussSum);
104  int cb = (int)(b / gaussSum);
105 
106  pix[y * width + x] = cr << 16 | cg << 8 | cb | 0xff000000;
107  }
108  }
109 
110  for(int x = 0; x < width; ++x)
111  {
112  for(int y = 0; y < height; ++y)
113  {
114  listData[y] = pix[y * width + x];
115  }
116 
117  for(int y = 0; y < height; ++y)
118  {
119  float r = 0, g = 0, b = 0;
120  gaussSum = 0;
121 
122  for(int j = -value; j <= value; ++j)
123  {
124  int k = y + j;
125 
126  if(0 <= k && k <= height)
127  {
128  int color = listData[k];
129  int cr = (color & 0x00ff0000) >> 16;
130  int cg = (color & 0x0000ff00) >> 8;
131  int cb = (color & 0x000000ff);
132 
133  r += cr * gaussMatrix[j + value];
134  g += cg * gaussMatrix[j + value];
135  b += cb * gaussMatrix[j + value];
136 
137  gaussSum += gaussMatrix[j + value];
138  }
139  }
140 
141  int cr = (int)(r / gaussSum);
142  int cg = (int)(g / gaussSum);
143  int cb = (int)(b / gaussSum);
144 
145  pix[y * width + x] = cr << 16 | cg << 8 | cb | 0xff000000;
146  }
147  }
148 
149  free(gaussMatrix);
150  free(rowData);
151  free(listData);
152  return QPixmap::fromImage(image);
153 }
154 
155 
157 
161 {
162 public:
163  CubeWavePrivate();
164 
165  void initialize(int width, int height);
166 
167  int count() const;
168  bool isValid(int index, int value) const;
169 
170  int m_row;
171  int m_column;
173 };
174 
176  : ImageRenderPrivate(),
177  m_row(0),
178  m_column(0)
179 {
181 }
182 
183 void CubeWavePrivate::initialize(int width, int height)
184 {
185  m_column = ceil(width * 1.0 / 8);
186  m_row = ceil(height * 1.0 / 8);
187 }
188 
189 bool CubeWavePrivate::isValid(int index, int value) const
190 {
191  return (index < 0 || index > m_data.count()) ? false : (m_data[index] > value);
192 }
193 
195 {
196  return 8 * 8;
197 }
198 
199 
202 {
203 
204 }
205 
206 void CubeWave::input(const QRect &region)
207 {
208  ImageRender::input(region);
209 
210  TTK_D(CubeWave);
211  d->initialize(region.width(), region.height());
212  for(int index = 0; index < d->count(); ++index)
213  {
214  d->m_data.push_back(QAlgorithm::random(100));
215  }
216 }
217 
218 QPixmap CubeWave::render(const QPixmap &pixmap, int value)
219 {
220  TTK_D(CubeWave);
221  QPixmap pix(d->m_rectangle.size());
222 
223  pix.fill(Qt::transparent);
224  for(int index = 0; index < d->count(); ++index)
225  {
226  QPainter painter(&pix);
227 
228  const int row = index / 8;
229  const int column = index % 8;
230 
231  QRect rect(QRect(row * d->m_column, column * d->m_row, d->m_column, d->m_row));
232  if(rect.y() + rect.height() > pixmap.height())
233  {
234  rect.setHeight(pixmap.height() - rect.y());
235  }
236 
237  if(d->isValid(index, value))
238  {
239  painter.fillRect(rect, QColor(0xFF, 0xFF, 0xFF, 255 - 2.55 * value));
240  }
241 
242  painter.setCompositionMode(QPainter::CompositionMode_SourceOut);
243  painter.drawPixmap(rect, pixmap.copy(rect));
244  }
245 
246  return pix;
247 }
248 
249 
251 
255 {
256 public:
259 
260  int* data();
261  void render();
262  void initialize(const QImage &image, int radius);
263 
264  void setWaveSourcePower(int depth);
265  void setWaveSourcePosition(int x, int y);
266 
267 private:
268  void spreedRipple();
269  void renderRipple();
270 
271 private:
274  short *m_buffer1;
275  short *m_buffer2;
278 
279  int m_width;
280  int m_height;
281 
283 
286 };
287 
290 {
291 
292 }
293 
295 {
296  if(m_orginPixels)
297  {
298  delete[] m_orginPixels;
299  }
300 
301  if(m_newPixels)
302  {
303  delete[] m_newPixels;
304  }
305 
306  if(m_buffer1)
307  {
308  delete[] m_buffer1;
309  }
310 
311  if(m_buffer2)
312  {
313  delete[] m_buffer2;
314  }
315 
316  if(m_sourcePower)
317  {
318  delete[] m_sourcePower;
319  }
320 
321  if(m_sourcePosition)
322  {
323  delete[] m_sourcePosition;
324  }
325 }
326 
328 {
329  return m_newPixels;
330 }
331 
333 {
334  spreedRipple();
335  renderRipple();
336 }
337 
338 void WaterWavePrivate::initialize(const QImage &image, int radius)
339 {
340  m_orginPixels = nullptr;
341  m_newPixels = nullptr;
342  m_buffer1 = nullptr;
343  m_buffer2 = nullptr;
344  m_sourcePower = nullptr;
345  m_sourcePosition = nullptr;
346 
347  m_width = image.width();
348  m_height = image.height();
349 
350  m_orginPixels = new int[m_width * m_height]{};
351  memcpy(m_orginPixels, image.bits(), m_width * m_height * 4);
352 
353  m_newPixels = new int[m_width * m_height]{};
354  memcpy(m_newPixels, image.bits(), m_width * m_height * sizeof(int));
355 
356  m_buffer1 = new short[m_width * m_height]{};
357  m_buffer2 = new short[m_width * m_height]{};
358 
359  m_powerRate = 3;
360  m_sourceRadius = TTKStaticCast(int, radius);
361 
362  setWaveSourcePower(100);
363 }
364 
366 {
367  m_sourceDepth = depth;
368 
369  const int value = m_sourceRadius * m_sourceRadius;
370  const int diameter = (m_sourceRadius << 1) + 1;
371  const int rate = m_sourceRadius / value;
372  const int size = diameter * diameter;
373 
374  m_sourcePower = new int[size]{};
375  m_sourcePosition = new int[size]{};
376 
377  for(int x = 0; x <= diameter; ++x)
378  {
379  for(int y = 0; y <= diameter; ++y)
380  {
381  const int distanceSquare = (m_sourceRadius - x) * (m_sourceRadius - x) + (m_sourceRadius - y) * (m_sourceRadius - y);
382  if(distanceSquare <= value)
383  {
384  const int depth = m_sourceDepth - distanceSquare * rate;
385  m_sourcePosition[y * diameter + x] = y * m_width + x;
386  m_sourcePower[y * diameter + x] = depth;
387  }
388  }
389  }
390 }
391 
393 {
394  const int sourceX = TTKStaticCast(int, x);
395  const int sourceY = TTKStaticCast(int, y);
396  if((sourceX + m_sourceRadius) >= m_width || (sourceY + m_sourceRadius) >= m_height || (sourceX - m_sourceRadius) <= 0 || (sourceY - m_sourceRadius) <= 0)
397  {
398  return;
399  }
400 
401  const int distance = (sourceY - m_sourceRadius) * m_width + sourceX - m_sourceRadius;
402  const int size = ((m_sourceRadius << 1) + 1) * ((m_sourceRadius << 1) + 1);
403  for(int i = 0; i < size; ++i)
404  {
405  m_buffer1[distance + m_sourcePosition[i]] = TTKStaticCast(short, m_sourcePower[i]);
406  }
407 }
408 
410 {
411  const int length = m_width * (m_height - 1);
412  for(int i = m_width; i < length; ++i)
413  {
414  m_buffer2[i] = ((m_buffer1[i - 1] + m_buffer1[i - m_width] + m_buffer1[i + 1] + m_buffer1[i + m_width]) >> 1) - m_buffer2[i];
415  m_buffer2[i] -= m_buffer2[i] >> m_powerRate;
416  }
417 
418  short* temp = m_buffer1;
420  m_buffer2 = temp;
421 }
422 
424 {
425  int offset;
426  int w = m_width;
427  for(int y = 1; y < m_height - 1; ++y)
428  {
429  for(int x = 0; x < m_width; ++x, ++w)
430  {
431  offset = (m_width * (m_buffer1[w - m_width] - m_buffer1[w + m_width])) + (m_buffer1[w - 1] - m_buffer1[w + 1]);
432  if(w + offset > 0 && w + offset < m_width * m_height)
433  {
434  m_newPixels[w] = m_orginPixels[w + offset];
435  }
436  else
437  {
438  m_newPixels[w] = m_orginPixels[w];
439  }
440  }
441  }
442 }
443 
444 
445 WaterWave::WaterWave(const QImage &image, int radius)
447 {
448  TTK_D(WaterWave);
449  d->initialize(image, radius);
450 }
451 
452 void WaterWave::input(const QRect &region)
453 {
454  ImageRender::input(region);
455 
456  TTK_D(WaterWave);
457  d->setWaveSourcePosition(region.width() / 2, region.height() / 2);
458 }
459 
460 QPixmap WaterWave::render(const QPixmap &pixmap, int value)
461 {
462  TTK_D(WaterWave);
463  d->render();
464 
465  QImage image = pixmap.toImage();
466  memcpy(image.bits(), (const uchar*)d->data(), QtImageBytes(image));
467 
468  QPixmap pix(d->m_rectangle.size());
469  pix.fill(Qt::transparent);
470 
471  QPainter painter(&pix);
472  painter.fillRect(d->m_rectangle, QColor(0xFF, 0xFF, 0xFF, qMin(2.55 * 2 * value, 255.0)));
473  painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
474  painter.drawPixmap(d->m_rectangle, QPixmap::fromImage(image));
475  return pix;
476 }
477 }
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:159
#define QtImageBytes(p)
Image byte count.
Definition: ttkqtcompat.h:38
The class of the water wave.
Definition: imagewrapper.h:111
The class of the image render.
Definition: imagewrapper.h:35
void initRandom()
Definition: random.cpp:10
WaterWave(const QImage &image, int radius)
The class of the water wave private.
voidpf void uLong size
Definition: ioapi.h:136
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
virtual QPixmap render(const QPixmap &pixmap, int value) overridefinal
The namespace of the algorithm.
int random(int value)
Definition: random.cpp:17
void setWaveSourcePower(int depth)
void initialize(const QImage &image, int radius)
voidpf uLong offset
Definition: ioapi.h:142
QList< int > TTKIntList
Definition: ttkqtglobal.h:204
#define TTK_INIT_PRIVATE_D(PVT)
Definition: ttkprivate.h:37
virtual void input(const QRect &region)
virtual QPixmap render(const QPixmap &pixmap, int value) overridefinal
#define TTK_CREATE_PRIVATE(Class)
Definition: ttkprivate.h:24
virtual void input(const QRect &region) overridefinal
virtual QPixmap render(const QPixmap &pixmap, int value) overridefinal
The class of the cube wave.
Definition: imagewrapper.h:88
void free(voidpf ptr)
void setWaveSourcePosition(int x, int y)
virtual void input(const QRect &region) overridefinal
The class of the ttk private base.
Definition: ttkprivate.h:48
voidp malloc(uInt size)
void initialize(int width, int height)
The class of the image render private.
bool isValid(int index, int value) const
The class of the cube wave private.
#define TTK_D(Class)
Definition: ttkprivate.h:41