• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mcallegari / qlcplus / 11388022654

17 Oct 2024 03:21PM UTC coverage: 31.573% (-0.4%) from 31.983%
11388022654

Pull #1422

github

web-flow
Merge 4147c937e into 5f77fc96f
Pull Request #1422: RgbScript make stage colors available to scripts

56 of 908 new or added lines in 11 files covered. (6.17%)

12 existing lines in 8 files now uncovered.

14057 of 44522 relevant lines covered (31.57%)

26666.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.07
/engine/src/rgbimage.cpp
1
/*
2
  Q Light Controller Plus
3
  rgbimage.cpp
4

5
  Copyright (c) Heikki Junnila
6
  Copyright (c) Jano Svitok
7
  Copyright (c) Massimo Callegari
8

9
  Licensed under the Apache License, Version 2.0 (the "License");
10
  you may not use this file except in compliance with the License.
11
  You may obtain a copy of the License at
12

13
      http://www.apache.org/licenses/LICENSE-2.0.txt
14

15
  Unless required by applicable law or agreed to in writing, software
16
  distributed under the License is distributed on an "AS IS" BASIS,
17
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
  See the License for the specific language governing permissions and
19
  limitations under the License.
20
*/
21

22
#include <QXmlStreamReader>
23
#include <QXmlStreamWriter>
24
#include <QPainter>
25
#include <QDebug>
26

27
#include "rgbimage.h"
28
#include "qlcmacros.h"
29
#include "doc.h"
30

31
#define KXMLQLCRGBImageFilename       QString("Filename")
32
#define KXMLQLCRGBImageAnimationStyle QString("Animation")
33
#define KXMLQLCRGBImageOffset         QString("Offset")
34
#define KXMLQLCRGBImageOffsetX        QString("X")
35
#define KXMLQLCRGBImageOffsetY        QString("Y")
36

37
RGBImage::RGBImage(Doc * doc)
7✔
38
    : RGBAlgorithm(doc)
39
    , m_filename("")
40
    , m_animatedSource(false)
41
    , m_animationStyle(Static)
42
    , m_xOffset(0)
43
    , m_yOffset(0)
7✔
44
{
45
}
7✔
46

47
RGBImage::RGBImage(const RGBImage& i)
×
48
    : RGBAlgorithm(i.doc())
49
    , m_filename(i.filename())
50
    , m_animatedSource(i.animatedSource())
×
51
    , m_animationStyle(i.animationStyle())
×
52
    , m_xOffset(i.xOffset())
×
53
    , m_yOffset(i.yOffset())
×
54
{
55
    reloadImage();
×
56
}
×
57

58
RGBImage::~RGBImage()
7✔
59
{
60
}
7✔
61

62
RGBAlgorithm* RGBImage::clone() const
×
63
{
64
    RGBImage* image = new RGBImage(*this);
×
65
    return static_cast<RGBAlgorithm*> (image);
×
66
}
67

68
/****************************************************************************
69
 * Image file
70
 ****************************************************************************/
71

72
void RGBImage::setFilename(const QString& filename)
×
73
{
74
    m_filename = filename;
×
75
    reloadImage();
×
76
}
×
77

78
QString RGBImage::filename() const
×
79
{
80
    return m_filename;
×
81
}
82

83
void RGBImage::setImageData(int width, int height, const QByteArray &pixelData)
×
84
{
85
    QMutexLocker locker(&m_mutex);
×
86

87
    qDebug() << "[RGBImage] setting image data:" << width << height << pixelData.length();
88
    QImage newImg(width, height, QImage::Format_RGB888);
×
89
    newImg.fill(Qt::black);
×
90

91
    int i = 0;
92
    for (int y = 0; y < height; y++)
×
93
    {
94
        for (int x = 0; x < width; x++)
×
95
        {
96
            if (i + 3 > pixelData.length())
×
97
                break;
98
            QRgb pixel = qRgb((uchar)pixelData.at(i), (uchar)pixelData.at(i + 1), (uchar)pixelData.at(i + 2));
×
99
            newImg.setPixel(x, y, pixel);
×
100
            i+=3;
×
101
        }
102
    }
103
    m_image = newImg;
×
104
}
×
105

106
bool RGBImage::animatedSource() const
×
107
{
108
    return m_animatedSource;
×
109
}
110

111
void RGBImage::reloadImage()
×
112
{
113
    m_animatedSource = false;
×
114

115
    if (m_filename.isEmpty())
×
116
    {
117
        qDebug() << "[RGBImage] Empty image!";
118
        return;
119
    }
120

121
    QMutexLocker locker(&m_mutex);
×
122

123
    if (m_filename.endsWith(".gif"))
×
124
    {
125
        m_animatedPlayer.setFileName(m_filename);
×
126
        if (m_animatedPlayer.frameCount() > 1)
×
127
            m_animatedSource = true;
×
128
    }
129

130
    if (m_animatedSource == false)
×
131
    {
132
        if (!m_image.load(m_filename))
×
133
        {
134
            qDebug() << "[RGBImage] Failed to load" << m_filename;
135
            return;
136
        }
137
    }
138
}
139

140
/****************************************************************************
141
 * Animation
142
 ****************************************************************************/
143

144
void RGBImage::setAnimationStyle(RGBImage::AnimationStyle ani)
×
145
{
146
    if (ani >= Static && ani <= Animation)
×
147
        m_animationStyle = ani;
×
148
    else
149
        m_animationStyle = Static;
×
150
}
×
151

152
RGBImage::AnimationStyle RGBImage::animationStyle() const
×
153
{
154
    return m_animationStyle;
×
155
}
156

157
QString RGBImage::animationStyleToString(RGBImage::AnimationStyle ani)
×
158
{
159
    switch (ani)
×
160
    {
161
        default:
×
162
        case Static:
163
            return QString("Static");
×
164
        case Horizontal:
×
165
            return QString("Horizontal");
×
166
        case Vertical:
×
167
            return QString("Vertical");
×
168
        case Animation:
×
169
            return QString("Animation");
×
170
    }
171
}
172

173
RGBImage::AnimationStyle RGBImage::stringToAnimationStyle(const QString& str)
×
174
{
175
    if (str == QString("Horizontal"))
×
176
        return Horizontal;
177
    else if (str == QString("Vertical"))
×
178
        return Vertical;
179
    else if (str == QString("Animation"))
×
180
        return Animation;
181
    else
182
        return Static;
×
183
}
184

185
QStringList RGBImage::animationStyles()
×
186
{
187
    QStringList list;
188
    list << animationStyleToString(Static);
×
189
    list << animationStyleToString(Horizontal);
×
190
    list << animationStyleToString(Vertical);
×
191
    list << animationStyleToString(Animation);
×
192
    return list;
×
193
}
194

195
void RGBImage::setXOffset(int offset)
×
196
{
197
    m_xOffset = offset;
×
198
}
×
199

200
int RGBImage::xOffset() const
×
201
{
202
    return m_xOffset;
×
203
}
204

205
void RGBImage::setYOffset(int offset)
×
206
{
207
    m_yOffset = offset;
×
208
}
×
209

210
int RGBImage::yOffset() const
×
211
{
212
    return m_yOffset;
×
213
}
214

215
/****************************************************************************
216
 * RGBAlgorithm
217
 ****************************************************************************/
218

219
int RGBImage::rgbMapStepCount(const QSize& size)
×
220
{
221
    QMutexLocker locker(&m_mutex);
×
222

223
    switch (animationStyle())
×
224
    {
225
        default:
226
        case Static:
227
            return 1;
228
        case Horizontal:
×
229
            return m_image.width();
×
230
        case Vertical:
×
231
            return m_image.height();
×
232
        case Animation:
×
233
            qDebug() << m_image.width() << " " << size.width() << " " << (m_image.width() / size.width());
234
            return MAX(1, m_image.width() / size.width());
×
235
    }
236
}
237

NEW
238
void RGBImage::rgbMapSetColors(QVector<uint> &colors)
×
239
{
240
    Q_UNUSED(colors);
NEW
241
}
×
242

UNCOV
243
void RGBImage::rgbMap(const QSize& size, uint rgb, int step, RGBMap &map)
×
244
{
245
    Q_UNUSED(rgb);
246

247
    QMutexLocker locker(&m_mutex);
×
248

249
    if (m_animatedSource == false && (m_image.width() == 0 || m_image.height() == 0))
×
250
        return;
251

252
    int xOffs = xOffset();
×
253
    int yOffs = yOffset();
×
254

255
    switch(animationStyle())
×
256
    {
257
        default:
258
        case Static:
259
        break;
260
        case Horizontal:
×
261
            xOffs += step;
×
262
        break;
×
263
        case Vertical:
×
264
            yOffs += step;
×
265
        break;
×
266
        case Animation:
×
267
            xOffs += step * size.width();
×
268
        break;
×
269
    }
270

271
    if (m_animatedSource)
×
272
    {
273
        m_animatedPlayer.jumpToNextFrame();
×
274
        m_image = m_animatedPlayer.currentImage().scaled(size);
×
275
    }
276

277
    map.resize(size.height());
×
278
    for (int y = 0; y < size.height(); y++)
×
279
    {
280
        map[y].resize(size.width());
×
281
        for (int x = 0; x < size.width(); x++)
×
282
        {
283
            int x1 = (x + xOffs) % m_image.width();
×
284
            int y1 = (y + yOffs) % m_image.height();
×
285

286
            map[y][x] = m_image.pixel(x1,y1);
×
287
            if (qAlpha(map[y][x]) == 0)
×
288
                map[y][x] = 0;
×
289
        }
290
    }
291
}
292

