Commit 30c6bf74 authored by Simon Eugster's avatar Simon Eugster

Levels added.

svn path=/trunk/kdenlive/; revision=4623
parent 902d140c
......@@ -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
)
......
......@@ -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)
......
......@@ -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. */
......
/***************************************************************************
* 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;
}
/***************************************************************************
* 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
/***************************************************************************
* 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();
}
/***************************************************************************
* 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
......@@ -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);
......
......@@ -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;
......
<?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>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment