1 /* Webcamoid, webcam capture application.
2 * Copyright (C) 2016 Gonzalo Exequiel Pedone
3 *
4 * Webcamoid is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Webcamoid is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Webcamoid. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Web-Site: http://webcamoid.github.io/
18 */
19
20 #include <QtMath>
21 #include <QPainter>
22 #include <QQmlContext>
23 #include <akfrac.h>
24 #include <akpacket.h>
25 #include <akvideopacket.h>
26
27 #include "dizzyelement.h"
28
29 class DizzyElementPrivate
30 {
31 public:
32 qreal m_speed {5.0};
33 qreal m_zoomRate {0.02};
34 qreal m_strength {0.75};
35 QImage m_prevFrame;
36
37 void setParams(int *dx, int *dy,
38 int *sx, int *sy,
39 int width, int height,
40 qreal phase, qreal zoomRate);
41 };
42
DizzyElement()43 DizzyElement::DizzyElement():
44 AkElement()
45 {
46 this->d = new DizzyElementPrivate;
47 }
48
~DizzyElement()49 DizzyElement::~DizzyElement()
50 {
51 delete this->d;
52 }
53
speed() const54 qreal DizzyElement::speed() const
55 {
56 return this->d->m_speed;
57 }
58
zoomRate() const59 qreal DizzyElement::zoomRate() const
60 {
61 return this->d->m_zoomRate;
62 }
63
strength() const64 qreal DizzyElement::strength() const
65 {
66 return this->d->m_strength;
67 }
68
controlInterfaceProvide(const QString & controlId) const69 QString DizzyElement::controlInterfaceProvide(const QString &controlId) const
70 {
71 Q_UNUSED(controlId)
72
73 return QString("qrc:/Dizzy/share/qml/main.qml");
74 }
75
controlInterfaceConfigure(QQmlContext * context,const QString & controlId) const76 void DizzyElement::controlInterfaceConfigure(QQmlContext *context,
77 const QString &controlId) const
78 {
79 Q_UNUSED(controlId)
80
81 context->setContextProperty("Dizzy", const_cast<QObject *>(qobject_cast<const QObject *>(this)));
82 context->setContextProperty("controlId", this->objectName());
83 }
84
iVideoStream(const AkVideoPacket & packet)85 AkPacket DizzyElement::iVideoStream(const AkVideoPacket &packet)
86 {
87 auto src = packet.toImage();
88
89 if (src.isNull())
90 return AkPacket();
91
92 src = src.convertToFormat(QImage::Format_ARGB32);
93 QImage oFrame(src.size(), src.format());
94 oFrame.fill(0);
95
96 if (this->d->m_prevFrame.isNull()) {
97 this->d->m_prevFrame = QImage(src.size(), src.format());
98 this->d->m_prevFrame.fill(0);
99 }
100
101 qreal pts = 2 * M_PI * packet.pts() * packet.timeBase().value()
102 / this->d->m_speed;
103
104 qreal angle = (2 * M_PI / 180) * sin(pts) + (M_PI / 180) * sin(pts + 2.5);
105 qreal scale = 1.0 + this->d->m_zoomRate;
106
107 QTransform transform;
108 transform.scale(scale, scale);
109 transform.rotateRadians(angle);
110 this->d->m_prevFrame = this->d->m_prevFrame.transformed(transform);
111
112 QRect rect(this->d->m_prevFrame.rect());
113 rect.moveCenter(oFrame.rect().center());
114
115 QPainter painter;
116 painter.begin(&oFrame);
117 painter.drawImage(rect, this->d->m_prevFrame);
118 painter.setOpacity(1.0 - this->d->m_strength);
119 painter.drawImage(0, 0, src);
120 painter.end();
121
122 this->d->m_prevFrame = oFrame;
123
124 auto oPacket = AkVideoPacket::fromImage(oFrame, packet);
125 akSend(oPacket)
126 }
127
setSpeed(qreal speed)128 void DizzyElement::setSpeed(qreal speed)
129 {
130 if (qFuzzyCompare(this->d->m_speed, speed))
131 return;
132
133 this->d->m_speed = speed;
134 emit this->speedChanged(speed);
135 }
136
setZoomRate(qreal zoomRate)137 void DizzyElement::setZoomRate(qreal zoomRate)
138 {
139 if (qFuzzyCompare(this->d->m_zoomRate, zoomRate))
140 return;
141
142 this->d->m_zoomRate = zoomRate;
143 emit this->zoomRateChanged(zoomRate);
144 }
145
setStrength(qreal strength)146 void DizzyElement::setStrength(qreal strength)
147 {
148 if (qFuzzyCompare(this->d->m_strength, strength))
149 return;
150
151 this->d->m_strength = strength;
152 emit this->strengthChanged(strength);
153 }
154
resetSpeed()155 void DizzyElement::resetSpeed()
156 {
157 this->setSpeed(5.0);
158 }
159
resetZoomRate()160 void DizzyElement::resetZoomRate()
161 {
162 this->setZoomRate(0.02);
163 }
164
resetStrength()165 void DizzyElement::resetStrength()
166 {
167 this->setStrength(0.15);
168 }
169
170 #include "moc_dizzyelement.cpp"
171