293
QString RGBImage::name() const
6✔
294
{
295
    return QString("Image");
6✔
296
}
297

298
QString RGBImage::author() const
×
299
{
300
    return QString("Jano Svitok");
×
301
}
302

303
int RGBImage::apiVersion() const
×
304
{
305
    return 1;
×
306
}
307

308
RGBAlgorithm::Type RGBImage::type() const
×
309
{
310
    return RGBAlgorithm::Image;
×
311
}
312

313
int RGBImage::acceptColors() const
×
314
{
315
    return 0;
×
316
}
317

318
bool RGBImage::loadXML(QXmlStreamReader &root)
×
319
{
320
    if (root.name() != KXMLQLCRGBAlgorithm)
×
321
    {
322
        qWarning() << Q_FUNC_INFO << "RGB Algorithm node not found";
×
323
        return false;
×
324
    }
325

326
    if (root.attributes().value(KXMLQLCRGBAlgorithmType).toString() != KXMLQLCRGBImage)
×
327
    {
328
        qWarning() << Q_FUNC_INFO << "RGB Algorithm is not Image";
×
329
        return false;
×
330
    }
331

332
    while (root.readNextStartElement())
×
333
    {
334
        if (root.name() == KXMLQLCRGBImageFilename)
×
335
        {
336
            setFilename(doc()->denormalizeComponentPath(root.readElementText()));
×
337
        }
338
        else if (root.name() == KXMLQLCRGBImageAnimationStyle)
×
339
        {
340
            setAnimationStyle(stringToAnimationStyle(root.readElementText()));
×
341
        }
342
        else if (root.name() == KXMLQLCRGBImageOffset)
×
343
        {
344
            QString str;
×
345
            int value;
346
            bool ok;
347
            QXmlStreamAttributes attrs = root.attributes();
×
348

349
            str = attrs.value(KXMLQLCRGBImageOffsetX).toString();
×
350
            ok = false;
×
351
            value = str.toInt(&ok);
×
352
            if (ok == true)
×
353
                setXOffset(value);
×
354
            else
355
                qWarning() << Q_FUNC_INFO << "Invalid X offset:" << str;
×
356

357
            str = attrs.value(KXMLQLCRGBImageOffsetY).toString();
×
358
            ok = false;
×
359
            value = str.toInt(&ok);
×
360
            if (ok == true)
×
361
                setYOffset(value);
×
362
            else
363
                qWarning() << Q_FUNC_INFO << "Invalid Y offset:" << str;
×
364
            root.skipCurrentElement();
×
365
        }
366
        else
367
        {
368
            qWarning() << Q_FUNC_INFO << "Unknown RGBImage tag:" << root.name();
×
369
            root.skipCurrentElement();
×
370
        }
371
    }
372

373
    return true;
374
}
375

376
bool RGBImage::saveXML(QXmlStreamWriter *doc) const
×
377
{
378
    Q_ASSERT(doc != NULL);
379

380
    doc->writeStartElement(KXMLQLCRGBAlgorithm);
×
381
    doc->writeAttribute(KXMLQLCRGBAlgorithmType, KXMLQLCRGBImage);
×
382

383
    doc->writeTextElement(KXMLQLCRGBImageFilename, this->doc()->normalizeComponentPath(m_filename));
×
384

385
    doc->writeTextElement(KXMLQLCRGBImageAnimationStyle, animationStyleToString(animationStyle()));
×
386

387
    doc->writeStartElement(KXMLQLCRGBImageOffset);
×
388
    doc->writeAttribute(KXMLQLCRGBImageOffsetX, QString::number(xOffset()));
×
389
    doc->writeAttribute(KXMLQLCRGBImageOffsetY, QString::number(yOffset()));
×
390
    doc->writeEndElement();
×
391

392
    /* End the <Algorithm> tag */
393
    doc->writeEndElement();
×
394

395
    return true;
×
396
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc