Merge branch 'master' into stop_motion_improvements
This commit is contained in:
commit
6413c50de2
17 changed files with 4349 additions and 576 deletions
|
@ -1530,6 +1530,9 @@ ProjectPopup QLabel {
|
||||||
#GearButton {
|
#GearButton {
|
||||||
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
||||||
}
|
}
|
||||||
|
#GearButton::menu-indicator {
|
||||||
|
image: "";
|
||||||
|
}
|
||||||
#SubfolderButton {
|
#SubfolderButton {
|
||||||
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
|
|
|
@ -1530,6 +1530,9 @@ ProjectPopup QLabel {
|
||||||
#GearButton {
|
#GearButton {
|
||||||
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
||||||
}
|
}
|
||||||
|
#GearButton::menu-indicator {
|
||||||
|
image: "";
|
||||||
|
}
|
||||||
#SubfolderButton {
|
#SubfolderButton {
|
||||||
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
|
|
|
@ -1530,6 +1530,9 @@ ProjectPopup QLabel {
|
||||||
#GearButton {
|
#GearButton {
|
||||||
qproperty-icon: url('imgs/white/gear.svg');
|
qproperty-icon: url('imgs/white/gear.svg');
|
||||||
}
|
}
|
||||||
|
#GearButton::menu-indicator {
|
||||||
|
image: "";
|
||||||
|
}
|
||||||
#SubfolderButton {
|
#SubfolderButton {
|
||||||
qproperty-icon: url('imgs/white/subfolder.svg');
|
qproperty-icon: url('imgs/white/subfolder.svg');
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
|
|
|
@ -97,6 +97,9 @@ PencilTestPopup {
|
||||||
|
|
||||||
#GearButton {
|
#GearButton {
|
||||||
qproperty-icon: url('@{img-url}/gear.svg');
|
qproperty-icon: url('@{img-url}/gear.svg');
|
||||||
|
&::menu-indicator{
|
||||||
|
image:"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#SubfolderButton {
|
#SubfolderButton {
|
||||||
|
|
|
@ -1531,6 +1531,9 @@ ProjectPopup QLabel {
|
||||||
#GearButton {
|
#GearButton {
|
||||||
qproperty-icon: url('../Default/imgs/black/gear.svg');
|
qproperty-icon: url('../Default/imgs/black/gear.svg');
|
||||||
}
|
}
|
||||||
|
#GearButton::menu-indicator {
|
||||||
|
image: "";
|
||||||
|
}
|
||||||
#SubfolderButton {
|
#SubfolderButton {
|
||||||
qproperty-icon: url('../Default/imgs/black/subfolder.svg');
|
qproperty-icon: url('../Default/imgs/black/subfolder.svg');
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
|
|
|
@ -41,7 +41,7 @@ inline float valueToExposure(float value, float filmGamma) {
|
||||||
inline float exposureToValue(float exposure, float filmGamma) {
|
inline float exposureToValue(float exposure, float filmGamma) {
|
||||||
return log10(exposure) * filmGamma + 0.5;
|
return log10(exposure) * filmGamma + 0.5;
|
||||||
}
|
}
|
||||||
};
|
}; // namespace
|
||||||
|
|
||||||
//--------------------------------------------
|
//--------------------------------------------
|
||||||
// Threads used for FFT computation for each RGB channel
|
// Threads used for FFT computation for each RGB channel
|
||||||
|
@ -51,17 +51,17 @@ MyThread::MyThread(Channel channel, TRasterP layerTileRas, TRasterP outTileRas,
|
||||||
TRasterP tmpAlphaRas, kiss_fft_cpx* kissfft_comp_iris,
|
TRasterP tmpAlphaRas, kiss_fft_cpx* kissfft_comp_iris,
|
||||||
float filmGamma,
|
float filmGamma,
|
||||||
bool doLightenComp) // not used for now
|
bool doLightenComp) // not used for now
|
||||||
: m_channel(channel),
|
: m_channel(channel)
|
||||||
m_layerTileRas(layerTileRas),
|
, m_layerTileRas(layerTileRas)
|
||||||
m_outTileRas(outTileRas),
|
, m_outTileRas(outTileRas)
|
||||||
m_tmpAlphaRas(tmpAlphaRas),
|
, m_tmpAlphaRas(tmpAlphaRas)
|
||||||
m_kissfft_comp_iris(kissfft_comp_iris),
|
, m_kissfft_comp_iris(kissfft_comp_iris)
|
||||||
m_filmGamma(filmGamma),
|
, m_filmGamma(filmGamma)
|
||||||
m_finished(false),
|
, m_finished(false)
|
||||||
m_kissfft_comp_in(0),
|
, m_kissfft_comp_in(0)
|
||||||
m_kissfft_comp_out(0),
|
, m_kissfft_comp_out(0)
|
||||||
m_isTerminated(false),
|
, m_isTerminated(false)
|
||||||
m_doLightenComp(doLightenComp) // not used for now
|
, m_doLightenComp(doLightenComp) // not used for now
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool MyThread::init() {
|
bool MyThread::init() {
|
||||||
|
@ -446,6 +446,11 @@ void Iwa_BokehFx::doCompute(TTile& tile, double frame,
|
||||||
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
||||||
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
||||||
int new_y = kiss_fft_next_fast_size(dimOut.ly);
|
int new_y = kiss_fft_next_fast_size(dimOut.ly);
|
||||||
|
// margin should be integer
|
||||||
|
while ((new_x - dimOut.lx) % 2 != 0)
|
||||||
|
new_x = kiss_fft_next_fast_size(new_x + 1);
|
||||||
|
while ((new_y - dimOut.ly) % 2 != 0)
|
||||||
|
new_y = kiss_fft_next_fast_size(new_y + 1);
|
||||||
|
|
||||||
_rectOut = _rectOut.enlarge(static_cast<double>(new_x - dimOut.lx) / 2.0,
|
_rectOut = _rectOut.enlarge(static_cast<double>(new_x - dimOut.lx) / 2.0,
|
||||||
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
||||||
|
@ -852,22 +857,17 @@ void Iwa_BokehFx::convertIris(const float irisSize,
|
||||||
// Create the raster for resized iris
|
// Create the raster for resized iris
|
||||||
double2 resizedIrisSize = {std::abs(irisSizeResampleRatio) * irisOrgSize.x,
|
double2 resizedIrisSize = {std::abs(irisSizeResampleRatio) * irisOrgSize.x,
|
||||||
std::abs(irisSizeResampleRatio) * irisOrgSize.y};
|
std::abs(irisSizeResampleRatio) * irisOrgSize.y};
|
||||||
int2 filterSize = {tceil(resizedIrisSize.x), tceil(resizedIrisSize.y)};
|
// add 1 pixel margins to all sides
|
||||||
|
int2 filterSize = {int(std::ceil(resizedIrisSize.x)) + 2,
|
||||||
|
int(std::ceil(resizedIrisSize.y)) + 2};
|
||||||
|
|
||||||
TPointD resizeOffset((double)filterSize.x - resizedIrisSize.x,
|
TPointD resizeOffset((double)filterSize.x - resizedIrisSize.x,
|
||||||
(double)filterSize.y - resizedIrisSize.y);
|
(double)filterSize.y - resizedIrisSize.y);
|
||||||
|
|
||||||
// Add some adjustment in order to absorb the difference of the cases when the
|
// Add some adjustment in order to absorb the difference of the cases when the
|
||||||
// iris size is odd and even numbers.
|
// iris size is odd and even numbers.
|
||||||
bool isIrisOffset[2] = {false, false};
|
|
||||||
// Try to set the center of the iris to the center of the screen
|
// Try to set the center of the iris to the center of the screen
|
||||||
if ((dimOut.lx - filterSize.x) % 2 == 1) {
|
if ((dimOut.lx - filterSize.x) % 2 == 1) filterSize.x++;
|
||||||
filterSize.x++;
|
if ((dimOut.ly - filterSize.y) % 2 == 1) filterSize.y++;
|
||||||
isIrisOffset[0] = true;
|
|
||||||
}
|
|
||||||
if ((dimOut.ly - filterSize.y) % 2 == 1) {
|
|
||||||
filterSize.y++;
|
|
||||||
isIrisOffset[1] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate if the filter size becomes bigger than the output size.
|
// Terminate if the filter size becomes bigger than the output size.
|
||||||
if (filterSize.x > dimOut.lx || filterSize.y > dimOut.ly) {
|
if (filterSize.x > dimOut.lx || filterSize.y > dimOut.ly) {
|
||||||
|
@ -882,10 +882,9 @@ void Iwa_BokehFx::convertIris(const float irisSize,
|
||||||
// Add some adjustment in order to absorb the 0.5 translation to be done in
|
// Add some adjustment in order to absorb the 0.5 translation to be done in
|
||||||
// resample()
|
// resample()
|
||||||
TAffine aff;
|
TAffine aff;
|
||||||
TPointD affOffset((isIrisOffset[0]) ? 0.5 : 1.0,
|
TPointD affOffset(0.5, 0.5);
|
||||||
(isIrisOffset[1]) ? 0.5 : 1.0);
|
affOffset += TPointD((dimOut.lx % 2 == 1) ? 0.5 : 0.0,
|
||||||
if (!isIrisOffset[0]) affOffset.x -= resizeOffset.x / 2;
|
(dimOut.ly % 2 == 1) ? 0.5 : 0.0);
|
||||||
if (!isIrisOffset[1]) affOffset.y -= resizeOffset.y / 2;
|
|
||||||
|
|
||||||
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
||||||
aff *= TScale(irisSizeResampleRatio);
|
aff *= TScale(irisSizeResampleRatio);
|
||||||
|
|
|
@ -463,21 +463,15 @@ void Iwa_BokehRefFx::convertIris(const float irisSize, const TRectD& irisBBox,
|
||||||
// create the raster for resizing
|
// create the raster for resizing
|
||||||
TDimensionD resizedIrisSize(std::abs(irisSizeResampleRatio) * irisOrgSize.lx,
|
TDimensionD resizedIrisSize(std::abs(irisSizeResampleRatio) * irisOrgSize.lx,
|
||||||
std::abs(irisSizeResampleRatio) * irisOrgSize.ly);
|
std::abs(irisSizeResampleRatio) * irisOrgSize.ly);
|
||||||
TDimensionI filterSize((int)std::ceil(resizedIrisSize.lx),
|
// add 1 pixel margins to all sides
|
||||||
(int)std::ceil(resizedIrisSize.ly));
|
TDimensionI filterSize((int)std::ceil(resizedIrisSize.lx) + 2,
|
||||||
|
(int)std::ceil(resizedIrisSize.ly) + 2);
|
||||||
TPointD resizeOffset((double)filterSize.lx - resizedIrisSize.lx,
|
TPointD resizeOffset((double)filterSize.lx - resizedIrisSize.lx,
|
||||||
(double)filterSize.ly - resizedIrisSize.ly);
|
(double)filterSize.ly - resizedIrisSize.ly);
|
||||||
|
|
||||||
bool isIrisOffset[2] = {false, false};
|
|
||||||
// iris shape must be exactly at the center of the image
|
// iris shape must be exactly at the center of the image
|
||||||
if ((dimOut.lx - filterSize.lx) % 2 == 1) {
|
if ((dimOut.lx - filterSize.lx) % 2 == 1) filterSize.lx++;
|
||||||
filterSize.lx++;
|
if ((dimOut.ly - filterSize.ly) % 2 == 1) filterSize.ly++;
|
||||||
isIrisOffset[0] = true;
|
|
||||||
}
|
|
||||||
if ((dimOut.ly - filterSize.ly) % 2 == 1) {
|
|
||||||
filterSize.ly++;
|
|
||||||
isIrisOffset[1] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the filter size becomes larger than the output size, return
|
// if the filter size becomes larger than the output size, return
|
||||||
if (filterSize.lx > dimOut.lx || filterSize.ly > dimOut.ly) {
|
if (filterSize.lx > dimOut.lx || filterSize.ly > dimOut.ly) {
|
||||||
|
@ -491,10 +485,9 @@ void Iwa_BokehRefFx::convertIris(const float irisSize, const TRectD& irisBBox,
|
||||||
|
|
||||||
// offset
|
// offset
|
||||||
TAffine aff;
|
TAffine aff;
|
||||||
TPointD affOffset((isIrisOffset[0]) ? 0.5 : 1.0,
|
TPointD affOffset(0.5, 0.5);
|
||||||
(isIrisOffset[1]) ? 0.5 : 1.0);
|
affOffset += TPointD((dimOut.lx % 2 == 1) ? 0.5 : 0.0,
|
||||||
if (!isIrisOffset[0]) affOffset.x -= resizeOffset.x / 2;
|
(dimOut.ly % 2 == 1) ? 0.5 : 0.0);
|
||||||
if (!isIrisOffset[1]) affOffset.y -= resizeOffset.y / 2;
|
|
||||||
|
|
||||||
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
||||||
aff *= TScale(irisSizeResampleRatio);
|
aff *= TScale(irisSizeResampleRatio);
|
||||||
|
@ -924,6 +917,11 @@ void Iwa_BokehRefFx::doCompute(TTile& tile, double frame,
|
||||||
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
||||||
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
||||||
int new_y = kiss_fft_next_fast_size(dimOut.ly);
|
int new_y = kiss_fft_next_fast_size(dimOut.ly);
|
||||||
|
// margin should be integer
|
||||||
|
while ((new_x - dimOut.lx) % 2 != 0)
|
||||||
|
new_x = kiss_fft_next_fast_size(new_x + 1);
|
||||||
|
while ((new_y - dimOut.ly) % 2 != 0)
|
||||||
|
new_y = kiss_fft_next_fast_size(new_y + 1);
|
||||||
|
|
||||||
rectOut = rectOut.enlarge(static_cast<double>(new_x - dimOut.lx) / 2.0,
|
rectOut = rectOut.enlarge(static_cast<double>(new_x - dimOut.lx) / 2.0,
|
||||||
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
||||||
|
|
|
@ -13,7 +13,6 @@ set(MOC_HEADERS
|
||||||
boardsettingspopup.h
|
boardsettingspopup.h
|
||||||
brightnessandcontrastpopup.h
|
brightnessandcontrastpopup.h
|
||||||
cachefxcommand.h
|
cachefxcommand.h
|
||||||
cameracapturelevelcontrol.h
|
|
||||||
camerasettingspopup.h
|
camerasettingspopup.h
|
||||||
canvassizepopup.h
|
canvassizepopup.h
|
||||||
castviewer.h
|
castviewer.h
|
||||||
|
@ -69,7 +68,6 @@ set(MOC_HEADERS
|
||||||
outputsettingspopup.h
|
outputsettingspopup.h
|
||||||
overwritepopup.h
|
overwritepopup.h
|
||||||
pane.h
|
pane.h
|
||||||
penciltestpopup.h
|
|
||||||
pltgizmopopup.h
|
pltgizmopopup.h
|
||||||
preferencespopup.h
|
preferencespopup.h
|
||||||
previewer.h
|
previewer.h
|
||||||
|
@ -124,6 +122,14 @@ set(MOC_HEADERS
|
||||||
xdtsimportpopup.h
|
xdtsimportpopup.h
|
||||||
../stopmotion/stopmotion.h
|
../stopmotion/stopmotion.h
|
||||||
../stopmotion/stopmotioncontroller.h
|
../stopmotion/stopmotioncontroller.h
|
||||||
|
cameracapturelevelcontrol.h
|
||||||
|
penciltestpopup.h
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(MOC_HEADERS
|
||||||
|
${MOC_HEADERS}
|
||||||
|
cameracapturelevelcontrol_qt.h
|
||||||
|
penciltestpopup_qt.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
|
@ -334,11 +340,9 @@ set(SOURCES
|
||||||
comboviewerpane.cpp
|
comboviewerpane.cpp
|
||||||
historypane.cpp
|
historypane.cpp
|
||||||
cleanupsettingspane.cpp
|
cleanupsettingspane.cpp
|
||||||
penciltestpopup.cpp
|
|
||||||
audiorecordingpopup.cpp
|
audiorecordingpopup.cpp
|
||||||
locatorpopup.cpp
|
locatorpopup.cpp
|
||||||
styleshortcutswitchablepanel.cpp
|
styleshortcutswitchablepanel.cpp
|
||||||
cameracapturelevelcontrol.cpp
|
|
||||||
reframepopup.cpp
|
reframepopup.cpp
|
||||||
autoinputcellnumberpopup.cpp
|
autoinputcellnumberpopup.cpp
|
||||||
colormodelbehaviorpopup.cpp
|
colormodelbehaviorpopup.cpp
|
||||||
|
@ -354,6 +358,14 @@ set(SOURCES
|
||||||
predict3d.cpp
|
predict3d.cpp
|
||||||
../stopmotion/stopmotion.cpp
|
../stopmotion/stopmotion.cpp
|
||||||
../stopmotion/stopmotioncontroller.cpp
|
../stopmotion/stopmotioncontroller.cpp
|
||||||
|
cameracapturelevelcontrol.cpp
|
||||||
|
penciltestpopup.cpp
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(SOURCES
|
||||||
|
${SOURCES}
|
||||||
|
cameracapturelevelcontrol_qt.cpp
|
||||||
|
penciltestpopup_qt.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_translation(toonz ${HEADERS} ${SOURCES})
|
add_translation(toonz ${HEADERS} ${SOURCES})
|
||||||
|
|
|
@ -5,7 +5,12 @@
|
||||||
#include "menubarcommandids.h"
|
#include "menubarcommandids.h"
|
||||||
#include "cellselection.h"
|
#include "cellselection.h"
|
||||||
#include "columnselection.h"
|
#include "columnselection.h"
|
||||||
#include "penciltestpopup.h" // for FrameNumberLineEdit
|
|
||||||
|
#ifdef WITH_STOPMOTION
|
||||||
|
#include "penciltestpopup.h"
|
||||||
|
#else
|
||||||
|
#include "penciltestpopup_qt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// TnzQt includes
|
// TnzQt includes
|
||||||
#include "toonzqt/intfield.h"
|
#include "toonzqt/intfield.h"
|
||||||
|
@ -31,7 +36,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class AutoInputCellNumberUndo final : public TUndo {
|
class AutoInputCellNumberUndo final : public TUndo {
|
||||||
int m_increment, m_interval, m_step, m_repeat;
|
int m_increment, m_interval, m_step, m_repeat;
|
||||||
int m_from, m_to;
|
int m_from, m_to;
|
||||||
|
@ -64,7 +68,7 @@ public:
|
||||||
|
|
||||||
int rowsCount() { return m_rowsCount; }
|
int rowsCount() { return m_rowsCount; }
|
||||||
};
|
};
|
||||||
};
|
}; // namespace
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// executing this on column selection, set r1 = -1.
|
// executing this on column selection, set r1 = -1.
|
||||||
|
|
|
@ -50,12 +50,12 @@ void drawSliderHandle(QPoint pos, QPainter& p, QColor color, bool selected) {
|
||||||
p.drawConvexPolygon(points, 5);
|
p.drawConvexPolygon(points, 5);
|
||||||
p.resetTransform();
|
p.resetTransform();
|
||||||
}
|
}
|
||||||
};
|
}; // namespace
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
||||||
: QFrame(parent)
|
: QFrame(parent)
|
||||||
, m_histogramCue(false)
|
//, m_histogramCue(false)
|
||||||
, m_currentItem(None)
|
, m_currentItem(None)
|
||||||
, m_black(0)
|
, m_black(0)
|
||||||
, m_white(255)
|
, m_white(255)
|
||||||
|
@ -72,29 +72,27 @@ CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void CameraCaptureLevelHistogram::updateHistogram(QImage& image) {
|
void CameraCaptureLevelHistogram::updateHistogram(cv::Mat& image) {
|
||||||
// obtain histogram only when clicked
|
cv::Mat gray, hist;
|
||||||
if (!m_histogramCue) return;
|
cv::cvtColor(image, gray, cv::COLOR_RGB2GRAY);
|
||||||
|
|
||||||
QVector<int> tmpHisto(256);
|
const int hdims[] = {256}; // size of histogram
|
||||||
tmpHisto.fill(0);
|
const float hranges[] = {0, 256};
|
||||||
for (int y = 0; y < image.height(); y++) {
|
const float* ranges[] = {hranges}; // min and max values for each bin
|
||||||
QRgb* rgb_p = (QRgb*)(image.scanLine(y));
|
double max_val = .0;
|
||||||
for (int x = 0; x < image.width(); x++, rgb_p++) {
|
|
||||||
tmpHisto[qGray(*rgb_p)]++;
|
cv::calcHist(&gray, 1, 0, cv::Mat(), hist, 1, hdims, ranges);
|
||||||
}
|
// obtain the maximum value
|
||||||
}
|
cv::minMaxLoc(hist, 0, &max_val);
|
||||||
// obtain max value and normalize
|
// scaling
|
||||||
int max = 0;
|
hist = hist * (max_val ? HISTOGRAM_HEIGHT / max_val : 0.);
|
||||||
|
|
||||||
|
float* histVal = hist.ptr<float>(0);
|
||||||
for (int c = 0; c < 256; c++) {
|
for (int c = 0; c < 256; c++) {
|
||||||
if (tmpHisto.at(c) > max) max = tmpHisto.at(c);
|
m_histogramData[c] = int(histVal[c]);
|
||||||
}
|
|
||||||
for (int c = 0; c < 256; c++) {
|
|
||||||
m_histogramData[c] = tmpHisto.at(c) * HISTOGRAM_HEIGHT / max;
|
|
||||||
}
|
}
|
||||||
histogramObtained = true;
|
histogramObtained = true;
|
||||||
update();
|
update();
|
||||||
m_histogramCue = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -106,7 +104,7 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
||||||
|
|
||||||
// draw histogram
|
// draw histogram
|
||||||
p.setPen(Qt::black);
|
p.setPen(Qt::black);
|
||||||
p.setBrush((m_currentItem == Histogram) ? Qt::darkGray : QColor(32, 32, 32));
|
p.setBrush(QColor(32, 32, 32));
|
||||||
p.drawRect(histoRect.adjusted(-1, -1, 0, 0));
|
p.drawRect(histoRect.adjusted(-1, -1, 0, 0));
|
||||||
|
|
||||||
if (histogramObtained) {
|
if (histogramObtained) {
|
||||||
|
@ -117,10 +115,6 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
||||||
histoRect.bottomLeft() + QPoint(c, -m_histogramData.at(c)));
|
histoRect.bottomLeft() + QPoint(c, -m_histogramData.at(c)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!histogramObtained || m_currentItem == Histogram) {
|
|
||||||
p.setPen(Qt::white);
|
|
||||||
p.drawText(histoRect, Qt::AlignCenter, tr("Click to Update Histogram"));
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setRenderHint(QPainter::Antialiasing);
|
p.setRenderHint(QPainter::Antialiasing);
|
||||||
// draw slider handles
|
// draw slider handles
|
||||||
|
@ -147,10 +141,6 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
||||||
|
|
||||||
void CameraCaptureLevelHistogram::mousePressEvent(QMouseEvent* event) {
|
void CameraCaptureLevelHistogram::mousePressEvent(QMouseEvent* event) {
|
||||||
if (event->button() != Qt::LeftButton) return;
|
if (event->button() != Qt::LeftButton) return;
|
||||||
if (m_currentItem == Histogram) {
|
|
||||||
m_histogramCue = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_currentItem == None) return;
|
if (m_currentItem == None) return;
|
||||||
QPoint pos = event->pos();
|
QPoint pos = event->pos();
|
||||||
if (m_currentItem == BlackSlider)
|
if (m_currentItem == BlackSlider)
|
||||||
|
@ -168,7 +158,7 @@ void CameraCaptureLevelHistogram::mousePressEvent(QMouseEvent* event) {
|
||||||
void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
||||||
QPoint pos = event->pos();
|
QPoint pos = event->pos();
|
||||||
if (event->buttons() & Qt::LeftButton) {
|
if (event->buttons() & Qt::LeftButton) {
|
||||||
if (m_currentItem == None || m_currentItem == Histogram) return;
|
if (m_currentItem == None) return;
|
||||||
|
|
||||||
int hPos = pos.x() - SIDE_MARGIN - m_offset;
|
int hPos = pos.x() - SIDE_MARGIN - m_offset;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -223,8 +213,7 @@ void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
||||||
setToolTip("");
|
setToolTip("");
|
||||||
QRect histoRect(5, 1, 256, HISTOGRAM_HEIGHT);
|
QRect histoRect(5, 1, 256, HISTOGRAM_HEIGHT);
|
||||||
if (histoRect.contains(pos)) {
|
if (histoRect.contains(pos)) {
|
||||||
setToolTip(tr("Click to Update Histogram"));
|
// do nothing
|
||||||
m_currentItem = Histogram;
|
|
||||||
} else {
|
} else {
|
||||||
// slider handles
|
// slider handles
|
||||||
QPoint sliderBasePos(SIDE_MARGIN, HISTOGRAM_HEIGHT + 2);
|
QPoint sliderBasePos(SIDE_MARGIN, HISTOGRAM_HEIGHT + 2);
|
||||||
|
@ -286,6 +275,7 @@ CameraCaptureLevelControl::CameraCaptureLevelControl(QWidget* parent)
|
||||||
m_whiteFld = new IntLineEdit(this, m_histogram->white(), 2, 255);
|
m_whiteFld = new IntLineEdit(this, m_histogram->white(), 2, 255);
|
||||||
m_thresholdFld = new IntLineEdit(this, m_histogram->threshold(), 0, 255);
|
m_thresholdFld = new IntLineEdit(this, m_histogram->threshold(), 0, 255);
|
||||||
m_gammaFld = new DoubleLineEdit(this, m_histogram->gamma());
|
m_gammaFld = new DoubleLineEdit(this, m_histogram->gamma());
|
||||||
|
m_lut = cv::Mat(1, 256, CV_8U);
|
||||||
|
|
||||||
m_blackFld->setToolTip(tr("Black Point Value"));
|
m_blackFld->setToolTip(tr("Black Point Value"));
|
||||||
m_whiteFld->setToolTip(tr("White Point Value"));
|
m_whiteFld->setToolTip(tr("White Point Value"));
|
||||||
|
@ -330,6 +320,10 @@ CameraCaptureLevelControl::CameraCaptureLevelControl(QWidget* parent)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void CameraCaptureLevelControl::onHistogramValueChanged(int itemId) {
|
void CameraCaptureLevelControl::onHistogramValueChanged(int itemId) {
|
||||||
|
if (itemId == CameraCaptureLevelHistogram::ThresholdSlider) {
|
||||||
|
m_thresholdFld->setValue(m_histogram->threshold());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (itemId == CameraCaptureLevelHistogram::BlackSlider) {
|
if (itemId == CameraCaptureLevelHistogram::BlackSlider) {
|
||||||
m_blackFld->setValue(m_histogram->black());
|
m_blackFld->setValue(m_histogram->black());
|
||||||
m_whiteFld->setRange(m_histogram->black() + 2, 255);
|
m_whiteFld->setRange(m_histogram->black() + 2, 255);
|
||||||
|
@ -338,9 +332,8 @@ void CameraCaptureLevelControl::onHistogramValueChanged(int itemId) {
|
||||||
m_blackFld->setRange(0, m_histogram->white() - 2);
|
m_blackFld->setRange(0, m_histogram->white() - 2);
|
||||||
} else if (itemId == CameraCaptureLevelHistogram::GammaSlider) {
|
} else if (itemId == CameraCaptureLevelHistogram::GammaSlider) {
|
||||||
m_gammaFld->setValue(m_histogram->gamma());
|
m_gammaFld->setValue(m_histogram->gamma());
|
||||||
} else if (itemId == CameraCaptureLevelHistogram::ThresholdSlider) {
|
|
||||||
m_thresholdFld->setValue(m_histogram->threshold());
|
|
||||||
}
|
}
|
||||||
|
computeLut();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -367,3 +360,42 @@ void CameraCaptureLevelControl::setMode(bool color_grayscale) {
|
||||||
m_thresholdFld->setVisible(!color_grayscale);
|
m_thresholdFld->setVisible(!color_grayscale);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::adjustLevel(cv::Mat& image) {
|
||||||
|
int black = m_histogram->black();
|
||||||
|
int white = m_histogram->white();
|
||||||
|
float gamma = m_histogram->gamma();
|
||||||
|
if (black == 0 && white == 255 && gamma == 1.0) return;
|
||||||
|
|
||||||
|
cv::LUT(image, m_lut, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::binarize(cv::Mat& image) {
|
||||||
|
cv::threshold(image, image, m_histogram->threshold(), 255, cv::THRESH_BINARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::computeLut() {
|
||||||
|
int black = m_histogram->black();
|
||||||
|
int white = m_histogram->white();
|
||||||
|
float gamma = m_histogram->gamma();
|
||||||
|
|
||||||
|
const float maxChannelValueF = 255.0f;
|
||||||
|
|
||||||
|
float value;
|
||||||
|
|
||||||
|
uchar* p = m_lut.data;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
if (i <= black)
|
||||||
|
value = 0.0f;
|
||||||
|
else if (i >= white)
|
||||||
|
value = 1.0f;
|
||||||
|
else {
|
||||||
|
value = (float)(i - black) / (float)(white - black);
|
||||||
|
value = std::pow(value, 1.0f / gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
p[i] = (uchar)std::floor(value * maxChannelValueF);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,12 @@
|
||||||
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
|
||||||
namespace DVGui {
|
namespace DVGui {
|
||||||
class IntLineEdit;
|
class IntLineEdit;
|
||||||
class DoubleLineEdit;
|
class DoubleLineEdit;
|
||||||
}
|
} // namespace DVGui
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// CameraCaptureLevelHistogram
|
// CameraCaptureLevelHistogram
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -22,15 +23,12 @@ public:
|
||||||
WhiteSlider,
|
WhiteSlider,
|
||||||
GammaSlider,
|
GammaSlider,
|
||||||
ThresholdSlider,
|
ThresholdSlider,
|
||||||
Histogram,
|
|
||||||
NumItems
|
NumItems
|
||||||
};
|
};
|
||||||
enum LevelControlMode { Color_GrayScale, BlackAndWhite, NumModes };
|
enum LevelControlMode { Color_GrayScale, BlackAndWhite, NumModes };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_histogramCue;
|
|
||||||
QVector<int> m_histogramData;
|
QVector<int> m_histogramData;
|
||||||
|
|
||||||
LevelControlItem m_currentItem;
|
LevelControlItem m_currentItem;
|
||||||
|
|
||||||
int m_black, m_white, m_threshold;
|
int m_black, m_white, m_threshold;
|
||||||
|
@ -42,7 +40,7 @@ private:
|
||||||
public:
|
public:
|
||||||
CameraCaptureLevelHistogram(QWidget* parent = 0);
|
CameraCaptureLevelHistogram(QWidget* parent = 0);
|
||||||
|
|
||||||
void updateHistogram(QImage& image);
|
void updateHistogram(cv::Mat& image);
|
||||||
|
|
||||||
int black() { return m_black; }
|
int black() { return m_black; }
|
||||||
int white() { return m_white; }
|
int white() { return m_white; }
|
||||||
|
@ -78,19 +76,18 @@ class CameraCaptureLevelControl : public QFrame {
|
||||||
CameraCaptureLevelHistogram* m_histogram;
|
CameraCaptureLevelHistogram* m_histogram;
|
||||||
DVGui::IntLineEdit *m_blackFld, *m_whiteFld, *m_thresholdFld;
|
DVGui::IntLineEdit *m_blackFld, *m_whiteFld, *m_thresholdFld;
|
||||||
DVGui::DoubleLineEdit* m_gammaFld;
|
DVGui::DoubleLineEdit* m_gammaFld;
|
||||||
|
cv::Mat m_lut;
|
||||||
|
|
||||||
|
void computeLut();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CameraCaptureLevelControl(QWidget* parent = 0);
|
CameraCaptureLevelControl(QWidget* parent = 0);
|
||||||
|
|
||||||
void updateHistogram(QImage& image) { m_histogram->updateHistogram(image); }
|
void updateHistogram(cv::Mat& image) { m_histogram->updateHistogram(image); }
|
||||||
void setMode(bool color_grayscale);
|
void setMode(bool color_grayscale);
|
||||||
|
|
||||||
void getValues(int& black, int& white, float& gamma) {
|
void adjustLevel(cv::Mat& image);
|
||||||
black = m_histogram->black();
|
void binarize(cv::Mat& image);
|
||||||
white = m_histogram->white();
|
|
||||||
gamma = m_histogram->gamma();
|
|
||||||
}
|
|
||||||
float getThreshold() { return m_histogram->threshold(); }
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onHistogramValueChanged(int itemId);
|
void onHistogramValueChanged(int itemId);
|
||||||
|
|
369
toonz/sources/toonz/cameracapturelevelcontrol_qt.cpp
Normal file
369
toonz/sources/toonz/cameracapturelevelcontrol_qt.cpp
Normal file
|
@ -0,0 +1,369 @@
|
||||||
|
#include "cameracapturelevelcontrol_qt.h"
|
||||||
|
|
||||||
|
#include "toonzqt/intfield.h"
|
||||||
|
#include "toonzqt/doublefield.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace DVGui;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int HISTOGRAM_HEIGHT = 50;
|
||||||
|
const int SIDE_MARGIN = 7;
|
||||||
|
static bool histogramObtained = false;
|
||||||
|
|
||||||
|
// returns the horizontal position of gamma slider (0-255)
|
||||||
|
int gammaToHPos(float gamma, int black, int white) {
|
||||||
|
float ratio = std::pow(0.5f, gamma);
|
||||||
|
return black + (int)std::round((float)(white - black) * ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the gamma value from the slider position
|
||||||
|
float hPosToGamma(int hPos, int black, int white) {
|
||||||
|
if (hPos <= black + 1)
|
||||||
|
return 9.99f;
|
||||||
|
else if (hPos >= white - 1)
|
||||||
|
return 0.01f;
|
||||||
|
|
||||||
|
float ratio = (float)(hPos - black) / (float)(white - black);
|
||||||
|
|
||||||
|
float gamma = std::log(ratio) / std::log(0.5);
|
||||||
|
int decimals = 2;
|
||||||
|
gamma =
|
||||||
|
std::round(gamma * std::pow(10.0, decimals)) / std::pow(10.0, decimals);
|
||||||
|
return gamma;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawSliderHandle(QPoint pos, QPainter& p, QColor color, bool selected) {
|
||||||
|
p.setPen((selected) ? Qt::yellow : Qt::black);
|
||||||
|
p.setBrush(color);
|
||||||
|
|
||||||
|
p.translate(pos);
|
||||||
|
|
||||||
|
static const QPoint points[5] = {QPoint(0, 0), QPoint(-6, 8), QPoint(-3, 12),
|
||||||
|
QPoint(3, 12), QPoint(6, 8)};
|
||||||
|
p.drawConvexPolygon(points, 5);
|
||||||
|
p.resetTransform();
|
||||||
|
}
|
||||||
|
}; // namespace
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
, m_histogramCue(false)
|
||||||
|
, m_currentItem(None)
|
||||||
|
, m_black(0)
|
||||||
|
, m_white(255)
|
||||||
|
, m_gamma(1.0)
|
||||||
|
, m_threshold(128)
|
||||||
|
, m_offset(0)
|
||||||
|
, m_mode(Color_GrayScale)
|
||||||
|
, m_histogramData(256) {
|
||||||
|
setFixedSize(256 + SIDE_MARGIN * 2, HISTOGRAM_HEIGHT + 15);
|
||||||
|
setMouseTracking(true);
|
||||||
|
|
||||||
|
m_histogramData.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::updateHistogram(QImage& image) {
|
||||||
|
// obtain histogram only when clicked
|
||||||
|
if (!m_histogramCue) return;
|
||||||
|
|
||||||
|
QVector<int> tmpHisto(256);
|
||||||
|
tmpHisto.fill(0);
|
||||||
|
for (int y = 0; y < image.height(); y++) {
|
||||||
|
QRgb* rgb_p = (QRgb*)(image.scanLine(y));
|
||||||
|
for (int x = 0; x < image.width(); x++, rgb_p++) {
|
||||||
|
tmpHisto[qGray(*rgb_p)]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// obtain max value and normalize
|
||||||
|
int max = 0;
|
||||||
|
for (int c = 0; c < 256; c++) {
|
||||||
|
if (tmpHisto.at(c) > max) max = tmpHisto.at(c);
|
||||||
|
}
|
||||||
|
for (int c = 0; c < 256; c++) {
|
||||||
|
m_histogramData[c] = tmpHisto.at(c) * HISTOGRAM_HEIGHT / max;
|
||||||
|
}
|
||||||
|
histogramObtained = true;
|
||||||
|
update();
|
||||||
|
m_histogramCue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
||||||
|
QPainter p(this);
|
||||||
|
|
||||||
|
QRect histoRect(SIDE_MARGIN, 1, 256, HISTOGRAM_HEIGHT);
|
||||||
|
|
||||||
|
// draw histogram
|
||||||
|
p.setPen(Qt::black);
|
||||||
|
p.setBrush((m_currentItem == Histogram) ? Qt::darkGray : QColor(32, 32, 32));
|
||||||
|
p.drawRect(histoRect.adjusted(-1, -1, 0, 0));
|
||||||
|
|
||||||
|
if (histogramObtained) {
|
||||||
|
p.setPen(Qt::white);
|
||||||
|
for (int c = 0; c < 256; c++) {
|
||||||
|
if (m_histogramData.at(c) == 0) continue;
|
||||||
|
p.drawLine(histoRect.bottomLeft() + QPoint(c, 0),
|
||||||
|
histoRect.bottomLeft() + QPoint(c, -m_histogramData.at(c)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!histogramObtained || m_currentItem == Histogram) {
|
||||||
|
p.setPen(Qt::white);
|
||||||
|
p.drawText(histoRect, Qt::AlignCenter, tr("Click to Update Histogram"));
|
||||||
|
}
|
||||||
|
|
||||||
|
p.setRenderHint(QPainter::Antialiasing);
|
||||||
|
// draw slider handles
|
||||||
|
QPoint sliderBasePos(SIDE_MARGIN, HISTOGRAM_HEIGHT + 2);
|
||||||
|
if (m_mode == Color_GrayScale) {
|
||||||
|
// black
|
||||||
|
drawSliderHandle(sliderBasePos + QPoint(m_black, 0), p, QColor(32, 32, 32),
|
||||||
|
m_currentItem == BlackSlider);
|
||||||
|
// gamma
|
||||||
|
drawSliderHandle(
|
||||||
|
sliderBasePos + QPoint(gammaToHPos(m_gamma, m_black, m_white), 0), p,
|
||||||
|
Qt::gray, m_currentItem == GammaSlider);
|
||||||
|
// white
|
||||||
|
drawSliderHandle(sliderBasePos + QPoint(m_white, 0), p,
|
||||||
|
QColor(220, 220, 220), m_currentItem == WhiteSlider);
|
||||||
|
} else if (m_mode == BlackAndWhite)
|
||||||
|
// threshold
|
||||||
|
drawSliderHandle(sliderBasePos + QPoint(m_threshold, 0), p, Qt::gray,
|
||||||
|
m_currentItem == ThresholdSlider);
|
||||||
|
p.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::mousePressEvent(QMouseEvent* event) {
|
||||||
|
if (event->button() != Qt::LeftButton) return;
|
||||||
|
if (m_currentItem == Histogram) {
|
||||||
|
m_histogramCue = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_currentItem == None) return;
|
||||||
|
QPoint pos = event->pos();
|
||||||
|
if (m_currentItem == BlackSlider)
|
||||||
|
m_offset = pos.x() - SIDE_MARGIN - m_black;
|
||||||
|
else if (m_currentItem == GammaSlider)
|
||||||
|
m_offset = pos.x() - SIDE_MARGIN - gammaToHPos(m_gamma, m_black, m_white);
|
||||||
|
else if (m_currentItem == BlackSlider)
|
||||||
|
m_offset = pos.x() - SIDE_MARGIN - m_white;
|
||||||
|
else if (m_currentItem == ThresholdSlider)
|
||||||
|
m_offset = pos.x() - SIDE_MARGIN - m_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
||||||
|
QPoint pos = event->pos();
|
||||||
|
if (event->buttons() & Qt::LeftButton) {
|
||||||
|
if (m_currentItem == None || m_currentItem == Histogram) return;
|
||||||
|
|
||||||
|
int hPos = pos.x() - SIDE_MARGIN - m_offset;
|
||||||
|
bool changed = false;
|
||||||
|
if (m_currentItem == BlackSlider) {
|
||||||
|
if (hPos < 0)
|
||||||
|
hPos = 0;
|
||||||
|
else if (hPos > m_white - 2)
|
||||||
|
hPos = m_white - 2;
|
||||||
|
if (hPos != m_black) {
|
||||||
|
m_black = hPos;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if (m_currentItem == GammaSlider) {
|
||||||
|
if (hPos < m_black + 1)
|
||||||
|
hPos = m_black + 1;
|
||||||
|
else if (hPos > m_white - 1)
|
||||||
|
hPos = m_white - 1;
|
||||||
|
float gamma = hPosToGamma(hPos, m_black, m_white);
|
||||||
|
if (gamma != m_gamma) {
|
||||||
|
m_gamma = gamma;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if (m_currentItem == WhiteSlider) {
|
||||||
|
if (hPos < m_black + 2)
|
||||||
|
hPos = m_black + 2;
|
||||||
|
else if (hPos > 255)
|
||||||
|
hPos = 255;
|
||||||
|
if (hPos != m_white) {
|
||||||
|
m_white = hPos;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if (m_currentItem == ThresholdSlider) {
|
||||||
|
if (hPos < 0)
|
||||||
|
hPos = 0;
|
||||||
|
else if (hPos > 255)
|
||||||
|
hPos = 255;
|
||||||
|
if (hPos != m_threshold) {
|
||||||
|
m_threshold = hPos;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
update();
|
||||||
|
emit valueChange(m_currentItem);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on hover
|
||||||
|
LevelControlItem oldItem = m_currentItem;
|
||||||
|
m_currentItem = None;
|
||||||
|
setToolTip("");
|
||||||
|
QRect histoRect(5, 1, 256, HISTOGRAM_HEIGHT);
|
||||||
|
if (histoRect.contains(pos)) {
|
||||||
|
setToolTip(tr("Click to Update Histogram"));
|
||||||
|
m_currentItem = Histogram;
|
||||||
|
} else {
|
||||||
|
// slider handles
|
||||||
|
QPoint sliderBasePos(SIDE_MARGIN, HISTOGRAM_HEIGHT + 2);
|
||||||
|
QRect sliderRect(-6, 0, 12, 12);
|
||||||
|
if (m_mode == Color_GrayScale) {
|
||||||
|
// white
|
||||||
|
if (sliderRect.translated(sliderBasePos + QPoint(m_white, 0))
|
||||||
|
.contains(pos)) {
|
||||||
|
m_currentItem = WhiteSlider;
|
||||||
|
setToolTip(tr("Drag to Move White Point"));
|
||||||
|
}
|
||||||
|
// gamma
|
||||||
|
else if (sliderRect
|
||||||
|
.translated(
|
||||||
|
sliderBasePos +
|
||||||
|
QPoint(gammaToHPos(m_gamma, m_black, m_white), 0))
|
||||||
|
.contains(pos)) {
|
||||||
|
m_currentItem = GammaSlider;
|
||||||
|
setToolTip(tr("Drag to Move Gamma"));
|
||||||
|
}
|
||||||
|
// black
|
||||||
|
else if (sliderRect.translated(sliderBasePos + QPoint(m_black, 0))
|
||||||
|
.contains(pos)) {
|
||||||
|
m_currentItem = BlackSlider;
|
||||||
|
setToolTip(tr("Drag to Move Black Point"));
|
||||||
|
}
|
||||||
|
} else if (m_mode == BlackAndWhite) {
|
||||||
|
// threshold
|
||||||
|
if (sliderRect.translated(sliderBasePos + QPoint(m_threshold, 0))
|
||||||
|
.contains(pos)) {
|
||||||
|
m_currentItem = ThresholdSlider;
|
||||||
|
setToolTip(tr("Drag to Move Threshold Point"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldItem != m_currentItem) update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
m_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelHistogram::leaveEvent(QEvent* event) {
|
||||||
|
m_currentItem = None;
|
||||||
|
m_offset = 0;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
CameraCaptureLevelControl::CameraCaptureLevelControl(QWidget* parent)
|
||||||
|
: QFrame(parent) {
|
||||||
|
m_histogram = new CameraCaptureLevelHistogram(this);
|
||||||
|
m_blackFld = new IntLineEdit(this, m_histogram->black(), 0, 253);
|
||||||
|
m_whiteFld = new IntLineEdit(this, m_histogram->white(), 2, 255);
|
||||||
|
m_thresholdFld = new IntLineEdit(this, m_histogram->threshold(), 0, 255);
|
||||||
|
m_gammaFld = new DoubleLineEdit(this, m_histogram->gamma());
|
||||||
|
|
||||||
|
m_blackFld->setToolTip(tr("Black Point Value"));
|
||||||
|
m_whiteFld->setToolTip(tr("White Point Value"));
|
||||||
|
m_thresholdFld->setToolTip(tr("Threshold Value"));
|
||||||
|
m_thresholdFld->hide();
|
||||||
|
m_gammaFld->setRange(0.01, 9.99);
|
||||||
|
m_gammaFld->setDecimals(2);
|
||||||
|
m_gammaFld->setFixedWidth(54);
|
||||||
|
m_gammaFld->setToolTip(tr("Gamma Value"));
|
||||||
|
|
||||||
|
QVBoxLayout* mainLay = new QVBoxLayout();
|
||||||
|
mainLay->setMargin(0);
|
||||||
|
mainLay->setSpacing(4);
|
||||||
|
{
|
||||||
|
mainLay->addWidget(m_histogram, 0, Qt::AlignHCenter);
|
||||||
|
QHBoxLayout* fieldsLay = new QHBoxLayout();
|
||||||
|
fieldsLay->setMargin(1);
|
||||||
|
fieldsLay->setSpacing(0);
|
||||||
|
{
|
||||||
|
fieldsLay->addWidget(m_blackFld, 0);
|
||||||
|
fieldsLay->addStretch(1);
|
||||||
|
fieldsLay->addWidget(m_gammaFld, 0);
|
||||||
|
fieldsLay->addWidget(m_thresholdFld, 0);
|
||||||
|
fieldsLay->addStretch(1);
|
||||||
|
fieldsLay->addWidget(m_whiteFld, 0);
|
||||||
|
}
|
||||||
|
mainLay->addLayout(fieldsLay, 0);
|
||||||
|
}
|
||||||
|
setLayout(mainLay);
|
||||||
|
|
||||||
|
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
|
|
||||||
|
connect(m_histogram, SIGNAL(valueChange(int)), this,
|
||||||
|
SLOT(onHistogramValueChanged(int)));
|
||||||
|
connect(m_blackFld, SIGNAL(editingFinished()), this, SLOT(onFieldChanged()));
|
||||||
|
connect(m_whiteFld, SIGNAL(editingFinished()), this, SLOT(onFieldChanged()));
|
||||||
|
connect(m_gammaFld, SIGNAL(editingFinished()), this, SLOT(onFieldChanged()));
|
||||||
|
connect(m_thresholdFld, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(onFieldChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::onHistogramValueChanged(int itemId) {
|
||||||
|
if (itemId == CameraCaptureLevelHistogram::BlackSlider) {
|
||||||
|
m_blackFld->setValue(m_histogram->black());
|
||||||
|
m_whiteFld->setRange(m_histogram->black() + 2, 255);
|
||||||
|
} else if (itemId == CameraCaptureLevelHistogram::WhiteSlider) {
|
||||||
|
m_whiteFld->setValue(m_histogram->white());
|
||||||
|
m_blackFld->setRange(0, m_histogram->white() - 2);
|
||||||
|
} else if (itemId == CameraCaptureLevelHistogram::GammaSlider) {
|
||||||
|
m_gammaFld->setValue(m_histogram->gamma());
|
||||||
|
} else if (itemId == CameraCaptureLevelHistogram::ThresholdSlider) {
|
||||||
|
m_thresholdFld->setValue(m_histogram->threshold());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::onFieldChanged() {
|
||||||
|
if (m_histogram->mode() == CameraCaptureLevelHistogram::Color_GrayScale)
|
||||||
|
m_histogram->setValues(m_blackFld->getValue(), m_whiteFld->getValue(),
|
||||||
|
m_gammaFld->getValue());
|
||||||
|
else if (m_histogram->mode() == CameraCaptureLevelHistogram::BlackAndWhite)
|
||||||
|
m_histogram->setThreshold(m_thresholdFld->getValue());
|
||||||
|
|
||||||
|
m_histogram->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CameraCaptureLevelControl::setMode(bool color_grayscale) {
|
||||||
|
m_histogram->setMode((color_grayscale)
|
||||||
|
? CameraCaptureLevelHistogram::Color_GrayScale
|
||||||
|
: CameraCaptureLevelHistogram::BlackAndWhite);
|
||||||
|
m_blackFld->setVisible(color_grayscale);
|
||||||
|
m_whiteFld->setVisible(color_grayscale);
|
||||||
|
m_gammaFld->setVisible(color_grayscale);
|
||||||
|
m_thresholdFld->setVisible(!color_grayscale);
|
||||||
|
update();
|
||||||
|
}
|
100
toonz/sources/toonz/cameracapturelevelcontrol_qt.h
Normal file
100
toonz/sources/toonz/cameracapturelevelcontrol_qt.h
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef CAMERA_CAPTURE_LEVEL_CONTROL_H
|
||||||
|
#define CAMERA_CAPTURE_LEVEL_CONTROL_H
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace DVGui {
|
||||||
|
class IntLineEdit;
|
||||||
|
class DoubleLineEdit;
|
||||||
|
} // namespace DVGui
|
||||||
|
//=============================================================================
|
||||||
|
// CameraCaptureLevelHistogram
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CameraCaptureLevelHistogram : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum LevelControlItem {
|
||||||
|
None = 0,
|
||||||
|
BlackSlider,
|
||||||
|
WhiteSlider,
|
||||||
|
GammaSlider,
|
||||||
|
ThresholdSlider,
|
||||||
|
Histogram,
|
||||||
|
NumItems
|
||||||
|
};
|
||||||
|
enum LevelControlMode { Color_GrayScale, BlackAndWhite, NumModes };
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_histogramCue;
|
||||||
|
QVector<int> m_histogramData;
|
||||||
|
|
||||||
|
LevelControlItem m_currentItem;
|
||||||
|
|
||||||
|
int m_black, m_white, m_threshold;
|
||||||
|
float m_gamma;
|
||||||
|
int m_offset; // offset between the handle position and the clicked position
|
||||||
|
|
||||||
|
LevelControlMode m_mode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CameraCaptureLevelHistogram(QWidget* parent = 0);
|
||||||
|
|
||||||
|
void updateHistogram(QImage& image);
|
||||||
|
|
||||||
|
int black() { return m_black; }
|
||||||
|
int white() { return m_white; }
|
||||||
|
float gamma() { return m_gamma; }
|
||||||
|
int threshold() { return m_threshold; }
|
||||||
|
LevelControlMode mode() { return m_mode; }
|
||||||
|
void setValues(int black, int white, float gamma) {
|
||||||
|
m_black = black;
|
||||||
|
m_white = white;
|
||||||
|
m_gamma = gamma;
|
||||||
|
}
|
||||||
|
void setThreshold(int thres) { m_threshold = thres; }
|
||||||
|
void setMode(LevelControlMode mode) { m_mode = mode; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
|
void leaveEvent(QEvent* event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void valueChange(int itemId);
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CameraCaptureLevelControl : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
CameraCaptureLevelHistogram* m_histogram;
|
||||||
|
DVGui::IntLineEdit *m_blackFld, *m_whiteFld, *m_thresholdFld;
|
||||||
|
DVGui::DoubleLineEdit* m_gammaFld;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CameraCaptureLevelControl(QWidget* parent = 0);
|
||||||
|
|
||||||
|
void updateHistogram(QImage& image) { m_histogram->updateHistogram(image); }
|
||||||
|
void setMode(bool color_grayscale);
|
||||||
|
|
||||||
|
void getValues(int& black, int& white, float& gamma) {
|
||||||
|
black = m_histogram->black();
|
||||||
|
white = m_histogram->white();
|
||||||
|
gamma = m_histogram->gamma();
|
||||||
|
}
|
||||||
|
float getThreshold() { return m_histogram->threshold(); }
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void onHistogramValueChanged(int itemId);
|
||||||
|
void onFieldChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,17 @@
|
||||||
#include "penciltestpopup.h"
|
#include "penciltestpopup.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <mfobjects.h>
|
||||||
|
#include <mfapi.h>
|
||||||
|
#include <mfidl.h>
|
||||||
|
#pragma comment(lib, "Mfplat.lib")
|
||||||
|
#pragma comment(lib, "Mf.lib")
|
||||||
|
#pragma comment(lib, "Mfreadwrite.lib")
|
||||||
|
#pragma comment(lib, "mfuuid.lib")
|
||||||
|
#pragma comment(lib, "shlwapi.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
// Tnz6 includes
|
// Tnz6 includes
|
||||||
#include "tapp.h"
|
#include "tapp.h"
|
||||||
#include "menubarcommandids.h"
|
#include "menubarcommandids.h"
|
||||||
|
@ -87,6 +99,10 @@ TEnv::StringVar CamCapCameraName("CamCapCameraName", "");
|
||||||
TEnv::StringVar CamCapCameraResolution("CamCapCameraResolution", "");
|
TEnv::StringVar CamCapCameraResolution("CamCapCameraResolution", "");
|
||||||
// Whether to open save-in popup on launch
|
// Whether to open save-in popup on launch
|
||||||
TEnv::IntVar CamCapOpenSaveInPopupOnLaunch("CamCapOpenSaveInPopupOnLaunch", 0);
|
TEnv::IntVar CamCapOpenSaveInPopupOnLaunch("CamCapOpenSaveInPopupOnLaunch", 0);
|
||||||
|
TEnv::IntVar CamCapUseMjpg("CamCapUseMjpg", 1);
|
||||||
|
#ifdef _WIN32
|
||||||
|
TEnv::IntVar CamCapUseDirectShow("CamCapUseDirectShow", 1);
|
||||||
|
#endif
|
||||||
// SaveInFolderPopup settings
|
// SaveInFolderPopup settings
|
||||||
TEnv::StringVar CamCapSaveInParentFolder("CamCapSaveInParentFolder", "");
|
TEnv::StringVar CamCapSaveInParentFolder("CamCapSaveInParentFolder", "");
|
||||||
TEnv::IntVar CamCapSaveInPopupSubFolder("CamCapSaveInPopupSubFolder", 0);
|
TEnv::IntVar CamCapSaveInPopupSubFolder("CamCapSaveInPopupSubFolder", 0);
|
||||||
|
@ -118,7 +134,9 @@ void convertImageToRaster(TRaster32P dstRas, const QImage& srcImg) {
|
||||||
dstRas->unlock();
|
dstRas->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgReduction(QImage& srcImg, QImage& bgImg, int reduction) {
|
void bgReduction(cv::Mat& srcImg, cv::Mat& bgImg, int reduction) {
|
||||||
|
// void bgReduction(QImage& srcImg, QImage& bgImg, int reduction) {
|
||||||
|
if (srcImg.cols != bgImg.cols || srcImg.rows != bgImg.rows) return;
|
||||||
float reductionRatio = (float)reduction / 100.0f;
|
float reductionRatio = (float)reduction / 100.0f;
|
||||||
// first, make the reduction table
|
// first, make the reduction table
|
||||||
std::vector<int> reductionAmount(256);
|
std::vector<int> reductionAmount(256);
|
||||||
|
@ -126,104 +144,15 @@ void bgReduction(QImage& srcImg, QImage& bgImg, int reduction) {
|
||||||
reductionAmount[i] = (int)(std::floor((float)(255 - i) * reductionRatio));
|
reductionAmount[i] = (int)(std::floor((float)(255 - i) * reductionRatio));
|
||||||
}
|
}
|
||||||
// then, compute for all pixels
|
// then, compute for all pixels
|
||||||
int lx = srcImg.width();
|
int lx = srcImg.cols;
|
||||||
int ly = srcImg.height();
|
int ly = srcImg.rows;
|
||||||
for (int j = 0; j < ly; j++) {
|
for (int j = 0; j < srcImg.rows; j++) {
|
||||||
// TPixel32 * pix = ras->pixels(j);
|
cv::Vec3b* pix = srcImg.ptr<cv::Vec3b>(j);
|
||||||
QRgb* pix = (QRgb*)srcImg.scanLine(j);
|
cv::Vec3b* bgPix = bgImg.ptr<cv::Vec3b>(j);
|
||||||
QRgb* bgPix = (QRgb*)bgImg.scanLine(j);
|
for (int i = 0; i < srcImg.cols; i++, pix++, bgPix++) {
|
||||||
for (int i = 0; i < lx; i++, pix++, bgPix++) {
|
*pix = cv::Vec3b(std::min(255, (*pix)[0] + reductionAmount[(*bgPix)[0]]),
|
||||||
*pix = qRgb(std::min(255, qRed(*pix) + reductionAmount[qRed(*bgPix)]),
|
std::min(255, (*pix)[1] + reductionAmount[(*bgPix)[1]]),
|
||||||
std::min(255, qGreen(*pix) + reductionAmount[qGreen(*bgPix)]),
|
std::min(255, (*pix)[2] + reductionAmount[(*bgPix)[2]]));
|
||||||
std::min(255, qBlue(*pix) + reductionAmount[qBlue(*bgPix)]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void my_compute_lut(int black, int white, float gamma, std::vector<int>& lut) {
|
|
||||||
const int maxChannelValue = lut.size() - 1;
|
|
||||||
const float half_maxChannelValueF = 0.5f * maxChannelValue;
|
|
||||||
const float maxChannelValueF = maxChannelValue;
|
|
||||||
|
|
||||||
float value;
|
|
||||||
|
|
||||||
int lutSize = lut.size();
|
|
||||||
for (int i = 0; i < lutSize; i++) {
|
|
||||||
if (i <= black)
|
|
||||||
value = 0.0f;
|
|
||||||
else if (i >= white)
|
|
||||||
value = 1.0f;
|
|
||||||
else {
|
|
||||||
value = (float)(i - black) / (float)(white - black);
|
|
||||||
value = std::pow(value, 1.0f / gamma);
|
|
||||||
}
|
|
||||||
|
|
||||||
lut[i] = (int)std::floor(value * maxChannelValueF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline void doPixGray(QRgb* pix, const std::vector<int>& lut) {
|
|
||||||
int gray = lut[qGray(*pix)];
|
|
||||||
*pix = qRgb(gray, gray, gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline void doPixBinary(QRgb* pix, int threshold) {
|
|
||||||
int gray = qGray(*pix);
|
|
||||||
if (gray >= threshold)
|
|
||||||
gray = 255;
|
|
||||||
else
|
|
||||||
gray = 0;
|
|
||||||
*pix = qRgb(gray, gray, gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline void doPix(QRgb* pix, const std::vector<int>& lut) {
|
|
||||||
// The captured image MUST be full opaque!
|
|
||||||
*pix = qRgb(lut[qRed(*pix)], lut[qGreen(*pix)], lut[qBlue(*pix)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void onChange(QImage& img, int black, int white, float gamma, bool doGray) {
|
|
||||||
std::vector<int> lut(TPixel32::maxChannelValue + 1);
|
|
||||||
my_compute_lut(black, white, gamma, lut);
|
|
||||||
|
|
||||||
int ly = img.height();
|
|
||||||
// compute in multi thread
|
|
||||||
int threadCount =
|
|
||||||
std::max(1, QThreadPool::globalInstance()->maxThreadCount() / 2);
|
|
||||||
int tmpStart = 0;
|
|
||||||
for (int t = 0; t < threadCount; t++) {
|
|
||||||
int tmpEnd = (int)std::round((float)(ly * (t + 1)) / (float)threadCount);
|
|
||||||
|
|
||||||
QRunnable* task;
|
|
||||||
if (doGray)
|
|
||||||
task = new ApplyGrayLutTask(tmpStart, tmpEnd, img, lut);
|
|
||||||
else
|
|
||||||
task = new ApplyLutTask(tmpStart, tmpEnd, img, lut);
|
|
||||||
|
|
||||||
QThreadPool::globalInstance()->start(task);
|
|
||||||
|
|
||||||
tmpStart = tmpEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
QThreadPool::globalInstance()->waitForDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void onChangeBW(QImage& img, int threshold) {
|
|
||||||
int lx = img.width(), y, ly = img.height();
|
|
||||||
for (y = 0; y < ly; ++y) {
|
|
||||||
QRgb *pix = (QRgb*)img.scanLine(y), *endPix = (QRgb*)(pix + lx);
|
|
||||||
while (pix < endPix) {
|
|
||||||
doPixBinary(pix, threshold);
|
|
||||||
++pix;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,130 +402,9 @@ bool getRasterLevelSize(TXshLevel* level, TDimension& dim) {
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void ApplyLutTask::run() {
|
|
||||||
int lx = m_img.width();
|
|
||||||
for (int y = m_fromY; y < m_toY; ++y) {
|
|
||||||
QRgb *pix = (QRgb*)m_img.scanLine(y), *endPix = (QRgb*)(pix + lx);
|
|
||||||
while (pix < endPix) {
|
|
||||||
doPix(pix, m_lut);
|
|
||||||
++pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApplyGrayLutTask::run() {
|
|
||||||
int lx = m_img.width();
|
|
||||||
for (int y = m_fromY; y < m_toY; ++y) {
|
|
||||||
QRgb *pix = (QRgb*)m_img.scanLine(y), *endPix = (QRgb*)(pix + lx);
|
|
||||||
while (pix < endPix) {
|
|
||||||
doPixGray(pix, m_lut);
|
|
||||||
++pix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
MyVideoSurface::MyVideoSurface(QWidget* widget, QObject* parent)
|
|
||||||
: QAbstractVideoSurface(parent)
|
|
||||||
, m_widget(widget)
|
|
||||||
, m_imageFormat(QImage::Format_Invalid) {}
|
|
||||||
|
|
||||||
QList<QVideoFrame::PixelFormat> MyVideoSurface::supportedPixelFormats(
|
|
||||||
QAbstractVideoBuffer::HandleType handleType) const {
|
|
||||||
if (handleType == QAbstractVideoBuffer::NoHandle) {
|
|
||||||
return QList<QVideoFrame::PixelFormat>()
|
|
||||||
<< QVideoFrame::Format_RGB32 << QVideoFrame::Format_ARGB32
|
|
||||||
<< QVideoFrame::Format_ARGB32_Premultiplied
|
|
||||||
<< QVideoFrame::Format_RGB565 << QVideoFrame::Format_RGB555;
|
|
||||||
} else {
|
|
||||||
return QList<QVideoFrame::PixelFormat>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyVideoSurface::isFormatSupported(const QVideoSurfaceFormat& format,
|
|
||||||
QVideoSurfaceFormat* similar) const {
|
|
||||||
Q_UNUSED(similar);
|
|
||||||
|
|
||||||
const QImage::Format imageFormat =
|
|
||||||
QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
|
|
||||||
const QSize size = format.frameSize();
|
|
||||||
|
|
||||||
return imageFormat != QImage::Format_Invalid && !size.isEmpty() &&
|
|
||||||
format.handleType() == QAbstractVideoBuffer::NoHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyVideoSurface::start(const QVideoSurfaceFormat& format) {
|
|
||||||
const QImage::Format imageFormat =
|
|
||||||
QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
|
|
||||||
const QSize size = format.frameSize();
|
|
||||||
|
|
||||||
if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) {
|
|
||||||
m_imageFormat = imageFormat;
|
|
||||||
m_imageSize = size;
|
|
||||||
m_sourceRect = format.viewport();
|
|
||||||
|
|
||||||
QAbstractVideoSurface::start(format);
|
|
||||||
|
|
||||||
m_widget->updateGeometry();
|
|
||||||
updateVideoRect();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyVideoSurface::updateVideoRect() {
|
|
||||||
QSize size = surfaceFormat().sizeHint();
|
|
||||||
size.scale(m_widget->size(), Qt::KeepAspectRatio);
|
|
||||||
|
|
||||||
m_targetRect = QRect(QPoint(0, 0), size);
|
|
||||||
m_targetRect.moveCenter(m_widget->rect().center());
|
|
||||||
|
|
||||||
double scale =
|
|
||||||
(double)m_targetRect.width() / (double)surfaceFormat().sizeHint().width();
|
|
||||||
m_S2V_Transform =
|
|
||||||
QTransform::fromTranslate(m_targetRect.left(), m_targetRect.top())
|
|
||||||
.scale(scale, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyVideoSurface::present(const QVideoFrame& frame) {
|
|
||||||
if (surfaceFormat().pixelFormat() != frame.pixelFormat() ||
|
|
||||||
surfaceFormat().frameSize() != frame.size()) {
|
|
||||||
setError(IncorrectFormatError);
|
|
||||||
stop();
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
m_currentFrame = frame;
|
|
||||||
|
|
||||||
if (m_currentFrame.map(QAbstractVideoBuffer::ReadOnly)) {
|
|
||||||
QImage image = QImage(m_currentFrame.bits(), m_currentFrame.width(),
|
|
||||||
m_currentFrame.height(),
|
|
||||||
m_currentFrame.bytesPerLine(), m_imageFormat);
|
|
||||||
m_currentFrame.unmap();
|
|
||||||
if (!image.isNull()) emit frameCaptured(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyVideoSurface::stop() {
|
|
||||||
m_currentFrame = QVideoFrame();
|
|
||||||
m_targetRect = QRect();
|
|
||||||
|
|
||||||
QAbstractVideoSurface::stop();
|
|
||||||
|
|
||||||
m_widget->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
MyVideoWidget::MyVideoWidget(QWidget* parent)
|
MyVideoWidget::MyVideoWidget(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_previousImage(QImage())
|
, m_previousImage(QImage())
|
||||||
, m_surface(0)
|
|
||||||
, m_showOnionSkin(false)
|
, m_showOnionSkin(false)
|
||||||
, m_onionOpacity(128)
|
, m_onionOpacity(128)
|
||||||
, m_upsideDown(false)
|
, m_upsideDown(false)
|
||||||
|
@ -604,44 +412,21 @@ MyVideoWidget::MyVideoWidget(QWidget* parent)
|
||||||
, m_subCameraRect(QRect()) {
|
, m_subCameraRect(QRect()) {
|
||||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
m_surface = new MyVideoSurface(this);
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyVideoWidget::~MyVideoWidget() { delete m_surface; }
|
|
||||||
|
|
||||||
QSize MyVideoWidget::sizeHint() const {
|
|
||||||
return m_surface->surfaceFormat().sizeHint();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyVideoWidget::paintEvent(QPaintEvent* event) {
|
void MyVideoWidget::paintEvent(QPaintEvent* event) {
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
|
|
||||||
p.fillRect(rect(), Qt::black);
|
p.fillRect(rect(), Qt::black);
|
||||||
|
|
||||||
if (m_surface->isActive()) {
|
if (!m_image.isNull()) {
|
||||||
const QRect videoRect = m_surface->videoRect();
|
p.drawImage(m_targetRect, m_image);
|
||||||
const QTransform oldTransform = p.transform();
|
|
||||||
|
|
||||||
if (m_upsideDown) {
|
|
||||||
p.translate(videoRect.center());
|
|
||||||
p.rotate(180);
|
|
||||||
p.translate(-videoRect.center());
|
|
||||||
}
|
|
||||||
if (m_surface->surfaceFormat().scanLineDirection() ==
|
|
||||||
QVideoSurfaceFormat::BottomToTop) {
|
|
||||||
p.scale(1, -1);
|
|
||||||
p.translate(0, -height());
|
|
||||||
}
|
|
||||||
|
|
||||||
p.drawImage(videoRect, m_image, m_surface->sourceRect());
|
|
||||||
|
|
||||||
p.setTransform(oldTransform);
|
|
||||||
|
|
||||||
if (m_showOnionSkin && m_onionOpacity > 0.0f && !m_previousImage.isNull() &&
|
if (m_showOnionSkin && m_onionOpacity > 0.0f && !m_previousImage.isNull() &&
|
||||||
m_previousImage.size() == m_image.size()) {
|
m_previousImage.size() == m_image.size()) {
|
||||||
p.setOpacity((qreal)m_onionOpacity / 255.0);
|
p.setOpacity((qreal)m_onionOpacity / 255.0);
|
||||||
p.drawImage(videoRect, m_previousImage, m_surface->sourceRect());
|
p.drawImage(m_targetRect, m_previousImage);
|
||||||
p.setOpacity(1.0);
|
p.setOpacity(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,12 +454,23 @@ void MyVideoWidget::paintEvent(QPaintEvent* event) {
|
||||||
|
|
||||||
void MyVideoWidget::resizeEvent(QResizeEvent* event) {
|
void MyVideoWidget::resizeEvent(QResizeEvent* event) {
|
||||||
QWidget::resizeEvent(event);
|
QWidget::resizeEvent(event);
|
||||||
|
computeTransform(m_image.size());
|
||||||
|
}
|
||||||
|
|
||||||
m_surface->updateVideoRect();
|
void MyVideoWidget::computeTransform(QSize imgSize) {
|
||||||
|
QSize adjustedSize = imgSize;
|
||||||
|
adjustedSize.scale(size(), Qt::KeepAspectRatio);
|
||||||
|
m_targetRect = QRect(QPoint(), adjustedSize);
|
||||||
|
m_targetRect.moveCenter(rect().center());
|
||||||
|
|
||||||
|
double scale = (double)m_targetRect.width() / (double)imgSize.width();
|
||||||
|
m_S2V_Transform =
|
||||||
|
QTransform::fromTranslate(m_targetRect.left(), m_targetRect.top())
|
||||||
|
.scale(scale, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyVideoWidget::setSubCameraSize(QSize size) {
|
void MyVideoWidget::setSubCameraSize(QSize size) {
|
||||||
QSize frameSize = m_surface->surfaceFormat().frameSize();
|
QSize frameSize = m_image.size();
|
||||||
assert(frameSize == size.expandedTo(frameSize));
|
assert(frameSize == size.expandedTo(frameSize));
|
||||||
|
|
||||||
m_subCameraRect.setSize(size);
|
m_subCameraRect.setSize(size);
|
||||||
|
@ -698,7 +494,7 @@ void MyVideoWidget::drawSubCamera(QPainter& p) {
|
||||||
p.drawRect(handleRect);
|
p.drawRect(handleRect);
|
||||||
};
|
};
|
||||||
|
|
||||||
QRect vidSubRect = m_surface->transform().mapRect(m_subCameraRect);
|
QRect vidSubRect = m_S2V_Transform.mapRect(m_subCameraRect);
|
||||||
p.setBrush(Qt::NoBrush);
|
p.setBrush(Qt::NoBrush);
|
||||||
drawSubFrameLine(HandleLeft, vidSubRect.topLeft(), vidSubRect.bottomLeft());
|
drawSubFrameLine(HandleLeft, vidSubRect.topLeft(), vidSubRect.bottomLeft());
|
||||||
drawSubFrameLine(HandleTop, vidSubRect.topLeft(), vidSubRect.topRight());
|
drawSubFrameLine(HandleTop, vidSubRect.topLeft(), vidSubRect.topRight());
|
||||||
|
@ -726,11 +522,11 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// if the sub camera is not active, do nothing and return
|
// if the sub camera is not active, do nothing and return
|
||||||
if (!m_surface->isActive() || m_subCameraRect.isNull()) return;
|
if (m_image.isNull() || m_subCameraRect.isNull()) return;
|
||||||
|
|
||||||
// with no mouse button, update the active handles
|
// with no mouse button, update the active handles
|
||||||
if (event->buttons() == Qt::NoButton) {
|
if (event->buttons() == Qt::NoButton) {
|
||||||
QRect vidSubRect = m_surface->transform().mapRect(m_subCameraRect);
|
QRect vidSubRect = m_S2V_Transform.mapRect(m_subCameraRect);
|
||||||
SUBHANDLE preHandle = m_activeSubHandle;
|
SUBHANDLE preHandle = m_activeSubHandle;
|
||||||
if (!vidSubRect.adjusted(-d, -d, d, d).contains(event->pos()))
|
if (!vidSubRect.adjusted(-d, -d, d, d).contains(event->pos()))
|
||||||
m_activeSubHandle = HandleNone;
|
m_activeSubHandle = HandleNone;
|
||||||
|
@ -795,7 +591,7 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||||
int minimumSize = 100;
|
int minimumSize = 100;
|
||||||
|
|
||||||
QPoint offset =
|
QPoint offset =
|
||||||
m_surface->transform().inverted().map(event->pos()) - m_dragStartPos;
|
m_S2V_Transform.inverted().map(event->pos()) - m_dragStartPos;
|
||||||
if (m_activeSubHandle >= HandleTopLeft &&
|
if (m_activeSubHandle >= HandleTopLeft &&
|
||||||
m_activeSubHandle <= HandleBottomRight) {
|
m_activeSubHandle <= HandleBottomRight) {
|
||||||
QSize offsetSize = m_preSubCameraRect.size();
|
QSize offsetSize = m_preSubCameraRect.size();
|
||||||
|
@ -808,7 +604,7 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||||
m_activeSubHandle == HandleTopRight)
|
m_activeSubHandle == HandleTopRight)
|
||||||
offset.rx() *= -1;
|
offset.rx() *= -1;
|
||||||
}
|
}
|
||||||
QSize camSize = m_surface->surfaceFormat().sizeHint();
|
QSize camSize = m_image.size();
|
||||||
|
|
||||||
if (m_activeSubHandle == HandleFrame) {
|
if (m_activeSubHandle == HandleFrame) {
|
||||||
clampPoint(offset, -m_preSubCameraRect.left(),
|
clampPoint(offset, -m_preSubCameraRect.left(),
|
||||||
|
@ -855,13 +651,13 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||||
void MyVideoWidget::mousePressEvent(QMouseEvent* event) {
|
void MyVideoWidget::mousePressEvent(QMouseEvent* event) {
|
||||||
// if the sub camera is not active, do nothing and return
|
// if the sub camera is not active, do nothing and return
|
||||||
// use left button only and some handle must be active
|
// use left button only and some handle must be active
|
||||||
if (!m_surface->isActive() || m_subCameraRect.isNull() ||
|
if (m_image.isNull() || m_subCameraRect.isNull() ||
|
||||||
event->button() != Qt::LeftButton || m_activeSubHandle == HandleNone)
|
event->button() != Qt::LeftButton || m_activeSubHandle == HandleNone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// record the original sub camera size
|
// record the original sub camera size
|
||||||
m_preSubCameraRect = m_subCameraRect;
|
m_preSubCameraRect = m_subCameraRect;
|
||||||
m_dragStartPos = m_surface->transform().inverted().map(event->pos());
|
m_dragStartPos = m_S2V_Transform.inverted().map(event->pos());
|
||||||
|
|
||||||
// temporary stop the camera
|
// temporary stop the camera
|
||||||
emit stopCamera();
|
emit stopCamera();
|
||||||
|
@ -870,7 +666,7 @@ void MyVideoWidget::mousePressEvent(QMouseEvent* event) {
|
||||||
void MyVideoWidget::mouseReleaseEvent(QMouseEvent* event) {
|
void MyVideoWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
// if the sub camera is not active, do nothing and return
|
// if the sub camera is not active, do nothing and return
|
||||||
// use left button only and some handle must be active
|
// use left button only and some handle must be active
|
||||||
if (!m_surface->isActive() || m_subCameraRect.isNull() ||
|
if (m_image.isNull() || m_subCameraRect.isNull() ||
|
||||||
event->button() != Qt::LeftButton || m_activeSubHandle == HandleNone)
|
event->button() != Qt::LeftButton || m_activeSubHandle == HandleNone)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1421,7 +1217,12 @@ PencilTestPopup::PencilTestPopup()
|
||||||
: Dialog(0, false, false, "PencilTest")
|
: Dialog(0, false, false, "PencilTest")
|
||||||
, m_currentCamera(NULL)
|
, m_currentCamera(NULL)
|
||||||
, m_captureWhiteBGCue(false)
|
, m_captureWhiteBGCue(false)
|
||||||
, m_captureCue(false) {
|
, m_captureCue(false)
|
||||||
|
, m_useMjpg(CamCapUseMjpg != 0)
|
||||||
|
#ifdef _WIN32
|
||||||
|
, m_useDirectShow(CamCapUseDirectShow != 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
setWindowTitle(tr("Camera Capture"));
|
setWindowTitle(tr("Camera Capture"));
|
||||||
|
|
||||||
// add maximize button to the dialog
|
// add maximize button to the dialog
|
||||||
|
@ -1476,15 +1277,12 @@ PencilTestPopup::PencilTestPopup()
|
||||||
m_timerIntervalFld = new IntField(this);
|
m_timerIntervalFld = new IntField(this);
|
||||||
m_captureTimer = new QTimer(this);
|
m_captureTimer = new QTimer(this);
|
||||||
m_countdownTimer = new QTimer(this);
|
m_countdownTimer = new QTimer(this);
|
||||||
|
m_timer = new QTimer(this);
|
||||||
|
|
||||||
m_captureButton = new QPushButton(tr("Capture\n[Return key]"), this);
|
m_captureButton = new QPushButton(tr("Capture\n[Return key]"), this);
|
||||||
QPushButton* closeButton = new QPushButton(tr("Close"), this);
|
QPushButton* closeButton = new QPushButton(tr("Close"), this);
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
m_captureFilterSettingsBtn = new QPushButton(this);
|
m_captureFilterSettingsBtn = new QPushButton(this);
|
||||||
#else
|
|
||||||
m_captureFilterSettingsBtn = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QPushButton* subfolderButton = new QPushButton(tr("Subfolder"), this);
|
QPushButton* subfolderButton = new QPushButton(tr("Subfolder"), this);
|
||||||
|
|
||||||
|
@ -1543,13 +1341,11 @@ PencilTestPopup::PencilTestPopup()
|
||||||
m_captureButton->setIcon(style.standardIcon(QStyle::SP_DialogOkButton));
|
m_captureButton->setIcon(style.standardIcon(QStyle::SP_DialogOkButton));
|
||||||
m_captureButton->setIconSize(QSize(30, 30));
|
m_captureButton->setIconSize(QSize(30, 30));
|
||||||
|
|
||||||
if (m_captureFilterSettingsBtn) {
|
|
||||||
m_captureFilterSettingsBtn->setObjectName("GearButton");
|
m_captureFilterSettingsBtn->setObjectName("GearButton");
|
||||||
m_captureFilterSettingsBtn->setFixedSize(23, 23);
|
m_captureFilterSettingsBtn->setFixedSize(23, 23);
|
||||||
m_captureFilterSettingsBtn->setIconSize(QSize(15, 15));
|
m_captureFilterSettingsBtn->setIconSize(QSize(15, 15));
|
||||||
m_captureFilterSettingsBtn->setToolTip(
|
m_captureFilterSettingsBtn->setToolTip(tr("Options"));
|
||||||
tr("Video Capture Filter Settings..."));
|
m_captureFilterSettingsBtn->setMenu(createOptionsMenu());
|
||||||
}
|
|
||||||
|
|
||||||
subfolderButton->setObjectName("SubfolderButton");
|
subfolderButton->setObjectName("SubfolderButton");
|
||||||
subfolderButton->setIconSize(QSize(15, 15));
|
subfolderButton->setIconSize(QSize(15, 15));
|
||||||
|
@ -1746,8 +1542,8 @@ PencilTestPopup::PencilTestPopup()
|
||||||
SLOT(refreshCameraList()));
|
SLOT(refreshCameraList()));
|
||||||
ret = ret && connect(m_cameraListCombo, SIGNAL(activated(int)), this,
|
ret = ret && connect(m_cameraListCombo, SIGNAL(activated(int)), this,
|
||||||
SLOT(onCameraListComboActivated(int)));
|
SLOT(onCameraListComboActivated(int)));
|
||||||
ret = ret && connect(m_resolutionCombo, SIGNAL(activated(const QString&)),
|
ret = ret && connect(m_resolutionCombo, SIGNAL(activated(int)), this,
|
||||||
this, SLOT(onResolutionComboActivated(const QString&)));
|
SLOT(onResolutionComboActivated()));
|
||||||
ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this,
|
ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this,
|
||||||
SLOT(onFileFormatOptionButtonPressed()));
|
SLOT(onFileFormatOptionButtonPressed()));
|
||||||
ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this,
|
ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this,
|
||||||
|
@ -1778,9 +1574,6 @@ PencilTestPopup::PencilTestPopup()
|
||||||
ret = ret && connect(closeButton, SIGNAL(clicked()), this, SLOT(reject()));
|
ret = ret && connect(closeButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||||
ret = ret && connect(m_captureButton, SIGNAL(clicked(bool)), this,
|
ret = ret && connect(m_captureButton, SIGNAL(clicked(bool)), this,
|
||||||
SLOT(onCaptureButtonClicked(bool)));
|
SLOT(onCaptureButtonClicked(bool)));
|
||||||
if (m_captureFilterSettingsBtn)
|
|
||||||
ret = ret && connect(m_captureFilterSettingsBtn, SIGNAL(pressed()), this,
|
|
||||||
SLOT(onCaptureFilterSettingsBtnPressed()));
|
|
||||||
ret = ret && connect(subfolderButton, SIGNAL(clicked(bool)), this,
|
ret = ret && connect(subfolderButton, SIGNAL(clicked(bool)), this,
|
||||||
SLOT(openSaveInFolderPopup()));
|
SLOT(openSaveInFolderPopup()));
|
||||||
ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this,
|
ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this,
|
||||||
|
@ -1799,15 +1592,10 @@ PencilTestPopup::PencilTestPopup()
|
||||||
SLOT(onSubCameraSizeEdited()));
|
SLOT(onSubCameraSizeEdited()));
|
||||||
ret = ret && connect(m_subHeightFld, SIGNAL(editingFinished()), this,
|
ret = ret && connect(m_subHeightFld, SIGNAL(editingFinished()), this,
|
||||||
SLOT(onSubCameraSizeEdited()));
|
SLOT(onSubCameraSizeEdited()));
|
||||||
ret = ret && connect(m_videoWidget, &MyVideoWidget::startCamera, [&]() {
|
|
||||||
if (m_currentCamera) m_currentCamera->start();
|
|
||||||
});
|
|
||||||
ret = ret && connect(m_videoWidget, &MyVideoWidget::stopCamera, [&]() {
|
|
||||||
if (m_currentCamera) m_currentCamera->stop();
|
|
||||||
});
|
|
||||||
ret = ret && connect(m_videoWidget, SIGNAL(subCameraResized(bool)), this,
|
ret = ret && connect(m_videoWidget, SIGNAL(subCameraResized(bool)), this,
|
||||||
SLOT(onSubCameraResized(bool)));
|
SLOT(onSubCameraResized(bool)));
|
||||||
|
|
||||||
|
ret = ret && connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
refreshCameraList();
|
refreshCameraList();
|
||||||
|
@ -1824,7 +1612,7 @@ PencilTestPopup::PencilTestPopup()
|
||||||
int startupResolutionIndex = m_resolutionCombo->findText(resStr);
|
int startupResolutionIndex = m_resolutionCombo->findText(resStr);
|
||||||
if (startupResolutionIndex >= 0) {
|
if (startupResolutionIndex >= 0) {
|
||||||
m_resolutionCombo->setCurrentIndex(startupResolutionIndex);
|
m_resolutionCombo->setCurrentIndex(startupResolutionIndex);
|
||||||
onResolutionComboActivated(resStr);
|
onResolutionComboActivated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1833,14 +1621,45 @@ PencilTestPopup::PencilTestPopup()
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
PencilTestPopup::~PencilTestPopup() {
|
PencilTestPopup::~PencilTestPopup() { m_cvWebcam.release(); }
|
||||||
if (m_currentCamera) {
|
|
||||||
if (m_currentCamera->state() == QCamera::ActiveState)
|
//-----------------------------------------------------------------------------
|
||||||
m_currentCamera->stop();
|
|
||||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
QMenu* PencilTestPopup::createOptionsMenu() {
|
||||||
m_currentCamera->unload();
|
QMenu* menu = new QMenu();
|
||||||
delete m_currentCamera;
|
bool ret = true;
|
||||||
}
|
#ifdef _WIN32
|
||||||
|
QAction* settingsAct =
|
||||||
|
menu->addAction(tr("Video Capture Filter Settings..."));
|
||||||
|
ret = ret && connect(settingsAct, SIGNAL(triggered()), this,
|
||||||
|
SLOT(onCaptureFilterSettingsBtnPressed()));
|
||||||
|
settingsAct->setIcon(QIcon(":Resources/preferences.svg"));
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
|
||||||
|
QAction* useDShowAct = menu->addAction(tr("Use Direct Show Webcam Drivers"));
|
||||||
|
useDShowAct->setCheckable(true);
|
||||||
|
useDShowAct->setChecked(m_useDirectShow);
|
||||||
|
ret = ret && connect(useDShowAct, &QAction::toggled, [&](bool checked) {
|
||||||
|
m_cvWebcam.release();
|
||||||
|
if (m_timer->isActive()) m_timer->stop();
|
||||||
|
m_useDirectShow = checked;
|
||||||
|
CamCapUseDirectShow = checked;
|
||||||
|
m_timer->start(40);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
QAction* useMjpgAct = menu->addAction(tr("Use MJPG with Webcam"));
|
||||||
|
useMjpgAct->setCheckable(true);
|
||||||
|
useMjpgAct->setChecked(m_useMjpg);
|
||||||
|
ret = ret && connect(useMjpgAct, &QAction::toggled, [&](bool checked) {
|
||||||
|
m_cvWebcam.release();
|
||||||
|
if (m_timer->isActive()) m_timer->stop();
|
||||||
|
m_useMjpg = checked;
|
||||||
|
CamCapUseMjpg = checked;
|
||||||
|
m_timer->start(40);
|
||||||
|
});
|
||||||
|
|
||||||
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1874,15 +1693,11 @@ void PencilTestPopup::onCameraListComboActivated(int comboIndex) {
|
||||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||||
if (cameras.size() != m_cameraListCombo->count() - 1) return;
|
if (cameras.size() != m_cameraListCombo->count() - 1) return;
|
||||||
|
|
||||||
|
m_cvWebcam.release();
|
||||||
|
if (m_timer->isActive()) m_timer->stop();
|
||||||
|
|
||||||
// if selected the non-connected state, then disconnect the current camera
|
// if selected the non-connected state, then disconnect the current camera
|
||||||
if (comboIndex == 0) {
|
if (comboIndex == 0) {
|
||||||
m_videoWidget->videoSurface()->stop();
|
|
||||||
if (m_currentCamera) {
|
|
||||||
if (m_currentCamera->state() == QCamera::ActiveState)
|
|
||||||
m_currentCamera->stop();
|
|
||||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
|
||||||
m_currentCamera->unload();
|
|
||||||
}
|
|
||||||
m_deviceName = QString();
|
m_deviceName = QString();
|
||||||
m_videoWidget->setImage(QImage());
|
m_videoWidget->setImage(QImage());
|
||||||
// update env
|
// update env
|
||||||
|
@ -1894,9 +1709,6 @@ void PencilTestPopup::onCameraListComboActivated(int comboIndex) {
|
||||||
// in case the camera is not changed (just click the combobox)
|
// in case the camera is not changed (just click the combobox)
|
||||||
if (cameras.at(index).deviceName() == m_deviceName) return;
|
if (cameras.at(index).deviceName() == m_deviceName) return;
|
||||||
|
|
||||||
QCamera* oldCamera = m_currentCamera;
|
|
||||||
if (oldCamera) m_videoWidget->videoSurface()->stop();
|
|
||||||
|
|
||||||
m_currentCamera = new QCamera(cameras.at(index), this);
|
m_currentCamera = new QCamera(cameras.at(index), this);
|
||||||
m_deviceName = cameras.at(index).deviceName();
|
m_deviceName = cameras.at(index).deviceName();
|
||||||
|
|
||||||
|
@ -1907,63 +1719,46 @@ void PencilTestPopup::onCameraListComboActivated(int comboIndex) {
|
||||||
m_resolutionCombo->clear();
|
m_resolutionCombo->clear();
|
||||||
QList<QSize> sizes = m_currentCamera->supportedViewfinderResolutions();
|
QList<QSize> sizes = m_currentCamera->supportedViewfinderResolutions();
|
||||||
|
|
||||||
for (int s = 0; s < sizes.size(); s++) {
|
m_currentCamera->unload();
|
||||||
|
for (const QSize size : sizes) {
|
||||||
m_resolutionCombo->addItem(
|
m_resolutionCombo->addItem(
|
||||||
QString("%1 x %2").arg(sizes.at(s).width()).arg(sizes.at(s).height()));
|
QString("%1 x %2").arg(size.width()).arg(size.height()), size);
|
||||||
}
|
}
|
||||||
if (!sizes.isEmpty()) {
|
if (!sizes.isEmpty()) {
|
||||||
// select the largest available resolution
|
// select the largest available resolution
|
||||||
m_resolutionCombo->setCurrentIndex(m_resolutionCombo->count() - 1);
|
m_resolutionCombo->setCurrentIndex(m_resolutionCombo->count() - 1);
|
||||||
QCameraViewfinderSettings settings = m_currentCamera->viewfinderSettings();
|
|
||||||
settings.setResolution(sizes.last());
|
|
||||||
m_currentCamera->setViewfinderSettings(settings);
|
|
||||||
}
|
}
|
||||||
m_currentCamera->setViewfinder(m_videoWidget->videoSurface());
|
|
||||||
m_videoWidget->videoSurface()->start(
|
|
||||||
m_videoWidget->videoSurface()->surfaceFormat());
|
|
||||||
|
|
||||||
// deleting old camera
|
|
||||||
if (oldCamera) {
|
|
||||||
if (oldCamera->state() == QCamera::ActiveState) oldCamera->stop();
|
|
||||||
delete oldCamera;
|
|
||||||
}
|
|
||||||
// start new camera
|
|
||||||
m_currentCamera->start();
|
|
||||||
m_videoWidget->setImage(QImage());
|
m_videoWidget->setImage(QImage());
|
||||||
|
m_timer->start(40);
|
||||||
// update env
|
// update env
|
||||||
CamCapCameraName = m_cameraListCombo->itemText(comboIndex).toStdString();
|
CamCapCameraName = m_cameraListCombo->itemText(comboIndex).toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PencilTestPopup::onResolutionComboActivated(const QString& itemText) {
|
void PencilTestPopup::onResolutionComboActivated() {
|
||||||
// resolution is written in the itemText with the format "<width> x <height>"
|
m_cvWebcam.release();
|
||||||
// (e.g. "800 x 600")
|
if (m_timer->isActive()) m_timer->stop();
|
||||||
QStringList texts = itemText.split(' ');
|
|
||||||
// the splited text must be "<width>" "x" and "<height>"
|
|
||||||
if (texts.size() != 3) return;
|
|
||||||
|
|
||||||
#ifndef MACOSX
|
QSize newResolution = m_resolutionCombo->currentData().toSize();
|
||||||
m_currentCamera->stop();
|
|
||||||
m_currentCamera->unload();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QCameraViewfinderSettings settings = m_currentCamera->viewfinderSettings();
|
if (!newResolution.isValid()) return;
|
||||||
QSize newResolution(texts[0].toInt(), texts[2].toInt());
|
if (newResolution == m_resolution) {
|
||||||
settings.setResolution(newResolution);
|
m_timer->start(40);
|
||||||
m_currentCamera->setViewfinderSettings(settings);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_resolution = newResolution;
|
||||||
|
|
||||||
// reset white bg
|
// reset white bg
|
||||||
m_whiteBGImg = QImage();
|
m_whiteBGImg = cv::Mat();
|
||||||
m_bgReductionFld->setDisabled(true);
|
m_bgReductionFld->setDisabled(true);
|
||||||
#ifndef MACOSX
|
|
||||||
m_currentCamera->start();
|
|
||||||
#endif
|
|
||||||
m_videoWidget->setImage(QImage());
|
m_videoWidget->setImage(QImage());
|
||||||
|
m_videoWidget->computeTransform(m_resolution);
|
||||||
|
|
||||||
// update env
|
// update env
|
||||||
CamCapCameraResolution = itemText.toStdString();
|
CamCapCameraResolution = m_resolutionCombo->currentText().toStdString();
|
||||||
|
|
||||||
refreshFrameInfo();
|
refreshFrameInfo();
|
||||||
|
|
||||||
|
@ -1982,13 +1777,14 @@ void PencilTestPopup::onResolutionComboActivated(const QString& itemText) {
|
||||||
TDimension camres = camera->getRes();
|
TDimension camres = camera->getRes();
|
||||||
newResolution =
|
newResolution =
|
||||||
QSize(camres.lx, camres.ly).scaled(newResolution, Qt::KeepAspectRatio);
|
QSize(camres.lx, camres.ly).scaled(newResolution, Qt::KeepAspectRatio);
|
||||||
// newResolution.scale(QSize(res.lx, res.ly), Qt::KeepAspectRatio);
|
|
||||||
m_subWidthFld->setValue(newResolution.width());
|
m_subWidthFld->setValue(newResolution.width());
|
||||||
m_subHeightFld->setValue(newResolution.height());
|
m_subHeightFld->setValue(newResolution.height());
|
||||||
} else {
|
} else {
|
||||||
m_subWidthFld->setValue(m_allowedCameraSize.width());
|
m_subWidthFld->setValue(m_allowedCameraSize.width());
|
||||||
m_subHeightFld->setValue(m_allowedCameraSize.height());
|
m_subHeightFld->setValue(m_allowedCameraSize.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_timer->start(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2018,7 +1814,6 @@ void PencilTestPopup::onNextName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring levelName = nameCreator->getNext();
|
std::wstring levelName = nameCreator->getNext();
|
||||||
|
|
||||||
updateLevelNameAndFrame(levelName);
|
updateLevelNameAndFrame(levelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2125,33 +1920,158 @@ void PencilTestPopup::onColorTypeComboChanged(int index) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PencilTestPopup::onFrameCaptured(QImage& image) {
|
void PencilTestPopup::onTimeout() { getWebcamImage(); }
|
||||||
if (!m_videoWidget || image.isNull()) return;
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int PencilTestPopup::translateIndex(int camIndex) {
|
||||||
|
// We are using Qt to get the camera info and supported resolutions, but
|
||||||
|
// we are using OpenCV to actually get the images.
|
||||||
|
// The camera index from OpenCV and from Qt don't always agree,
|
||||||
|
// So this checks the name against the correct index.
|
||||||
|
|
||||||
|
// Thanks to:
|
||||||
|
// https://elcharolin.wordpress.com/2017/08/28/webcam-capture-with-the-media-foundation-sdk/
|
||||||
|
// for the webcam enumeration here
|
||||||
|
|
||||||
|
std::wstring desc = m_cameraListCombo->currentText().toStdWString();
|
||||||
|
|
||||||
|
#define CLEAN_ATTRIBUTES() \
|
||||||
|
if (attributes) { \
|
||||||
|
attributes->Release(); \
|
||||||
|
attributes = NULL; \
|
||||||
|
} \
|
||||||
|
for (DWORD i = 0; i < count; i++) { \
|
||||||
|
if (&devices[i]) { \
|
||||||
|
devices[i]->Release(); \
|
||||||
|
devices[i] = NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
CoTaskMemFree(devices); \
|
||||||
|
return camIndex;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
// this is important!!
|
||||||
|
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
|
||||||
|
UINT32 count = 0;
|
||||||
|
IMFAttributes* attributes = NULL;
|
||||||
|
IMFActivate** devices = NULL;
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
CLEAN_ATTRIBUTES()
|
||||||
|
}
|
||||||
|
// Create an attribute store to specify enumeration parameters.
|
||||||
|
hr = MFCreateAttributes(&attributes, 1);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
CLEAN_ATTRIBUTES()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The attribute to be requested is devices that can capture video
|
||||||
|
hr = attributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||||
|
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
CLEAN_ATTRIBUTES()
|
||||||
|
}
|
||||||
|
// Enummerate the video capture devices
|
||||||
|
hr = MFEnumDeviceSources(attributes, &devices, &count);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
CLEAN_ATTRIBUTES()
|
||||||
|
}
|
||||||
|
// if there are any available devices
|
||||||
|
if (count > 0) {
|
||||||
|
WCHAR* nameString = NULL;
|
||||||
|
// Get the human-friendly name of the device
|
||||||
|
UINT32 cchName;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
hr = devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
|
||||||
|
&nameString, &cchName);
|
||||||
|
if (nameString == desc) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
// devices[0]->ShutdownObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoTaskMemFree(nameString);
|
||||||
|
}
|
||||||
|
// clean
|
||||||
|
CLEAN_ATTRIBUTES()
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void PencilTestPopup::getWebcamImage() {
|
||||||
|
bool error = false;
|
||||||
|
cv::Mat imgOriginal;
|
||||||
|
cv::Mat imgCorrected;
|
||||||
|
|
||||||
|
if (m_cvWebcam.isOpened() == false) {
|
||||||
|
if (m_cameraListCombo->currentIndex() <= 0) return;
|
||||||
|
int camIndex = m_cameraListCombo->currentIndex() - 1;
|
||||||
|
if (!m_useDirectShow) {
|
||||||
|
// the webcam order obtained from Qt isn't always the same order as
|
||||||
|
// the one obtained from OpenCV without DirectShow
|
||||||
|
m_cvWebcam.open(translateIndex(camIndex));
|
||||||
|
} else {
|
||||||
|
m_cvWebcam.open(camIndex, cv::CAP_DSHOW);
|
||||||
|
}
|
||||||
|
// mjpg is used by many webcams
|
||||||
|
// opencv runs very slow on some webcams without it.
|
||||||
|
if (m_useMjpg) {
|
||||||
|
m_cvWebcam.set(cv::CAP_PROP_FOURCC,
|
||||||
|
cv::VideoWriter::fourcc('m', 'j', 'p', 'g'));
|
||||||
|
m_cvWebcam.set(cv::CAP_PROP_FOURCC,
|
||||||
|
cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
|
||||||
|
}
|
||||||
|
m_cvWebcam.set(cv::CAP_PROP_FRAME_WIDTH, m_resolution.width());
|
||||||
|
m_cvWebcam.set(cv::CAP_PROP_FRAME_HEIGHT, m_resolution.height());
|
||||||
|
if (!m_cvWebcam.isOpened()) error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool blnFrameReadSuccessfully =
|
||||||
|
m_cvWebcam.read(imgOriginal); // get next frame
|
||||||
|
|
||||||
|
if (!blnFrameReadSuccessfully ||
|
||||||
|
imgOriginal.empty()) { // if frame not read successfully
|
||||||
|
std::cout << "error: frame not read from webcam\n";
|
||||||
|
error = true; // print error message to std out
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
cv::cvtColor(imgOriginal, imgCorrected, cv::COLOR_BGR2RGB);
|
||||||
|
onFrameCaptured(imgCorrected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void PencilTestPopup::onFrameCaptured(cv::Mat& image) {
|
||||||
|
if (!m_videoWidget) return;
|
||||||
// capture the white BG
|
// capture the white BG
|
||||||
if (m_captureWhiteBGCue) {
|
if (m_captureWhiteBGCue) {
|
||||||
m_whiteBGImg = image.copy();
|
;
|
||||||
|
m_whiteBGImg = image.clone();
|
||||||
m_captureWhiteBGCue = false;
|
m_captureWhiteBGCue = false;
|
||||||
m_bgReductionFld->setEnabled(true);
|
m_bgReductionFld->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
processImage(image);
|
processImage(image);
|
||||||
m_videoWidget->setImage(image.copy());
|
|
||||||
|
QImage::Format format = (m_colorTypeCombo->currentIndex() == 0)
|
||||||
|
? QImage::Format_RGB888
|
||||||
|
: QImage::Format_Grayscale8;
|
||||||
|
QImage qimg(image.data, image.cols, image.rows, format);
|
||||||
|
m_videoWidget->setImage(qimg.copy());
|
||||||
|
|
||||||
if (m_captureCue) {
|
if (m_captureCue) {
|
||||||
#ifndef MACOSX
|
|
||||||
m_currentCamera->stop();
|
|
||||||
#endif
|
|
||||||
m_captureCue = false;
|
m_captureCue = false;
|
||||||
|
|
||||||
bool scanBtoT =
|
if (importImage(qimg)) {
|
||||||
m_videoWidget->videoSurface()->surfaceFormat().scanLineDirection() ==
|
m_videoWidget->setPreviousImage(qimg.copy());
|
||||||
QVideoSurfaceFormat::BottomToTop;
|
|
||||||
bool upsideDown = m_upsideDownCB->isChecked();
|
|
||||||
|
|
||||||
image = image.mirrored(upsideDown, upsideDown != scanBtoT);
|
|
||||||
|
|
||||||
if (importImage(image)) {
|
|
||||||
m_videoWidget->setPreviousImage(image.copy());
|
|
||||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
|
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
|
||||||
int f = m_frameNumberEdit->getValue();
|
int f = m_frameNumberEdit->getValue();
|
||||||
if (f % 10 == 0) // next number
|
if (f % 10 == 0) // next number
|
||||||
|
@ -2179,34 +2099,18 @@ void PencilTestPopup::onFrameCaptured(QImage& image) {
|
||||||
m_captureButton->setChecked(false);
|
m_captureButton->setChecked(false);
|
||||||
onCaptureButtonClicked(false);
|
onCaptureButtonClicked(false);
|
||||||
}
|
}
|
||||||
#ifndef MACOSX
|
|
||||||
m_currentCamera->start();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PencilTestPopup::showEvent(QShowEvent* event) {
|
void PencilTestPopup::showEvent(QShowEvent* event) {
|
||||||
// m_timerId = startTimer(10);
|
|
||||||
|
|
||||||
// if there is another action of which "return" key is assigned as short cut
|
// if there is another action of which "return" key is assigned as short cut
|
||||||
// key,
|
// key,
|
||||||
// then release the shortcut key temporary while the popup opens
|
// then release the shortcut key temporary while the popup opens
|
||||||
QAction* action = CommandManager::instance()->getActionFromShortcut("Return");
|
QAction* action = CommandManager::instance()->getActionFromShortcut("Return");
|
||||||
if (action) action->setShortcut(QKeySequence(""));
|
if (action) action->setShortcut(QKeySequence(""));
|
||||||
|
|
||||||
connect(m_videoWidget->videoSurface(), SIGNAL(frameCaptured(QImage&)), this,
|
|
||||||
SLOT(onFrameCaptured(QImage&)));
|
|
||||||
|
|
||||||
// reload camera
|
|
||||||
if (m_currentCamera) {
|
|
||||||
if (m_currentCamera->state() == QCamera::UnloadedState)
|
|
||||||
m_currentCamera->load();
|
|
||||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
|
||||||
m_currentCamera->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene();
|
TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene();
|
||||||
connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(onSceneSwitched()));
|
connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(onSceneSwitched()));
|
||||||
connect(sceneHandle, SIGNAL(castChanged()), this, SLOT(refreshFrameInfo()));
|
connect(sceneHandle, SIGNAL(castChanged()), this, SLOT(refreshFrameInfo()));
|
||||||
|
@ -2214,6 +2118,9 @@ void PencilTestPopup::showEvent(QShowEvent* event) {
|
||||||
bool tmp_alwaysOverwrite = m_alwaysOverwrite;
|
bool tmp_alwaysOverwrite = m_alwaysOverwrite;
|
||||||
onSceneSwitched();
|
onSceneSwitched();
|
||||||
m_alwaysOverwrite = tmp_alwaysOverwrite;
|
m_alwaysOverwrite = tmp_alwaysOverwrite;
|
||||||
|
|
||||||
|
onResolutionComboActivated();
|
||||||
|
m_videoWidget->computeTransform(m_resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -2223,22 +2130,15 @@ void PencilTestPopup::hideEvent(QHideEvent* event) {
|
||||||
QAction* action = CommandManager::instance()->getActionFromShortcut("Return");
|
QAction* action = CommandManager::instance()->getActionFromShortcut("Return");
|
||||||
if (action) action->setShortcut(QKeySequence("Return"));
|
if (action) action->setShortcut(QKeySequence("Return"));
|
||||||
|
|
||||||
disconnect(m_videoWidget->videoSurface(), SIGNAL(frameCaptured(QImage&)),
|
|
||||||
this, SLOT(onFrameCaptured(QImage&)));
|
|
||||||
|
|
||||||
// stop interval timer if it is active
|
// stop interval timer if it is active
|
||||||
if (m_timerCB->isChecked() && m_captureButton->isChecked()) {
|
if (m_timerCB->isChecked() && m_captureButton->isChecked()) {
|
||||||
m_captureButton->setChecked(false);
|
m_captureButton->setChecked(false);
|
||||||
onCaptureButtonClicked(false);
|
onCaptureButtonClicked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// release camera
|
m_cvWebcam.release();
|
||||||
if (m_currentCamera) {
|
if (m_timer->isActive()) m_timer->stop();
|
||||||
if (m_currentCamera->state() == QCamera::ActiveState)
|
|
||||||
m_currentCamera->stop();
|
|
||||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
|
||||||
m_currentCamera->unload();
|
|
||||||
}
|
|
||||||
Dialog::hideEvent(event);
|
Dialog::hideEvent(event);
|
||||||
|
|
||||||
TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene();
|
TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene();
|
||||||
|
@ -2281,27 +2181,26 @@ bool PencilTestPopup::event(QEvent* event) {
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PencilTestPopup::processImage(QImage& image) {
|
void PencilTestPopup::processImage(cv::Mat& image) {
|
||||||
/* "upside down" is not executed here. It will be done when capturing the
|
// void PencilTestPopup::processImage(QImage& image) {
|
||||||
* image */
|
if (m_upsideDownCB->isChecked())
|
||||||
|
cv::flip(image, image, -1); // flip in both directions
|
||||||
// white bg reduction
|
// white bg reduction
|
||||||
if (!m_whiteBGImg.isNull() && m_bgReductionFld->getValue() != 0) {
|
if (!m_whiteBGImg.empty() && m_bgReductionFld->getValue() != 0)
|
||||||
bgReduction(image, m_whiteBGImg, m_bgReductionFld->getValue());
|
bgReduction(image, m_whiteBGImg, m_bgReductionFld->getValue());
|
||||||
}
|
|
||||||
// obtain histogram AFTER bg reduction
|
// obtain histogram AFTER bg reduction
|
||||||
m_camCapLevelControl->updateHistogram(image);
|
m_camCapLevelControl->updateHistogram(image);
|
||||||
|
|
||||||
|
// change channel
|
||||||
|
if (m_colorTypeCombo->currentIndex() != 0)
|
||||||
|
cv::cvtColor(image, image, cv::COLOR_RGB2GRAY);
|
||||||
|
|
||||||
// color and grayscale mode
|
// color and grayscale mode
|
||||||
if (m_colorTypeCombo->currentIndex() != 2) {
|
if (m_colorTypeCombo->currentIndex() != 2)
|
||||||
int black, white;
|
m_camCapLevelControl->adjustLevel(image);
|
||||||
float gamma;
|
else
|
||||||
m_camCapLevelControl->getValues(black, white, gamma);
|
m_camCapLevelControl->binarize(image);
|
||||||
if (black != 0 || white != 255 || gamma != 1.0)
|
|
||||||
onChange(image, black, white, gamma,
|
|
||||||
m_colorTypeCombo->currentIndex() != 0);
|
|
||||||
} else {
|
|
||||||
onChangeBW(image, m_camCapLevelControl->getThreshold());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -6,16 +6,17 @@
|
||||||
#include "toonzqt/dvdialog.h"
|
#include "toonzqt/dvdialog.h"
|
||||||
#include "toonzqt/lineedit.h"
|
#include "toonzqt/lineedit.h"
|
||||||
#include "toonz/namebuilder.h"
|
#include "toonz/namebuilder.h"
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
|
||||||
#include <QAbstractVideoSurface>
|
#include <QAbstractVideoSurface>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
// forward decl.
|
// forward decl.
|
||||||
class QCamera;
|
class QCamera;
|
||||||
class QCameraImageCapture;
|
class QCameraImageCapture;
|
||||||
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QLineEdit;
|
|
||||||
class QSlider;
|
class QSlider;
|
||||||
class QCheckBox;
|
class QCheckBox;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
|
@ -36,70 +37,6 @@ class IntLineEdit;
|
||||||
|
|
||||||
class CameraCaptureLevelControl;
|
class CameraCaptureLevelControl;
|
||||||
|
|
||||||
class ApplyLutTask : public QRunnable {
|
|
||||||
protected:
|
|
||||||
int m_fromY, m_toY;
|
|
||||||
QImage& m_img;
|
|
||||||
std::vector<int>& m_lut;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ApplyLutTask(int from, int to, QImage& img, std::vector<int>& lut)
|
|
||||||
: m_fromY(from), m_toY(to), m_img(img), m_lut(lut) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ApplyGrayLutTask : public ApplyLutTask {
|
|
||||||
public:
|
|
||||||
ApplyGrayLutTask(int from, int to, QImage& img, std::vector<int>& lut)
|
|
||||||
: ApplyLutTask(from, to, img, lut) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// MyVideoSurface
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class QVideoSurfaceFormat;
|
|
||||||
class MyVideoSurface : public QAbstractVideoSurface {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
MyVideoSurface(QWidget* widget, QObject* parent = 0);
|
|
||||||
|
|
||||||
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
|
|
||||||
QAbstractVideoBuffer::HandleType handleType =
|
|
||||||
QAbstractVideoBuffer::NoHandle) const;
|
|
||||||
bool isFormatSupported(const QVideoSurfaceFormat& format,
|
|
||||||
QVideoSurfaceFormat* similar) const;
|
|
||||||
|
|
||||||
bool start(const QVideoSurfaceFormat& format);
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
bool present(const QVideoFrame& frame);
|
|
||||||
|
|
||||||
QRect videoRect() const { return m_targetRect; }
|
|
||||||
QRect sourceRect() const { return m_sourceRect; }
|
|
||||||
void updateVideoRect();
|
|
||||||
|
|
||||||
QTransform transform() { return m_S2V_Transform; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWidget* m_widget;
|
|
||||||
QImage::Format m_imageFormat;
|
|
||||||
QRect m_targetRect;
|
|
||||||
QSize m_imageSize;
|
|
||||||
QRect m_sourceRect;
|
|
||||||
QVideoFrame m_currentFrame;
|
|
||||||
|
|
||||||
QTransform m_S2V_Transform; // surface to video transform
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void frameCaptured(QImage& image);
|
|
||||||
};
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// MyVideoWidget
|
// MyVideoWidget
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -118,6 +55,8 @@ class MyVideoWidget : public QWidget {
|
||||||
QRect m_preSubCameraRect;
|
QRect m_preSubCameraRect;
|
||||||
QPoint m_dragStartPos;
|
QPoint m_dragStartPos;
|
||||||
|
|
||||||
|
QRect m_targetRect;
|
||||||
|
QTransform m_S2V_Transform; // surface to video transform
|
||||||
enum SUBHANDLE {
|
enum SUBHANDLE {
|
||||||
HandleNone,
|
HandleNone,
|
||||||
HandleFrame,
|
HandleFrame,
|
||||||
|
@ -134,15 +73,11 @@ class MyVideoWidget : public QWidget {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyVideoWidget(QWidget* parent = 0);
|
MyVideoWidget(QWidget* parent = 0);
|
||||||
~MyVideoWidget();
|
|
||||||
|
|
||||||
void setImage(const QImage& image) {
|
void setImage(const QImage& image) {
|
||||||
m_image = image;
|
m_image = image;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
QAbstractVideoSurface* videoSurface() const { return m_surface; }
|
|
||||||
|
|
||||||
QSize sizeHint() const;
|
|
||||||
|
|
||||||
void setShowOnionSkin(bool on) { m_showOnionSkin = on; }
|
void setShowOnionSkin(bool on) { m_showOnionSkin = on; }
|
||||||
void setOnionOpacity(int value) { m_onionOpacity = value; }
|
void setOnionOpacity(int value) { m_onionOpacity = value; }
|
||||||
|
@ -156,6 +91,8 @@ public:
|
||||||
void setSubCameraSize(QSize size);
|
void setSubCameraSize(QSize size);
|
||||||
QRect subCameraRect() { return m_subCameraRect; }
|
QRect subCameraRect() { return m_subCameraRect; }
|
||||||
|
|
||||||
|
void computeTransform(QSize imgSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent* event) override;
|
void paintEvent(QPaintEvent* event) override;
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
@ -164,9 +101,6 @@ protected:
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
private:
|
|
||||||
MyVideoSurface* m_surface;
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onUpsideDownChecked(bool on) { m_upsideDown = on; }
|
void onUpsideDownChecked(bool on) { m_upsideDown = on; }
|
||||||
|
|
||||||
|
@ -281,6 +215,12 @@ protected slots:
|
||||||
class PencilTestPopup : public DVGui::Dialog {
|
class PencilTestPopup : public DVGui::Dialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
QTimer* m_timer;
|
||||||
|
cv::VideoCapture m_cvWebcam;
|
||||||
|
QSize m_resolution;
|
||||||
|
|
||||||
|
//--------
|
||||||
|
|
||||||
QCamera* m_currentCamera;
|
QCamera* m_currentCamera;
|
||||||
QString m_deviceName;
|
QString m_deviceName;
|
||||||
MyVideoWidget* m_videoWidget;
|
MyVideoWidget* m_videoWidget;
|
||||||
|
@ -297,7 +237,7 @@ class PencilTestPopup : public DVGui::Dialog {
|
||||||
|
|
||||||
QTimer *m_captureTimer, *m_countdownTimer;
|
QTimer *m_captureTimer, *m_countdownTimer;
|
||||||
|
|
||||||
QImage m_whiteBGImg;
|
cv::Mat m_whiteBGImg;
|
||||||
|
|
||||||
// used only for Windows
|
// used only for Windows
|
||||||
QPushButton* m_captureFilterSettingsBtn;
|
QPushButton* m_captureFilterSettingsBtn;
|
||||||
|
@ -317,13 +257,23 @@ class PencilTestPopup : public DVGui::Dialog {
|
||||||
bool m_captureWhiteBGCue;
|
bool m_captureWhiteBGCue;
|
||||||
bool m_captureCue;
|
bool m_captureCue;
|
||||||
bool m_alwaysOverwrite = false;
|
bool m_alwaysOverwrite = false;
|
||||||
|
bool m_useMjpg;
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool m_useDirectShow;
|
||||||
|
#endif
|
||||||
|
|
||||||
void processImage(QImage& procImage);
|
void processImage(cv::Mat& procImage);
|
||||||
bool importImage(QImage image);
|
bool importImage(QImage image);
|
||||||
|
|
||||||
void setToNextNewLevel();
|
void setToNextNewLevel();
|
||||||
void updateLevelNameAndFrame(std::wstring levelName);
|
void updateLevelNameAndFrame(std::wstring levelName);
|
||||||
|
|
||||||
|
void getWebcamImage();
|
||||||
|
|
||||||
|
QMenu* createOptionsMenu();
|
||||||
|
|
||||||
|
int translateIndex(int camIndex);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PencilTestPopup();
|
PencilTestPopup();
|
||||||
~PencilTestPopup();
|
~PencilTestPopup();
|
||||||
|
@ -338,13 +288,13 @@ protected:
|
||||||
protected slots:
|
protected slots:
|
||||||
void refreshCameraList();
|
void refreshCameraList();
|
||||||
void onCameraListComboActivated(int index);
|
void onCameraListComboActivated(int index);
|
||||||
void onResolutionComboActivated(const QString&);
|
void onResolutionComboActivated();
|
||||||
void onFileFormatOptionButtonPressed();
|
void onFileFormatOptionButtonPressed();
|
||||||
void onLevelNameEdited();
|
void onLevelNameEdited();
|
||||||
void onNextName();
|
void onNextName();
|
||||||
void onPreviousName();
|
void onPreviousName();
|
||||||
void onColorTypeComboChanged(int index);
|
void onColorTypeComboChanged(int index);
|
||||||
void onFrameCaptured(QImage& image);
|
void onFrameCaptured(cv::Mat& image);
|
||||||
void onCaptureWhiteBGButtonPressed();
|
void onCaptureWhiteBGButtonPressed();
|
||||||
void onOnionCBToggled(bool);
|
void onOnionCBToggled(bool);
|
||||||
void onLoadImageButtonPressed();
|
void onLoadImageButtonPressed();
|
||||||
|
@ -365,6 +315,7 @@ protected slots:
|
||||||
void onSubCameraResized(bool isDragging);
|
void onSubCameraResized(bool isDragging);
|
||||||
void onSubCameraSizeEdited();
|
void onSubCameraSizeEdited();
|
||||||
|
|
||||||
|
void onTimeout();
|
||||||
public slots:
|
public slots:
|
||||||
void openSaveInFolderPopup();
|
void openSaveInFolderPopup();
|
||||||
};
|
};
|
||||||
|
|
3025
toonz/sources/toonz/penciltestpopup_qt.cpp
Normal file
3025
toonz/sources/toonz/penciltestpopup_qt.cpp
Normal file
File diff suppressed because it is too large
Load diff
372
toonz/sources/toonz/penciltestpopup_qt.h
Normal file
372
toonz/sources/toonz/penciltestpopup_qt.h
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef PENCILTESTPOPUP_H
|
||||||
|
#define PENCILTESTPOPUP_H
|
||||||
|
|
||||||
|
#include "toonzqt/dvdialog.h"
|
||||||
|
#include "toonzqt/lineedit.h"
|
||||||
|
#include "toonz/namebuilder.h"
|
||||||
|
|
||||||
|
#include <QAbstractVideoSurface>
|
||||||
|
#include <QRunnable>
|
||||||
|
|
||||||
|
// forward decl.
|
||||||
|
class QCamera;
|
||||||
|
class QCameraImageCapture;
|
||||||
|
|
||||||
|
class QComboBox;
|
||||||
|
class QLineEdit;
|
||||||
|
class QSlider;
|
||||||
|
class QCheckBox;
|
||||||
|
class QPushButton;
|
||||||
|
class QVideoFrame;
|
||||||
|
class QTimer;
|
||||||
|
class QIntValidator;
|
||||||
|
class QRegExpValidator;
|
||||||
|
class QPushButton;
|
||||||
|
#ifdef MACOSX
|
||||||
|
class QCameraViewfinder;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace DVGui {
|
||||||
|
class FileField;
|
||||||
|
class IntField;
|
||||||
|
class IntLineEdit;
|
||||||
|
} // namespace DVGui
|
||||||
|
|
||||||
|
class CameraCaptureLevelControl;
|
||||||
|
|
||||||
|
class ApplyLutTask : public QRunnable {
|
||||||
|
protected:
|
||||||
|
int m_fromY, m_toY;
|
||||||
|
QImage& m_img;
|
||||||
|
std::vector<int>& m_lut;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ApplyLutTask(int from, int to, QImage& img, std::vector<int>& lut)
|
||||||
|
: m_fromY(from), m_toY(to), m_img(img), m_lut(lut) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void run() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ApplyGrayLutTask : public ApplyLutTask {
|
||||||
|
public:
|
||||||
|
ApplyGrayLutTask(int from, int to, QImage& img, std::vector<int>& lut)
|
||||||
|
: ApplyLutTask(from, to, img, lut) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// MyVideoSurface
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class QVideoSurfaceFormat;
|
||||||
|
class MyVideoSurface : public QAbstractVideoSurface {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MyVideoSurface(QWidget* widget, QObject* parent = 0);
|
||||||
|
|
||||||
|
QList<QVideoFrame::PixelFormat> supportedPixelFormats(
|
||||||
|
QAbstractVideoBuffer::HandleType handleType =
|
||||||
|
QAbstractVideoBuffer::NoHandle) const;
|
||||||
|
bool isFormatSupported(const QVideoSurfaceFormat& format,
|
||||||
|
QVideoSurfaceFormat* similar) const;
|
||||||
|
|
||||||
|
bool start(const QVideoSurfaceFormat& format);
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
bool present(const QVideoFrame& frame);
|
||||||
|
|
||||||
|
QRect videoRect() const { return m_targetRect; }
|
||||||
|
QRect sourceRect() const { return m_sourceRect; }
|
||||||
|
void updateVideoRect();
|
||||||
|
|
||||||
|
QTransform transform() { return m_S2V_Transform; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QWidget* m_widget;
|
||||||
|
QImage::Format m_imageFormat;
|
||||||
|
QRect m_targetRect;
|
||||||
|
QSize m_imageSize;
|
||||||
|
QRect m_sourceRect;
|
||||||
|
QVideoFrame m_currentFrame;
|
||||||
|
|
||||||
|
QTransform m_S2V_Transform; // surface to video transform
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void frameCaptured(QImage& image);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// MyVideoWidget
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MyVideoWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QImage m_image;
|
||||||
|
QImage m_previousImage;
|
||||||
|
int m_countDownTime;
|
||||||
|
bool m_showOnionSkin;
|
||||||
|
int m_onionOpacity;
|
||||||
|
bool m_upsideDown;
|
||||||
|
|
||||||
|
QRect m_subCameraRect;
|
||||||
|
QRect m_preSubCameraRect;
|
||||||
|
QPoint m_dragStartPos;
|
||||||
|
|
||||||
|
enum SUBHANDLE {
|
||||||
|
HandleNone,
|
||||||
|
HandleFrame,
|
||||||
|
HandleTopLeft,
|
||||||
|
HandleTopRight,
|
||||||
|
HandleBottomLeft,
|
||||||
|
HandleBottomRight,
|
||||||
|
HandleLeft,
|
||||||
|
HandleTop,
|
||||||
|
HandleRight,
|
||||||
|
HandleBottom
|
||||||
|
} m_activeSubHandle = HandleNone;
|
||||||
|
void drawSubCamera(QPainter&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyVideoWidget(QWidget* parent = 0);
|
||||||
|
~MyVideoWidget();
|
||||||
|
|
||||||
|
void setImage(const QImage& image) {
|
||||||
|
m_image = image;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
QAbstractVideoSurface* videoSurface() const { return m_surface; }
|
||||||
|
|
||||||
|
QSize sizeHint() const;
|
||||||
|
|
||||||
|
void setShowOnionSkin(bool on) { m_showOnionSkin = on; }
|
||||||
|
void setOnionOpacity(int value) { m_onionOpacity = value; }
|
||||||
|
void setPreviousImage(QImage prevImage) { m_previousImage = prevImage; }
|
||||||
|
|
||||||
|
void showCountDownTime(int time) {
|
||||||
|
m_countDownTime = time;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSubCameraSize(QSize size);
|
||||||
|
QRect subCameraRect() { return m_subCameraRect; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MyVideoSurface* m_surface;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void onUpsideDownChecked(bool on) { m_upsideDown = on; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void startCamera();
|
||||||
|
void stopCamera();
|
||||||
|
void subCameraResized(bool isDragging);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// FrameNumberLineEdit
|
||||||
|
// a special Line Edit which accepts imputting alphabets if the preference
|
||||||
|
// option
|
||||||
|
// "Show ABC Appendix to the Frame Number in Xsheet Cell" is active.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FrameNumberLineEdit : public DVGui::LineEdit {
|
||||||
|
Q_OBJECT
|
||||||
|
/* having two validators and switch them according to the preferences*/
|
||||||
|
QIntValidator* m_intValidator;
|
||||||
|
QRegExpValidator* m_regexpValidator;
|
||||||
|
|
||||||
|
void updateValidator();
|
||||||
|
QString m_textOnFocusIn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FrameNumberLineEdit(QWidget* parent = 0, int value = 1);
|
||||||
|
~FrameNumberLineEdit() {}
|
||||||
|
|
||||||
|
/*! Set text in field to \b value. */
|
||||||
|
void setValue(int value);
|
||||||
|
/*! Return an integer with text field value. */
|
||||||
|
int getValue();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*! If focus is lost and current text value is out of range emit signal
|
||||||
|
\b editingFinished.*/
|
||||||
|
void focusInEvent(QFocusEvent*) override;
|
||||||
|
void focusOutEvent(QFocusEvent*) override;
|
||||||
|
void showEvent(QShowEvent* event) override { updateValidator(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
class LevelNameLineEdit : public QLineEdit {
|
||||||
|
Q_OBJECT
|
||||||
|
QString m_textOnFocusIn;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LevelNameLineEdit(QWidget* parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void focusInEvent(QFocusEvent* e);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void onEditingFinished();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void levelNameEdited();
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// FlexibleNameCreator
|
||||||
|
// Inherits NameCreator, added function for obtaining the previous name and
|
||||||
|
// setting the current name.
|
||||||
|
|
||||||
|
class FlexibleNameCreator final : public NameCreator {
|
||||||
|
public:
|
||||||
|
FlexibleNameCreator() {}
|
||||||
|
std::wstring getPrevious();
|
||||||
|
bool setCurrent(std::wstring name);
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// PencilTestSaveInFolderPopup
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class PencilTestSaveInFolderPopup : public DVGui::Dialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
DVGui::FileField* m_parentFolderField;
|
||||||
|
QLineEdit *m_projectField, *m_episodeField, *m_sequenceField, *m_sceneField,
|
||||||
|
*m_subFolderNameField;
|
||||||
|
|
||||||
|
QCheckBox *m_subFolderCB, *m_autoSubNameCB, *m_createSceneInFolderCB;
|
||||||
|
QComboBox* m_subNameFormatCombo;
|
||||||
|
|
||||||
|
void createSceneInFolder();
|
||||||
|
|
||||||
|
public:
|
||||||
|
PencilTestSaveInFolderPopup(QWidget* parent = 0);
|
||||||
|
QString getPath();
|
||||||
|
QString getParentPath();
|
||||||
|
void updateParentFolder();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* event);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void updateSubFolderName();
|
||||||
|
void onAutoSubNameCBClicked(bool);
|
||||||
|
void onShowPopupOnLaunchCBClicked(bool);
|
||||||
|
void onCreateSceneInFolderCBClicked(bool);
|
||||||
|
void onSetAsDefaultBtnPressed();
|
||||||
|
void onOkPressed();
|
||||||
|
};
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// PencilTestPopup
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class PencilTestPopup : public DVGui::Dialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QCamera* m_currentCamera;
|
||||||
|
QString m_deviceName;
|
||||||
|
MyVideoWidget* m_videoWidget;
|
||||||
|
|
||||||
|
QComboBox *m_cameraListCombo, *m_resolutionCombo, *m_fileTypeCombo,
|
||||||
|
*m_colorTypeCombo;
|
||||||
|
LevelNameLineEdit* m_levelNameEdit;
|
||||||
|
QCheckBox *m_upsideDownCB, *m_onionSkinCB, *m_saveOnCaptureCB, *m_timerCB;
|
||||||
|
QPushButton *m_fileFormatOptionButton, *m_captureWhiteBGButton,
|
||||||
|
*m_captureButton, *m_loadImageButton;
|
||||||
|
DVGui::FileField* m_saveInFileFld;
|
||||||
|
FrameNumberLineEdit* m_frameNumberEdit;
|
||||||
|
DVGui::IntField *m_bgReductionFld, *m_onionOpacityFld, *m_timerIntervalFld;
|
||||||
|
|
||||||
|
QTimer *m_captureTimer, *m_countdownTimer;
|
||||||
|
|
||||||
|
QImage m_whiteBGImg;
|
||||||
|
|
||||||
|
// used only for Windows
|
||||||
|
QPushButton* m_captureFilterSettingsBtn;
|
||||||
|
|
||||||
|
PencilTestSaveInFolderPopup* m_saveInFolderPopup;
|
||||||
|
|
||||||
|
CameraCaptureLevelControl* m_camCapLevelControl;
|
||||||
|
|
||||||
|
QLabel* m_frameInfoLabel;
|
||||||
|
|
||||||
|
QToolButton* m_previousLevelButton;
|
||||||
|
|
||||||
|
QPushButton* m_subcameraButton;
|
||||||
|
DVGui::IntLineEdit *m_subWidthFld, *m_subHeightFld;
|
||||||
|
QSize m_allowedCameraSize;
|
||||||
|
|
||||||
|
bool m_captureWhiteBGCue;
|
||||||
|
bool m_captureCue;
|
||||||
|
bool m_alwaysOverwrite = false;
|
||||||
|
|
||||||
|
void processImage(QImage& procImage);
|
||||||
|
bool importImage(QImage image);
|
||||||
|
|
||||||
|
void setToNextNewLevel();
|
||||||
|
void updateLevelNameAndFrame(std::wstring levelName);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PencilTestPopup();
|
||||||
|
~PencilTestPopup();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* event);
|
||||||
|
void hideEvent(QHideEvent* event);
|
||||||
|
void keyPressEvent(QKeyEvent* event);
|
||||||
|
|
||||||
|
bool event(QEvent* e) override;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void refreshCameraList();
|
||||||
|
void onCameraListComboActivated(int index);
|
||||||
|
void onResolutionComboActivated(const QString&);
|
||||||
|
void onFileFormatOptionButtonPressed();
|
||||||
|
void onLevelNameEdited();
|
||||||
|
void onNextName();
|
||||||
|
void onPreviousName();
|
||||||
|
void onColorTypeComboChanged(int index);
|
||||||
|
void onFrameCaptured(QImage& image);
|
||||||
|
void onCaptureWhiteBGButtonPressed();
|
||||||
|
void onOnionCBToggled(bool);
|
||||||
|
void onLoadImageButtonPressed();
|
||||||
|
void onOnionOpacityFldEdited();
|
||||||
|
void onTimerCBToggled(bool);
|
||||||
|
void onCaptureTimerTimeout();
|
||||||
|
void onCountDown();
|
||||||
|
|
||||||
|
void onCaptureButtonClicked(bool);
|
||||||
|
void onCaptureFilterSettingsBtnPressed();
|
||||||
|
|
||||||
|
void refreshFrameInfo();
|
||||||
|
|
||||||
|
void onSaveInPathEdited();
|
||||||
|
void onSceneSwitched();
|
||||||
|
|
||||||
|
void onSubCameraToggled(bool);
|
||||||
|
void onSubCameraResized(bool isDragging);
|
||||||
|
void onSubCameraSizeEdited();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void openSaveInFolderPopup();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue