]> git.sesse.net Git - kdenlive/commitdiff
Levels added.
authorSimon A. Eugster <simon.eu@gmail.com>
Thu, 22 Jul 2010 18:48:11 +0000 (18:48 +0000)
committerSimon A. Eugster <simon.eu@gmail.com>
Thu, 22 Jul 2010 18:48:11 +0000 (18:48 +0000)
svn path=/trunk/kdenlive/; revision=4623

src/CMakeLists.txt
src/abstractscopewidget.cpp
src/abstractscopewidget.h
src/colorcorrection/levelsgenerator.cpp [new file with mode: 0644]
src/colorcorrection/levelsgenerator.h [new file with mode: 0644]
src/levels.cpp [new file with mode: 0644]
src/levels.h [new file with mode: 0644]
src/mainwindow.cpp
src/mainwindow.h
src/widgets/levels_ui.ui [new file with mode: 0644]

index 40732b5bd7a6f9c4b5cfb52df8c550e632b440f4..84177849247d540b5be9ed967320838b425b6245 100644 (file)
@@ -94,6 +94,7 @@ kde4_add_ui_files(kdenlive_UI
   widgets/colorplaneexport_ui.ui
   widgets/waveform_ui.ui
   widgets/rgbparade_ui.ui
+  widgets/levels_ui.ui
 )
 
 set(kdenlive_SRCS
@@ -196,15 +197,17 @@ set(kdenlive_SRCS
   tracksconfigdialog.cpp
   configtrackscommand.cpp
   abstractscopewidget.cpp
+  rebuildgroupcommand.cpp
+  levels.cpp
+  rgbparade.cpp
   vectorscope.cpp
+  waveform.cpp
   colorplaneexport.cpp
   colortools.cpp
-  rebuildgroupcommand.cpp
-  waveform.cpp
-  rgbparade.cpp
-  colorcorrection/waveformgenerator.cpp
-  colorcorrection/vectorscopegenerator.cpp
+  colorcorrection/levelsgenerator.cpp
   colorcorrection/rgbparadegenerator.cpp
+  colorcorrection/vectorscopegenerator.cpp
+  colorcorrection/waveformgenerator.cpp
   razorgroupcommand.cpp
 )
 
index 1d419116426f6d1c04f2e92d13545a98946614a4..998cc725a1b25d08c91af0b1dd3e53893692eb23 100644 (file)
@@ -216,10 +216,12 @@ void AbstractScopeWidget::paintEvent(QPaintEvent *)
         initialDimensionUpdateDone = true;
     }
 
+    qDebug() << "Drawing top/left at " << m_scopeRect.topLeft().x() << "/" << m_scopeRect.topLeft().y();
+
     QPainter davinci(this);
-    davinci.drawImage(scopeRect().topLeft(), m_imgBackground);
-    davinci.drawImage(scopeRect().topLeft(), m_imgScope);
-    davinci.drawImage(scopeRect().topLeft(), m_imgHUD);
+    davinci.drawImage(m_scopeRect.topLeft(), m_imgBackground);
+    davinci.drawImage(m_scopeRect.topLeft(), m_imgScope);
+    davinci.drawImage(m_scopeRect.topLeft(), m_imgHUD);
 }
 
 void AbstractScopeWidget::customContextMenuRequested(const QPoint &pos)
index 65cde13823d270127b8743d61ceb5a0c885a1a9a..fba34962e028eaacd27d8c53f46634107cd8697d 100644 (file)
@@ -97,7 +97,9 @@ protected:
     /** Offset from the widget's borders */
     const uchar offset;
 
-    /** The rect on the widget we're painting in. */
+    /** The rect on the widget we're painting in.
+        Can be used by the implementing widget, e.g. in the render methods.
+        Is updated when necessary (size changes). */
     QRect m_scopeRect;
 
     /** Images storing the calculated layers. Will be used on repaint events. */
diff --git a/src/colorcorrection/levelsgenerator.cpp b/src/colorcorrection/levelsgenerator.cpp
new file mode 100644 (file)
index 0000000..7a216aa
--- /dev/null
@@ -0,0 +1,172 @@
+/***************************************************************************
+ *   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 <algorithm>
+#include <math.h>
+#include <QDebug>
+#include <QImage>
+#include <QPainter>
+#include "levelsgenerator.h"
+
+LevelsGenerator::LevelsGenerator()
+{
+}
+
+QImage LevelsGenerator::calculateLevels(const QSize &paradeSize, const QImage &image, const int &components, const uint &accelFactor) const
+{
+    qDebug() << "Levels rect size is: " << paradeSize.width() << "/" << paradeSize.height();
+    if (paradeSize.height() <= 0 || paradeSize.width() <= 0) {
+        return QImage();
+    }
+
+    bool drawY = (components & LevelsGenerator::ComponentY) != 0;
+    bool drawR = (components & LevelsGenerator::ComponentR) != 0;
+    bool drawG = (components & LevelsGenerator::ComponentG) != 0;
+    bool drawB = (components & LevelsGenerator::ComponentB) != 0;
+
+    int r[256], g[256], b[256], y[256];
+    // Initialize the values to zero
+    std::fill(r, r+255, 0);
+    std::fill(g, g+255, 0);
+    std::fill(b, b+255, 0);
+    std::fill(y, y+255, 0);
+
+    const uint iw = image.bytesPerLine();
+    const uint ih = image.height();
+    const uint ww = paradeSize.width();
+    const uint wh = paradeSize.height();
+    const uint byteCount = iw*ih;
+    const uint stepsize = 4*accelFactor;
+
+    const uchar *bits = image.bits();
+    QRgb *col;
+
+
+    // Read the stats from the input image
+    for (uint i = 0; i < byteCount; i += stepsize) {
+        col = (QRgb *)bits;
+
+        r[qRed(*col)]++;
+        g[qGreen(*col)]++;
+        b[qBlue(*col)]++;
+        y[(int)floor(.299*qRed(*col) + .587*qGreen(*col) + .114*qBlue(*col))]++;
+
+        bits += stepsize;
+    }
+
+
+    const int nParts = (drawY ? 1 : 0) + (drawR ? 1 : 0) + (drawG ? 1 : 0) + (drawB ? 1 : 0);
+    if (nParts == 0) {
+        // Nothing to draw
+        return QImage();
+    }
+
+    const int d = 20; // Distance for text
+    const int partH = (wh-4*d)/nParts;
+    const float scaling = (float)partH/(byteCount >> 7);
+
+    int wy = 0; // Drawing position
+    int partY; // Vertical position for the dots
+
+    QImage levels(paradeSize, QImage::Format_ARGB32);
+    QImage component(256, partH, QImage::Format_ARGB32);
+    QPainter davinci(&levels);
+    levels.fill(qRgba(0, 0, 0, 0));
+
+    if (drawY) {
+        qDebug() << "Drawing Y at " << wy << " with height " << partH;
+        component.fill(qRgba(0, 0, 0, 0));
+
+        for (int x = 0; x < 256; x++) {
+            // Calculate the height of the curve at position x
+            partY = scaling*y[x];
+
+            // Invert the y axis
+            if (partY > partH-1) { partY = partH-1; }
+            partY = partH-1 - partY;
+
+            for (int k = partH-1; k >= partY; k--) {
+                component.setPixel(x, k, qRgba(220, 220, 210, 255));
+            }
+        }
+
+        davinci.drawImage(0, wy, component.scaled(ww, component.height(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+
+        wy += partH + d;
+    }
+
+    if (drawR) {
+        qDebug() << "Drawing R at " << wy << " with height " << partH;
+        component.fill(qRgba(0, 0, 0, 0));
+
+        for (int x = 0; x < 256; x++) {
+            // Calculate the height of the curve at position x
+            partY = scaling*r[x];
+
+            // Invert the y axis
+            if (partY > partH-1) { partY = partH-1; }
+            partY = partH-1 - partY;
+
+            for (int k = partH-1; k >= partY; k--) {
+                component.setPixel(x, k, qRgba(255, 128, 0, 255));
+            }
+        }
+
+        davinci.drawImage(0, wy, component.scaled(ww, component.height(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+
+        wy += partH + d;
+    }
+
+    if (drawG) {
+        qDebug() << "Drawing G at " << wy << " with height " << partH;
+        component.fill(qRgba(0, 0, 0, 0));
+
+        for (int x = 0; x < 256; x++) {
+            // Calculate the height of the curve at position x
+            partY = scaling*g[x];
+
+            // Invert the y axis
+            if (partY > partH-1) { partY = partH-1; }
+            partY = partH-1 - partY;
+
+            for (int k = partH-1; k >= partY; k--) {
+                component.setPixel(x, k, qRgba(128, 255, 0, 255));
+            }
+        }
+
+        davinci.drawImage(0, wy, component.scaled(ww, component.height(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+
+        wy += partH + d;
+    }
+
+    if (drawB) {
+        qDebug() << "Drawing B at " << wy << " with height " << partH;
+        component.fill(qRgba(0, 0, 0, 0));
+
+        for (int x = 0; x < 256; x++) {
+            // Calculate the height of the curve at position x
+            partY = scaling*b[x];
+
+            // Invert the y axis
+            if (partY > partH-1) { partY = partH-1; }
+            partY = partH-1 - partY;
+
+            for (int k = partH-1; k >= partY; k--) {
+                component.setPixel(x, k, qRgba(0, 128, 255, 255));
+            }
+        }
+
+        davinci.drawImage(0, wy, component.scaled(ww, component.height(), Qt::IgnoreAspectRatio, Qt::FastTransformation));
+
+        wy += partH + d;
+    }
+
+    return levels;
+}
diff --git a/src/colorcorrection/levelsgenerator.h b/src/colorcorrection/levelsgenerator.h
new file mode 100644 (file)
index 0000000..3f77c4c
--- /dev/null
@@ -0,0 +1,27 @@
+/***************************************************************************
+ *   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 LEVELSGENERATOR_H
+#define LEVELSGENERATOR_H
+
+#include <QObject>
+
+class QImage;
+class QSize;
+
+class LevelsGenerator : public QObject
+{
+public:
+    LevelsGenerator();
+    QImage calculateLevels(const QSize &paradeSize, const QImage &image, const int &components, const uint &accelFactor = 1) const;
+    enum Components { ComponentY = 1<<0, ComponentR = 1<<1, ComponentG = 1<<2, ComponentB = 1<<3 };
+};
+
+#endif // LEVELSGENERATOR_H
diff --git a/src/levels.cpp b/src/levels.cpp
new file mode 100644 (file)
index 0000000..84ab527
--- /dev/null
@@ -0,0 +1,78 @@
+/***************************************************************************
+ *   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 <QTime>
+#include "levelsgenerator.h"
+#include "levels.h"
+#include "renderer.h"
+
+Levels::Levels(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent) :
+    AbstractScopeWidget(projMonitor, clipMonitor, parent)
+{
+    ui = new Ui::Levels_UI();
+    ui->setupUi(this);
+
+    ui->cbY->setChecked(true);
+    ui->cbR->setChecked(true);
+    ui->cbG->setChecked(true);
+    ui->cbB->setChecked(true);
+
+    bool b = true;
+    b &= connect(ui->cbY, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));
+    b &= connect(ui->cbR, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));
+    b &= connect(ui->cbG, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));
+    b &= connect(ui->cbB, SIGNAL(toggled(bool)), this, SLOT(forceUpdateScope()));
+    Q_ASSERT(b);
+}
+
+Levels::~Levels()
+{
+    delete ui;
+}
+
+QString Levels::widgetName() const { return QString("Levels"); }
+
+bool Levels::isHUDDependingOnInput() const { return false; }
+bool Levels::isScopeDependingOnInput() const { return true; }
+bool Levels::isBackgroundDependingOnInput() const { return false; }
+
+QRect Levels::scopeRect()
+{
+    qDebug() << "According to the spacer, the top left point is " << ui->verticalSpacer->geometry().x() << "/" << ui->verticalSpacer->geometry().y();
+    QPoint topleft(offset, offset+ ui->verticalSpacer->geometry().y());
+    return QRect(topleft, this->rect().size() - QSize(topleft.x() + offset, topleft.y() + offset));
+}
+
+QImage Levels::renderHUD(uint)
+{
+    emit signalHUDRenderingFinished(0, 1);
+    return QImage();
+}
+QImage Levels::renderScope(uint accelFactor)
+{
+    QTime start = QTime::currentTime();
+    start.start();
+
+    const int componentFlags =   (ui->cbY->isChecked() ? 1 : 0) * LevelsGenerator::ComponentY
+                               | (ui->cbR->isChecked() ? 1 : 0) * LevelsGenerator::ComponentR
+                               | (ui->cbG->isChecked() ? 1 : 0) * LevelsGenerator::ComponentG
+                               | (ui->cbB->isChecked() ? 1 : 0) * LevelsGenerator::ComponentB;
+
+    QImage levels = m_levelsGenerator->calculateLevels(m_scopeRect.size(), m_activeRender->extractFrame(m_activeRender->seekFramePosition()),
+                                                       componentFlags, accelFactor);
+
+    emit signalScopeRenderingFinished(0, 1);
+    return levels;
+}
+QImage Levels::renderBackground(uint)
+{
+    emit signalBackgroundRenderingFinished(0, 1);
+    return QImage();
+}
diff --git a/src/levels.h b/src/levels.h
new file mode 100644 (file)
index 0000000..43df14e
--- /dev/null
@@ -0,0 +1,42 @@
+/***************************************************************************
+ *   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 LEVELS_H
+#define LEVELS_H
+
+#include "abstractscopewidget.h"
+#include "ui_levels_ui.h"
+
+class LevelsGenerator;
+
+class Levels : public AbstractScopeWidget {
+    Q_OBJECT
+
+public:
+    Levels(Monitor *projMonitor, Monitor *clipMonitor, QWidget *parent = 0);
+    ~Levels();
+    QString widgetName() const;
+
+
+private:
+    LevelsGenerator *m_levelsGenerator;
+
+    QRect scopeRect();
+    bool isHUDDependingOnInput() const;
+    bool isScopeDependingOnInput() const;
+    bool isBackgroundDependingOnInput() const;
+    QImage renderHUD(uint accelerationFactor);
+    QImage renderScope(uint accelerationFactor);
+    QImage renderBackground(uint accelerationFactor);
+    Ui::Levels_UI *ui;
+
+};
+
+#endif // LEVELS_H
index 836fa7fbd42071dfd0a36443c5d988d9c75a27d7..b59826ed43d1340c81b2feb2a3f682df18f7d9e7 100644 (file)
@@ -55,6 +55,7 @@
 #include "vectorscope.h"
 #include "waveform.h"
 #include "rgbparade.h"
+#include "levels.h"
 
 #include <KApplication>
 #include <KAction>
@@ -233,6 +234,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent
     m_RGBParadeDock->setWidget(m_RGBParade);
     addDockWidget(Qt::TopDockWidgetArea, m_RGBParadeDock);
 
+    m_levels = new Levels(m_projectMonitor, m_clipMonitor, this);
+    m_levelsDock = new QDockWidget("Levels", this);
+    m_levelsDock->setObjectName(m_levels->widgetName());
+    m_levelsDock->setWidget(m_levels);
+    addDockWidget(Qt::TopDockWidgetArea, m_levelsDock);
+
 
     m_undoViewDock = new QDockWidget(i18n("Undo History"), this);
     m_undoViewDock->setObjectName("undo_history");
@@ -264,6 +271,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent
 
     tabifyDockWidget(m_vectorscopeDock, m_waveformDock);
     tabifyDockWidget(m_vectorscopeDock, m_RGBParadeDock);
+    tabifyDockWidget(m_vectorscopeDock, m_levelsDock);
     tabifyDockWidget(m_vectorscopeDock, m_undoViewDock);
     tabifyDockWidget(m_vectorscopeDock, m_effectListDock);
 
index 983d486743e16878a5b25f2a8338bfebf9a53805..ff754134365bc510520fa06315a43aa96dff5742 100644 (file)
@@ -61,6 +61,7 @@ class JogShuttle;
 class DocClipBase;
 class Render;
 class Transition;
+class Levels;
 class Vectorscope;
 class Waveform;
 class RGBParade;
@@ -162,6 +163,9 @@ private:
     QDockWidget *m_RGBParadeDock;
     RGBParade *m_RGBParade;
 
+    QDockWidget *m_levelsDock;
+    Levels *m_levels;
+
     QDockWidget *m_undoViewDock;
     QUndoView *m_undoView;
     QUndoGroup *m_commandStack;
diff --git a/src/widgets/levels_ui.ui b/src/widgets/levels_ui.ui
new file mode 100644 (file)
index 0000000..5bd67cd
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Levels_UI</class>
+ <widget class="QWidget" name="Levels_UI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QCheckBox" name="cbY">
+     <property name="text">
+      <string>Y</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QCheckBox" name="cbR">
+     <property name="text">
+      <string>R</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2">
+    <widget class="QCheckBox" name="cbG">
+     <property name="text">
+      <string>G</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="3">
+    <widget class="QCheckBox" name="cbB">
+     <property name="text">
+      <string>B</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="4">
+    <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>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>