]> git.sesse.net Git - kdenlive/blob - src/colorcorrection/waveformgenerator.cpp
RGB Parade changes:
[kdenlive] / src / colorcorrection / waveformgenerator.cpp
1 /***************************************************************************
2  *   Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com)      *
3  *   This file is part of kdenlive. See www.kdenlive.org.                  *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10
11 #include <QColor>
12 #include <QImage>
13 #include <QPainter>
14 #include <QSize>
15 #include <QTime>
16
17 #include "waveformgenerator.h"
18
19 #define CHOP255(a) ((255) < (a) ? (255) : (a))
20
21 WaveformGenerator::WaveformGenerator()
22 {
23 }
24
25 WaveformGenerator::~WaveformGenerator()
26 {
27 }
28
29 QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QImage &image, WaveformGenerator::PaintMode paintMode,
30                                             const bool &drawAxis, WaveformGenerator::Rec rec, const uint &accelFactor)
31 {
32     Q_ASSERT(accelFactor >= 1);
33
34     QTime time;
35     time.start();
36
37     QImage wave(waveformSize, QImage::Format_ARGB32);
38
39     if (waveformSize.width() <= 0 || waveformSize.height() <= 0 || image.width() <= 0 || image.height() <= 0) {
40         return QImage();
41
42     } else {
43
44         // Fill with transparent color
45         wave.fill(qRgba(0,0,0,0));
46
47         QRgb *col;
48         QRgb waveCol;
49         QPoint wavePoint;
50
51         double dY, dx, dy;
52
53         const uint ww = waveformSize.width();
54         const uint wh = waveformSize.height();
55         const uint iw = image.bytesPerLine();
56         const uint ih = image.height();
57         const uint byteCount = iw*ih;
58
59         // Subtract 1 from sizes because we start counting from 0.
60         // Not doing it would result in attempts to paint outside of the image.
61         const float hPrediv = (float)(wh-1)/255;
62         const float wPrediv = (float)(ww-1)/(iw-1);
63
64         const float brightnessAdjustment = accelFactor * ((float) ww*wh/(byteCount>>3));
65
66         const uchar *bits = image.bits();
67         const uint stepsize = 4*accelFactor;
68
69         for (uint i = 0, x = 0; i < byteCount; i += stepsize) {
70
71             col = (QRgb *)bits;
72
73             if (rec == WaveformGenerator::Rec_601) {
74                 // CIE 601 Luminance
75                 dY = .299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col);
76             } else {
77                 // CIE 709 Luminance
78                 dY = .2125*qRed(*col) + .7154*qGreen(*col) + .0721*qBlue(*col);
79             }
80             // dY is on [0,255] now.
81
82             dy = dY*hPrediv;
83             dx = x*wPrediv;
84             wavePoint = QPoint((int)dx, (int)(wh-1 - dy));
85
86             waveCol = QRgb(wave.pixel(wavePoint));
87             switch (paintMode) {
88             case PaintMode_Green:
89                 wave.setPixel(wavePoint, qRgba(CHOP255(9 + qRed(waveCol)), CHOP255(36 + qGreen(waveCol)),
90                                                CHOP255(18 + qBlue(waveCol)), 255));
91                 break;
92             case PaintMode_Yellow:
93                 wave.setPixel(wavePoint, qRgba(255, 242,
94                                                0, CHOP255(brightnessAdjustment*10+qAlpha(waveCol))));
95                 break;
96             default:
97                 wave.setPixel(wavePoint, qRgba(255,255,255,
98                                                CHOP255(brightnessAdjustment*32+qAlpha(waveCol))));
99                 break;
100             }
101
102             bits += stepsize;
103             x += stepsize;
104             x %= iw; // Modulo image width, to represent the current x position in the image
105         }
106
107         if (drawAxis) {
108             QPainter davinci(&wave);
109             QRgb opx;
110             davinci.setPen(qRgba(150,255,200,32));
111             davinci.setCompositionMode(QPainter::CompositionMode_Overlay);
112             for (uint i = 0; i <= 10; i++) {
113                 dy = (float)i/10 * (wh-1);
114                 for (uint x = 0; x < ww; x++) {
115                     opx = wave.pixel(x, dy);
116                     wave.setPixel(x,dy, qRgba(CHOP255(150+qRed(opx)), 255,
117                                               CHOP255(200+qBlue(opx)), CHOP255(32+qAlpha(opx))));
118                 }
119             }
120         }
121
122     }
123
124     uint diff = time.elapsed();
125     emit signalCalculationFinished(wave, diff);
126
127     return wave;
128 }
129 #undef CHOP255