TTKMusicPlayer  4.3.0.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 "ttktime.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 {
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 {
45  TTK_D(const ImageRender);
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 * std::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 {
180  TTK::initRandom();
181 }
182 
183 void CubeWavePrivate::initialize(int width, int height)
184 {
185  m_column = std::ceil(width * 1.0 / 8);
186  m_row = std::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.append(TTK::random(100));
215  }
216 }
217 
218 QPixmap CubeWave::render(const QPixmap &pixmap, int value)
219 {
220  TTK_D(const 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  painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
228 
229  const int row = index / 8;
230  const int column = index % 8;
231 
232  QRect rect(QRect(row * d->m_column, column * d->m_row, d->m_column, d->m_row));
233  if(rect.y() + rect.height() > pixmap.height())
234  {
235  rect.setHeight(pixmap.height() - rect.y());
236  }
237 
238  if(d->isValid(index, value))
239  {
240  painter.fillRect(rect, QColor(0xFF, 0xFF, 0xFF, 255 - 2.55 * value));
241  }
242 
243  painter.setCompositionMode(QPainter::CompositionMode_SourceOut);
244  painter.drawPixmap(rect, pixmap.copy(rect));
245  }
246 
247  return pix;
248 }
249 
250 
252 
256 {
257 public:
260 
261  int* data();
262  void render();
263  void initialize(const QImage &image, int radius);
264 
265  void setWaveSourcePower(int depth);
266  void setWaveSourcePosition(int x, int y);
267 
268 private:
269  void spreedRipple();
270  void renderRipple();
271 
272 private:
275  short *m_buffer1;
276  short *m_buffer2;
279 
280  int m_width;
281  int m_height;
282 
284 
287 };
288 
291 {
292 
293 }
294 
296 {
297  delete[] m_orginPixels;
298  delete[] m_newPixels;
299  delete[] m_buffer1;
300  delete[] m_buffer2;
301  delete[] m_sourcePower;
302  delete[] m_sourcePosition;
303 }
304 
306 {
307  return m_newPixels;
308 }
309 
311 {
312  spreedRipple();
313  renderRipple();
314 }
315 
316 void WaterWavePrivate::initialize(const QImage &image, int radius)
317 {
318  m_orginPixels = nullptr;
319  m_newPixels = nullptr;
320  m_buffer1 = nullptr;
321  m_buffer2 = nullptr;
322  m_sourcePower = nullptr;
323  m_sourcePosition = nullptr;
324 
325  m_width = image.width();
326  m_height = image.height();
327 
328  m_orginPixels = new int[m_width * m_height]{};
329  memcpy(m_orginPixels, image.bits(), m_width * m_height * 4);
330 
331  m_newPixels = new int[m_width * m_height]{};
332  memcpy(m_newPixels, image.bits(), m_width * m_height * sizeof(int));
333 
334  m_buffer1 = new short[m_width * m_height]{};
335  m_buffer2 = new short[m_width * m_height]{};
336 
337  m_powerRate = 3;
338  m_sourceRadius = TTKStaticCast(int, radius);
339 
340  setWaveSourcePower(100);
341 }
342 
344 {
345  m_sourceDepth = depth;
346 
347  const int value = m_sourceRadius * m_sourceRadius;
348  const int diameter = (m_sourceRadius << 1) + 1;
349  const int rate = m_sourceRadius / value;
350  const int size = diameter * diameter;
351 
352  m_sourcePower = new int[size]{};
353  m_sourcePosition = new int[size]{};
354 
355  for(int x = 0; x <= diameter; ++x)
356  {
357  for(int y = 0; y <= diameter; ++y)
358  {
359  const int distanceSquare = (m_sourceRadius - x) * (m_sourceRadius - x) + (m_sourceRadius - y) * (m_sourceRadius - y);
360  if(distanceSquare <= value)
361  {
362  const int depth = m_sourceDepth - distanceSquare * rate;
363  m_sourcePosition[y * diameter + x] = y * m_width + x;
364  m_sourcePower[y * diameter + x] = depth;
365  }
366  }
367  }
368 }
369 
371 {
372  const int sourceX = TTKStaticCast(int, x);
373  const int sourceY = TTKStaticCast(int, y);
374  if((sourceX + m_sourceRadius) >= m_width || (sourceY + m_sourceRadius) >= m_height || (sourceX - m_sourceRadius) <= 0 || (sourceY - m_sourceRadius) <= 0)
375  {
376  return;
377  }
378 
379  const int distance = (sourceY - m_sourceRadius) * m_width + sourceX - m_sourceRadius;
380  const int size = ((m_sourceRadius << 1) + 1) * ((m_sourceRadius << 1) + 1);
381  for(int i = 0; i < size; ++i)
382  {
383  m_buffer1[distance + m_sourcePosition[i]] = TTKStaticCast(short, m_sourcePower[i]);
384  }
385 }
386 
388 {
389  const int length = m_width * (m_height - 1);
390  for(int i = m_width; i < length; ++i)
391  {
392  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];
393  m_buffer2[i] -= m_buffer2[i] >> m_powerRate;
394  }
395 
396  short* temp = m_buffer1;
398  m_buffer2 = temp;
399 }
400 
402 {
403  int offset;
404  int w = m_width;
405  for(int y = 1; y < m_height - 1; ++y)
406  {
407  for(int x = 0; x < m_width; ++x, ++w)
408  {
409  offset = (m_width * (m_buffer1[w - m_width] - m_buffer1[w + m_width])) + (m_buffer1[w - 1] - m_buffer1[w + 1]);
410  if(w + offset > 0 && w + offset < m_width * m_height)
411  {
412  m_newPixels[w] = m_orginPixels[w + offset];
413  }
414  else
415  {
416  m_newPixels[w] = m_orginPixels[w];
417  }
418  }
419  }
420 }
421 
422 
423 WaterWave::WaterWave(const QImage &image, int radius)
425 {
426  TTK_D(WaterWave);
427  d->initialize(image, radius);
428 }
429 
430 void WaterWave::input(const QRect &region)
431 {
432  ImageRender::input(region);
433 
434  TTK_D(WaterWave);
435  d->setWaveSourcePosition(region.width() / 2, region.height() / 2);
436 }
437 
438 QPixmap WaterWave::render(const QPixmap &pixmap, int value)
439 {
440  TTK_D(WaterWave);
441  d->render();
442 
443  QImage image = pixmap.toImage();
444  memcpy(image.bits(), (const uchar*)d->data(), QtImageBytes(image));
445 
446  QPixmap pix(d->m_rectangle.size());
447  pix.fill(Qt::transparent);
448 
449  QPainter painter(&pix);
450  painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
451  painter.fillRect(d->m_rectangle, QColor(0xFF, 0xFF, 0xFF, qMin(2.55 * 2 * value, 255.0)));
452  painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
453  painter.drawPixmap(d->m_rectangle, QPixmap::fromImage(image));
454  return pix;
455 }
456 }
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:231
#define QtImageBytes(p)
Image byte count.
Definition: ttkqtcompat.h:38
The class of the water wave.
Definition: imagewrapper.h:111
#define TTK_INIT_PRIVATE_OBJECT(PVT)
Definition: ttkprivate.h:37
The class of the image render.
Definition: imagewrapper.h:35
WaterWave(const QImage &image, int radius)
The class of the water wave private.
voidpf void uLong size
Definition: ioapi.h:136
TTK_MODULE_EXPORT void initRandom()
Definition: ttktime.cpp:7
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
virtual QPixmap render(const QPixmap &pixmap, int value) overridefinal
The namespace of the algorithm.
void setWaveSourcePower(int depth)
void initialize(const QImage &image, int radius)
TTK_MODULE_EXPORT int random(int value=RAND_MAX)
Definition: ttktime.cpp:14
voidpf uLong offset
Definition: ioapi.h:142
QList< int > TTKIntList
Definition: ttkqtglobal.h:200
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