Vectorscope only calculated when visible (\!QWidget::visibleRange.isEmpty()).
svn path=/trunk/kdenlive/; revision=4599
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src/widgets
+ ${CMAKE_SOURCE_DIR}/src/colorcorrection
)
LINK_LIBRARIES(
colortools.cpp
rebuildgroupcommand.cpp
waveform.cpp
+ colorcorrection/waveformgenerator.cpp
)
+
+add_subdirectory( ${CMAKE_SOURCE_DIR}/src/colorcorrection )
+
add_definitions( ${KDE4_DEFINITIONS} )
if(NO_JOGSHUTTLE)
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com) *
+ * This file is part of kdenlive. See www.kdenlive.org. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include <QDebug>
+#include <QTime>
+#include <QColor>
+#include <QPainter>
+
+#include "waveformgenerator.h"
+
+#define CHOP255(a) ((255) < (a) ? (255) : (a))
+
+WaveformGenerator::WaveformGenerator()
+{
+}
+
+WaveformGenerator::~WaveformGenerator()
+{
+}
+
+QImage WaveformGenerator::calculateWaveform(const QSize &waveformSize, const QImage &image, const bool &drawAxis)
+{
+ QTime time;
+ time.start();
+
+ QImage wave(waveformSize, QImage::Format_ARGB32);
+
+ if (waveformSize.width() <= 0 || waveformSize.height() <= 0) {
+ qCritical("Waveform size should not be 0.");
+
+ } else {
+
+ qDebug() << "Waveform calculation started.";
+
+ // Fill with transparent color
+ wave.fill(qRgba(0,0,0,0));
+
+ QRgb *col;
+ QRgb waveCol;
+ QPoint wavePoint;
+
+ double dY, dx, dy;
+
+ const uint ww = waveformSize.width();
+ const uint wh = waveformSize.height();
+ const uint iw = image.bytesPerLine();
+ const uint ih = image.height();
+ const uint byteCount = iw*ih;
+
+ // Subtract 1 from sizes because we start counting from 0.
+ // Not doing it would result in attempts to paint outside of the image.
+ const float hPrediv = (float)(wh-1)/255;
+ const float wPrediv = (float)(ww-1)/(iw-1);
+
+ const uchar *bits = image.bits();
+ const uint stepsize = 4;
+
+ for (uint i = 0, x = 0; i < byteCount; i += stepsize) {
+
+ col = (QRgb *)bits;
+
+ // CIE 601 Luminance
+ // dY is on [0,255] now.
+ dY = .299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col);
+
+ dy = dY*hPrediv;
+ dx = x*wPrediv;
+ wavePoint = QPoint((int)dx, (int)(wh-1 - dy));
+
+ waveCol = QRgb(wave.pixel(wavePoint));
+ wave.setPixel(wavePoint, qRgba(CHOP255(9 + qRed(waveCol)), CHOP255(36 + qGreen(waveCol)),
+ CHOP255(18 + qBlue(waveCol)), 255));
+
+ bits += stepsize;
+ x += stepsize;
+ x %= iw;
+ }
+
+ if (drawAxis) {
+ QPainter davinci(&wave);
+ QRgb opx;
+ davinci.setPen(qRgba(150,255,200,32));
+ davinci.setCompositionMode(QPainter::CompositionMode_Overlay);
+ for (uint i = 0; i <= 10; i++) {
+ dy = (float)i/10 * (wh-1);
+ for (uint x = 0; x < ww; x++) {
+ opx = wave.pixel(x, dy);
+ wave.setPixel(x,dy, qRgba(CHOP255(150+qRed(opx)), 255,
+ CHOP255(200+qBlue(opx)), CHOP255(32+qAlpha(opx))));
+ }
+ //davinci.drawLine(0, dy, ww-1, dy);
+ }
+ }
+
+ }
+
+ uint diff = time.elapsed();
+ qDebug() << "Waveform calculation ended. Time taken: " << diff << " ms. Sending signal now.";
+ emit signalCalculationFinished(wave, diff);
+
+ return wave;
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com) *
+ * This file is part of kdenlive. See www.kdenlive.org. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef WAVEFORMGENERATOR_H
+#define WAVEFORMGENERATOR_H
+
+#include <QObject>
+#include <QImage>
+#include <QSize>
+
+class WaveformGenerator : public QObject
+{
+ Q_OBJECT
+
+public:
+ WaveformGenerator();
+ ~WaveformGenerator();
+
+ QImage calculateWaveform(const QSize &waveformSize, const QImage &image, const bool &drawAxis);
+
+signals:
+ void signalCalculationFinished(QImage image, const uint &ms);
+
+};
+
+#endif // WAVEFORMGENERATOR_H
#include "cliptranscode.h"
#include "ui_templateclip_ui.h"
#include "vectorscope.h"
+#include "waveform.h"
#include <KApplication>
#include <KAction>
m_vectorscopeDock->setWidget(m_vectorscope);
addDockWidget(Qt::TopDockWidgetArea, m_vectorscopeDock);
+ m_waveform = new Waveform(m_projectMonitor, m_clipMonitor, this);
+ m_waveformDock = new QDockWidget(i18n("Waveform"), this);
+ m_waveformDock->setObjectName("waveform");
+ m_waveformDock->setWidget(m_waveform);
+ addDockWidget(Qt::TopDockWidgetArea, m_waveformDock);
+
m_undoViewDock = new QDockWidget(i18n("Undo History"), this);
m_undoViewDock->setObjectName("undo_history");
tabifyDockWidget(m_clipMonitorDock, m_recMonitorDock);
#endif
+ tabifyDockWidget(m_vectorscopeDock, m_waveformDock);
tabifyDockWidget(m_vectorscopeDock, m_undoViewDock);
tabifyDockWidget(m_vectorscopeDock, m_effectListDock);
//connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors()));
connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool)));
connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), m_vectorscope, SLOT(slotActiveMonitorChanged(bool)));
+ connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), m_waveform, SLOT(slotActiveMonitorChanged(bool)));
connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement)));
connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
m_projectListDock->setTitleBarWidget(0);
m_undoViewDock->setTitleBarWidget(0);
m_vectorscopeDock->setTitleBarWidget(0);
+ m_waveformDock->setTitleBarWidget(0);
} else {
if (!m_effectStackDock->isFloating()) { m_effectStackDock->setTitleBarWidget(new QWidget(this)); }
if (!m_clipMonitorDock->isFloating()) { m_clipMonitorDock->setTitleBarWidget(new QWidget(this)); }
if (!m_projectListDock->isFloating()) { m_projectListDock->setTitleBarWidget(new QWidget(this)); }
if (!m_undoViewDock->isFloating()) { m_undoViewDock->setTitleBarWidget(new QWidget(this)); }
if (!m_vectorscopeDock->isFloating()) { m_vectorscopeDock->setTitleBarWidget(new QWidget(this)); }
+ if (!m_waveformDock->isFloating()) { m_waveformDock->setTitleBarWidget(new QWidget(this)); }
}
KdenliveSettings::setShowtitlebars(show);
}
class Render;
class Transition;
class Vectorscope;
+class Waveform;
class KActionCollection;
class MainWindow : public KXmlGuiWindow
QDockWidget *m_vectorscopeDock;
Vectorscope *m_vectorscope;
+ QDockWidget *m_waveformDock;
+ Waveform *m_waveform;
+
QDockWidget *m_undoViewDock;
QUndoView *m_undoView;
QUndoGroup *m_commandStack;
bool Vectorscope::prodCalcThread()
{
bool ok = false;
- if (m_scopeCalcThread.isRunning()) {
+ if (this->visibleRegion().isEmpty()) {
+ qDebug() << "Nothing to see here. Other widget lying on top of Vectorscope. No need to render.";
+ ok = false;
+ } else if (m_scopeCalcThread.isRunning()) {
qDebug() << "Calc thread still running.";
ok = false;
} else {
void Vectorscope::slotRenderZoneUpdated()
{
- qDebug() << "Monitor incoming. New frames total: " << newFrames;
+ qDebug() << "Monitor incoming. New frames total: " << newFrames << ", visible: " << this->isVisible();
+ QRegion region = this->visibleRegion();
+ qDebug() << "Visible region: empty? " << region.isEmpty() << ", size: " << region.boundingRect().width() << "x" << region.boundingRect().height();
// Monitor has shown a new frame
newFrames.fetchAndAddRelaxed(1);
if (cbAutoRefresh->isChecked()) {
prodWheelThread();
QWidget::resizeEvent(event);
}
+
+void Vectorscope::raise()
+{
+ qDebug() << "Raised. Prodding calc thread.";
+ prodCalcThread();
+ QWidget::raise();
+}
void resizeEvent(QResizeEvent *event);
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *event);
+ void raise();
private:
Monitor *m_projMonitor;
+/***************************************************************************
+ * Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com) *
+ * This file is part of kdenlive. See www.kdenlive.org. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include <QPainter>
+#include <QPoint>
+#include <QDebug>
+
#include "waveform.h"
-Waveform::Waveform(QWidget *parent) :
- QWidget(parent)
+
+Waveform::Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
+ QWidget(parent),
+ m_projMonitor(projMonitor),
+ m_clipMonitor(clipMonitor),
+ m_activeRender(clipMonitor->render),
+ initialDimensionUpdateDone(false)
{
setupUi(this);
+ m_waveformGenerator = new WaveformGenerator();
+
+ connect(m_waveformGenerator, SIGNAL(signalCalculationFinished(QImage,uint)), this, SLOT(slotWaveformCalculated(QImage,uint)));
}
Waveform::~Waveform()
{
+ delete m_waveformGenerator;
+}
+
+
+
+void Waveform::updateDimensions()
+{
+ // Distance from top/left/right
+ int offset = 6;
+
+ QPoint topleft(offset, line->y()+offset);
+
+ m_scopeRect = QRect(topleft, this->size() - QSize(offset+topleft.x(), offset+topleft.y()));
+}
+
+
+///// Events /////
+
+void Waveform::paintEvent(QPaintEvent *)
+{
+ if (!initialDimensionUpdateDone) {
+ // This is a workaround.
+ // When updating the dimensions in the constructor, the size
+ // of the control items at the top are simply ignored! So do
+ // it here instead.
+ updateDimensions();
+ initialDimensionUpdateDone = true;
+ }
+
+ QPainter davinci(this);
+ QPoint vinciPoint;
+
+ davinci.setRenderHint(QPainter::Antialiasing, true);
+ davinci.fillRect(0, 0, this->size().width(), this->size().height(), QColor(25,25,23));
+
+ davinci.drawImage(m_scopeRect.topLeft(), m_waveform);
+
+}
+
+void Waveform::resizeEvent(QResizeEvent *event)
+{
+ updateDimensions();
+ m_waveformGenerator->calculateWaveform(m_scopeRect.size(), m_activeRender->extractFrame(m_activeRender->seekFramePosition()), true);
+ QWidget::resizeEvent(event);
+}
+
+void Waveform::mouseReleaseEvent(QMouseEvent *)
+{
+ qDebug() << "Calculating scope now. Size: " << m_scopeRect.size().width() << "x" << m_scopeRect.size().height();
+ m_waveformGenerator->calculateWaveform(m_scopeRect.size(), m_activeRender->extractFrame(m_activeRender->seekFramePosition()), true);
+}
+
+
+///// Slots /////
+
+void Waveform::slotWaveformCalculated(QImage waveform, const uint &msec)
+{
+ qDebug() << "Waveform received. Time taken for rendering: " << msec << " ms. Painting it.";
+ m_waveform = waveform;
+ this->update();
+}
+
+void Waveform::slotActiveMonitorChanged(bool isClipMonitor)
+{
+ if (isClipMonitor) {
+ m_activeRender = m_clipMonitor->render;
+ disconnect(this, SLOT(slotRenderZoneUpdated()));
+ connect(m_activeRender, SIGNAL(rendererPosition(int)), this, SLOT(slotRenderZoneUpdated()));
+ } else {
+ m_activeRender = m_projMonitor->render;
+ disconnect(this, SLOT(slotRenderZoneUpdated()));
+ connect(m_activeRender, SIGNAL(rendererPosition(int)), this, SLOT(slotRenderZoneUpdated()));
+ }
+}
+
+void Waveform::slotRenderZoneUpdated()
+{
+ qDebug() << "Monitor incoming.";//New frames total: " << newFrames;
+ // Monitor has shown a new frame
+// newFrames.fetchAndAddRelaxed(1);
+// if (cbAutoRefresh->isChecked()) {
+// prodCalcThread();
+// }
}
+/***************************************************************************
+ * Copyright (C) 2010 by Simon Andreas Eugster (simon.eu@gmail.com) *
+ * This file is part of kdenlive. See www.kdenlive.org. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
#ifndef WAVEFORM_H
#define WAVEFORM_H
#include <QWidget>
#include "ui_waveform_ui.h"
+#include "renderer.h"
+#include "monitor.h"
+#include "waveformgenerator.h"
class Waveform_UI;
+class WaveformGenerator;
+class Render;
+class Monitor;
class Waveform : public QWidget, public Ui::Waveform_UI {
Q_OBJECT
public:
- Waveform(QWidget *parent = 0);
+ Waveform(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
~Waveform();
+protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+
+private:
+ Monitor *m_projMonitor;
+ Monitor *m_clipMonitor;
+ Render *m_activeRender;
+
+ WaveformGenerator *m_waveformGenerator;
+
+ void updateDimensions();
+ bool initialDimensionUpdateDone;
+
+ QRect m_scopeRect;
+ QImage m_waveform;
+
+private slots:
+ void slotActiveMonitorChanged(bool isClipMonitor);
+ void slotRenderZoneUpdated();
+ void slotWaveformCalculated(QImage waveform, const uint &msec);
+
};
#endif // WAVEFORM_H
<property name="windowTitle">
<string>Form</string>
</property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="horizontalSpacing">
+ <number>5</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="paintMode">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="lblPaintMode">
+ <property name="text">
+ <string>Paint mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
<resources/>
<connections/>