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 {
|
||||
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
||||
}
|
||||
#GearButton::menu-indicator {
|
||||
image: "";
|
||||
}
|
||||
#SubfolderButton {
|
||||
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
||||
padding-left: 6px;
|
||||
|
|
|
@ -1530,6 +1530,9 @@ ProjectPopup QLabel {
|
|||
#GearButton {
|
||||
qproperty-icon: url('../Default/imgs/white/gear.svg');
|
||||
}
|
||||
#GearButton::menu-indicator {
|
||||
image: "";
|
||||
}
|
||||
#SubfolderButton {
|
||||
qproperty-icon: url('../Default/imgs/white/subfolder.svg');
|
||||
padding-left: 6px;
|
||||
|
|
|
@ -1530,6 +1530,9 @@ ProjectPopup QLabel {
|
|||
#GearButton {
|
||||
qproperty-icon: url('imgs/white/gear.svg');
|
||||
}
|
||||
#GearButton::menu-indicator {
|
||||
image: "";
|
||||
}
|
||||
#SubfolderButton {
|
||||
qproperty-icon: url('imgs/white/subfolder.svg');
|
||||
padding-left: 6px;
|
||||
|
|
|
@ -97,6 +97,9 @@ PencilTestPopup {
|
|||
|
||||
#GearButton {
|
||||
qproperty-icon: url('@{img-url}/gear.svg');
|
||||
&::menu-indicator{
|
||||
image:"";
|
||||
}
|
||||
}
|
||||
|
||||
#SubfolderButton {
|
||||
|
|
|
@ -1531,6 +1531,9 @@ ProjectPopup QLabel {
|
|||
#GearButton {
|
||||
qproperty-icon: url('../Default/imgs/black/gear.svg');
|
||||
}
|
||||
#GearButton::menu-indicator {
|
||||
image: "";
|
||||
}
|
||||
#SubfolderButton {
|
||||
qproperty-icon: url('../Default/imgs/black/subfolder.svg');
|
||||
padding-left: 6px;
|
||||
|
|
|
@ -41,7 +41,7 @@ inline float valueToExposure(float value, float filmGamma) {
|
|||
inline float exposureToValue(float exposure, float filmGamma) {
|
||||
return log10(exposure) * filmGamma + 0.5;
|
||||
}
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
//--------------------------------------------
|
||||
// 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,
|
||||
float filmGamma,
|
||||
bool doLightenComp) // not used for now
|
||||
: m_channel(channel),
|
||||
m_layerTileRas(layerTileRas),
|
||||
m_outTileRas(outTileRas),
|
||||
m_tmpAlphaRas(tmpAlphaRas),
|
||||
m_kissfft_comp_iris(kissfft_comp_iris),
|
||||
m_filmGamma(filmGamma),
|
||||
m_finished(false),
|
||||
m_kissfft_comp_in(0),
|
||||
m_kissfft_comp_out(0),
|
||||
m_isTerminated(false),
|
||||
m_doLightenComp(doLightenComp) // not used for now
|
||||
: m_channel(channel)
|
||||
, m_layerTileRas(layerTileRas)
|
||||
, m_outTileRas(outTileRas)
|
||||
, m_tmpAlphaRas(tmpAlphaRas)
|
||||
, m_kissfft_comp_iris(kissfft_comp_iris)
|
||||
, m_filmGamma(filmGamma)
|
||||
, m_finished(false)
|
||||
, m_kissfft_comp_in(0)
|
||||
, m_kissfft_comp_out(0)
|
||||
, m_isTerminated(false)
|
||||
, m_doLightenComp(doLightenComp) // not used for now
|
||||
{}
|
||||
|
||||
bool MyThread::init() {
|
||||
|
@ -446,6 +446,11 @@ void Iwa_BokehFx::doCompute(TTile& tile, double frame,
|
|||
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
||||
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
||||
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,
|
||||
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
||||
|
@ -710,14 +715,14 @@ void Iwa_BokehFx::doCompute(TTile& tile, double frame,
|
|||
}
|
||||
|
||||
/*
|
||||
* What is done in the thread for each RGB channel:
|
||||
* - Convert channel value -> Exposure
|
||||
* - Multiply by alpha channel
|
||||
* - Forward FFT
|
||||
* - Multiply by the iris FFT data
|
||||
* - Backward FFT
|
||||
* - Convert Exposure -> channel value
|
||||
*/
|
||||
* What is done in the thread for each RGB channel:
|
||||
* - Convert channel value -> Exposure
|
||||
* - Multiply by alpha channel
|
||||
* - Forward FFT
|
||||
* - Multiply by the iris FFT data
|
||||
* - Backward FFT
|
||||
* - Convert Exposure -> channel value
|
||||
*/
|
||||
|
||||
waitCount = 0;
|
||||
while (1) {
|
||||
|
@ -852,22 +857,17 @@ void Iwa_BokehFx::convertIris(const float irisSize,
|
|||
// Create the raster for resized iris
|
||||
double2 resizedIrisSize = {std::abs(irisSizeResampleRatio) * irisOrgSize.x,
|
||||
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,
|
||||
(double)filterSize.y - resizedIrisSize.y);
|
||||
|
||||
// Add some adjustment in order to absorb the difference of the cases when the
|
||||
// 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
|
||||
if ((dimOut.lx - filterSize.x) % 2 == 1) {
|
||||
filterSize.x++;
|
||||
isIrisOffset[0] = true;
|
||||
}
|
||||
if ((dimOut.ly - filterSize.y) % 2 == 1) {
|
||||
filterSize.y++;
|
||||
isIrisOffset[1] = true;
|
||||
}
|
||||
if ((dimOut.lx - filterSize.x) % 2 == 1) filterSize.x++;
|
||||
if ((dimOut.ly - filterSize.y) % 2 == 1) filterSize.y++;
|
||||
|
||||
// Terminate if the filter size becomes bigger than the output size.
|
||||
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
|
||||
// resample()
|
||||
TAffine aff;
|
||||
TPointD affOffset((isIrisOffset[0]) ? 0.5 : 1.0,
|
||||
(isIrisOffset[1]) ? 0.5 : 1.0);
|
||||
if (!isIrisOffset[0]) affOffset.x -= resizeOffset.x / 2;
|
||||
if (!isIrisOffset[1]) affOffset.y -= resizeOffset.y / 2;
|
||||
TPointD affOffset(0.5, 0.5);
|
||||
affOffset += TPointD((dimOut.lx % 2 == 1) ? 0.5 : 0.0,
|
||||
(dimOut.ly % 2 == 1) ? 0.5 : 0.0);
|
||||
|
||||
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
||||
aff *= TScale(irisSizeResampleRatio);
|
||||
|
|
|
@ -463,21 +463,15 @@ void Iwa_BokehRefFx::convertIris(const float irisSize, const TRectD& irisBBox,
|
|||
// create the raster for resizing
|
||||
TDimensionD resizedIrisSize(std::abs(irisSizeResampleRatio) * irisOrgSize.lx,
|
||||
std::abs(irisSizeResampleRatio) * irisOrgSize.ly);
|
||||
TDimensionI filterSize((int)std::ceil(resizedIrisSize.lx),
|
||||
(int)std::ceil(resizedIrisSize.ly));
|
||||
// add 1 pixel margins to all sides
|
||||
TDimensionI filterSize((int)std::ceil(resizedIrisSize.lx) + 2,
|
||||
(int)std::ceil(resizedIrisSize.ly) + 2);
|
||||
TPointD resizeOffset((double)filterSize.lx - resizedIrisSize.lx,
|
||||
(double)filterSize.ly - resizedIrisSize.ly);
|
||||
|
||||
bool isIrisOffset[2] = {false, false};
|
||||
// iris shape must be exactly at the center of the image
|
||||
if ((dimOut.lx - filterSize.lx) % 2 == 1) {
|
||||
filterSize.lx++;
|
||||
isIrisOffset[0] = true;
|
||||
}
|
||||
if ((dimOut.ly - filterSize.ly) % 2 == 1) {
|
||||
filterSize.ly++;
|
||||
isIrisOffset[1] = true;
|
||||
}
|
||||
if ((dimOut.lx - filterSize.lx) % 2 == 1) filterSize.lx++;
|
||||
if ((dimOut.ly - filterSize.ly) % 2 == 1) filterSize.ly++;
|
||||
|
||||
// if the filter size becomes larger than the output size, return
|
||||
if (filterSize.lx > dimOut.lx || filterSize.ly > dimOut.ly) {
|
||||
|
@ -491,10 +485,9 @@ void Iwa_BokehRefFx::convertIris(const float irisSize, const TRectD& irisBBox,
|
|||
|
||||
// offset
|
||||
TAffine aff;
|
||||
TPointD affOffset((isIrisOffset[0]) ? 0.5 : 1.0,
|
||||
(isIrisOffset[1]) ? 0.5 : 1.0);
|
||||
if (!isIrisOffset[0]) affOffset.x -= resizeOffset.x / 2;
|
||||
if (!isIrisOffset[1]) affOffset.y -= resizeOffset.y / 2;
|
||||
TPointD affOffset(0.5, 0.5);
|
||||
affOffset += TPointD((dimOut.lx % 2 == 1) ? 0.5 : 0.0,
|
||||
(dimOut.ly % 2 == 1) ? 0.5 : 0.0);
|
||||
|
||||
aff = TTranslation(resizedIris->getCenterD() + affOffset);
|
||||
aff *= TScale(irisSizeResampleRatio);
|
||||
|
@ -924,6 +917,11 @@ void Iwa_BokehRefFx::doCompute(TTile& tile, double frame,
|
|||
if (dimOut.lx < 10000 && dimOut.ly < 10000) {
|
||||
int new_x = kiss_fft_next_fast_size(dimOut.lx);
|
||||
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,
|
||||
static_cast<double>(new_y - dimOut.ly) / 2.0);
|
||||
|
|
|
@ -13,7 +13,6 @@ set(MOC_HEADERS
|
|||
boardsettingspopup.h
|
||||
brightnessandcontrastpopup.h
|
||||
cachefxcommand.h
|
||||
cameracapturelevelcontrol.h
|
||||
camerasettingspopup.h
|
||||
canvassizepopup.h
|
||||
castviewer.h
|
||||
|
@ -69,7 +68,6 @@ set(MOC_HEADERS
|
|||
outputsettingspopup.h
|
||||
overwritepopup.h
|
||||
pane.h
|
||||
penciltestpopup.h
|
||||
pltgizmopopup.h
|
||||
preferencespopup.h
|
||||
previewer.h
|
||||
|
@ -124,6 +122,14 @@ set(MOC_HEADERS
|
|||
xdtsimportpopup.h
|
||||
../stopmotion/stopmotion.h
|
||||
../stopmotion/stopmotioncontroller.h
|
||||
cameracapturelevelcontrol.h
|
||||
penciltestpopup.h
|
||||
)
|
||||
else()
|
||||
set(MOC_HEADERS
|
||||
${MOC_HEADERS}
|
||||
cameracapturelevelcontrol_qt.h
|
||||
penciltestpopup_qt.h
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
|
@ -334,11 +340,9 @@ set(SOURCES
|
|||
comboviewerpane.cpp
|
||||
historypane.cpp
|
||||
cleanupsettingspane.cpp
|
||||
penciltestpopup.cpp
|
||||
audiorecordingpopup.cpp
|
||||
locatorpopup.cpp
|
||||
styleshortcutswitchablepanel.cpp
|
||||
cameracapturelevelcontrol.cpp
|
||||
reframepopup.cpp
|
||||
autoinputcellnumberpopup.cpp
|
||||
colormodelbehaviorpopup.cpp
|
||||
|
@ -354,6 +358,14 @@ set(SOURCES
|
|||
predict3d.cpp
|
||||
../stopmotion/stopmotion.cpp
|
||||
../stopmotion/stopmotioncontroller.cpp
|
||||
cameracapturelevelcontrol.cpp
|
||||
penciltestpopup.cpp
|
||||
)
|
||||
else()
|
||||
set(SOURCES
|
||||
${SOURCES}
|
||||
cameracapturelevelcontrol_qt.cpp
|
||||
penciltestpopup_qt.cpp
|
||||
)
|
||||
|
||||
add_translation(toonz ${HEADERS} ${SOURCES})
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
#include "menubarcommandids.h"
|
||||
#include "cellselection.h"
|
||||
#include "columnselection.h"
|
||||
#include "penciltestpopup.h" // for FrameNumberLineEdit
|
||||
|
||||
#ifdef WITH_STOPMOTION
|
||||
#include "penciltestpopup.h"
|
||||
#else
|
||||
#include "penciltestpopup_qt.h"
|
||||
#endif
|
||||
|
||||
// TnzQt includes
|
||||
#include "toonzqt/intfield.h"
|
||||
|
@ -31,7 +36,6 @@
|
|||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
class AutoInputCellNumberUndo final : public TUndo {
|
||||
int m_increment, m_interval, m_step, m_repeat;
|
||||
int m_from, m_to;
|
||||
|
@ -64,7 +68,7 @@ public:
|
|||
|
||||
int rowsCount() { return m_rowsCount; }
|
||||
};
|
||||
};
|
||||
}; // namespace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// executing this on column selection, set r1 = -1.
|
||||
|
@ -273,7 +277,7 @@ AutoInputCellNumberPopup::AutoInputCellNumberPopup()
|
|||
bool ret = true;
|
||||
ret = ret && connect(m_overwriteBtn, SIGNAL(clicked()), this,
|
||||
SLOT(onOverwritePressed()));
|
||||
ret = ret &&
|
||||
ret = ret &&
|
||||
connect(m_insertBtn, SIGNAL(clicked()), this, SLOT(onInsertPressed()));
|
||||
ret = ret && connect(cancelBtn, SIGNAL(clicked()), this, SLOT(close()));
|
||||
assert(ret);
|
||||
|
|
|
@ -50,12 +50,12 @@ void drawSliderHandle(QPoint pos, QPainter& p, QColor color, bool selected) {
|
|||
p.drawConvexPolygon(points, 5);
|
||||
p.resetTransform();
|
||||
}
|
||||
};
|
||||
}; // namespace
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
||||
: QFrame(parent)
|
||||
, m_histogramCue(false)
|
||||
//, m_histogramCue(false)
|
||||
, m_currentItem(None)
|
||||
, m_black(0)
|
||||
, m_white(255)
|
||||
|
@ -72,29 +72,27 @@ CameraCaptureLevelHistogram::CameraCaptureLevelHistogram(QWidget* parent)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CameraCaptureLevelHistogram::updateHistogram(QImage& image) {
|
||||
// obtain histogram only when clicked
|
||||
if (!m_histogramCue) return;
|
||||
void CameraCaptureLevelHistogram::updateHistogram(cv::Mat& image) {
|
||||
cv::Mat gray, hist;
|
||||
cv::cvtColor(image, gray, cv::COLOR_RGB2GRAY);
|
||||
|
||||
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;
|
||||
const int hdims[] = {256}; // size of histogram
|
||||
const float hranges[] = {0, 256};
|
||||
const float* ranges[] = {hranges}; // min and max values for each bin
|
||||
double max_val = .0;
|
||||
|
||||
cv::calcHist(&gray, 1, 0, cv::Mat(), hist, 1, hdims, ranges);
|
||||
// obtain the maximum value
|
||||
cv::minMaxLoc(hist, 0, &max_val);
|
||||
// scaling
|
||||
hist = hist * (max_val ? HISTOGRAM_HEIGHT / max_val : 0.);
|
||||
|
||||
float* histVal = hist.ptr<float>(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;
|
||||
m_histogramData[c] = int(histVal[c]);
|
||||
}
|
||||
histogramObtained = true;
|
||||
update();
|
||||
m_histogramCue = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -106,7 +104,7 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
|||
|
||||
// draw histogram
|
||||
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));
|
||||
|
||||
if (histogramObtained) {
|
||||
|
@ -117,10 +115,6 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
|||
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
|
||||
|
@ -147,10 +141,6 @@ void CameraCaptureLevelHistogram::paintEvent(QPaintEvent* event) {
|
|||
|
||||
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)
|
||||
|
@ -168,7 +158,7 @@ void CameraCaptureLevelHistogram::mousePressEvent(QMouseEvent* event) {
|
|||
void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
||||
QPoint pos = event->pos();
|
||||
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;
|
||||
bool changed = false;
|
||||
|
@ -185,7 +175,7 @@ void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
|||
if (hPos < m_black + 1)
|
||||
hPos = m_black + 1;
|
||||
else if (hPos > m_white - 1)
|
||||
hPos = m_white - 1;
|
||||
hPos = m_white - 1;
|
||||
float gamma = hPosToGamma(hPos, m_black, m_white);
|
||||
if (gamma != m_gamma) {
|
||||
m_gamma = gamma;
|
||||
|
@ -223,8 +213,7 @@ void CameraCaptureLevelHistogram::mouseMoveEvent(QMouseEvent* event) {
|
|||
setToolTip("");
|
||||
QRect histoRect(5, 1, 256, HISTOGRAM_HEIGHT);
|
||||
if (histoRect.contains(pos)) {
|
||||
setToolTip(tr("Click to Update Histogram"));
|
||||
m_currentItem = Histogram;
|
||||
// do nothing
|
||||
} else {
|
||||
// slider handles
|
||||
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_thresholdFld = new IntLineEdit(this, m_histogram->threshold(), 0, 255);
|
||||
m_gammaFld = new DoubleLineEdit(this, m_histogram->gamma());
|
||||
m_lut = cv::Mat(1, 256, CV_8U);
|
||||
|
||||
m_blackFld->setToolTip(tr("Black Point Value"));
|
||||
m_whiteFld->setToolTip(tr("White Point Value"));
|
||||
|
@ -330,6 +320,10 @@ CameraCaptureLevelControl::CameraCaptureLevelControl(QWidget* parent)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CameraCaptureLevelControl::onHistogramValueChanged(int itemId) {
|
||||
if (itemId == CameraCaptureLevelHistogram::ThresholdSlider) {
|
||||
m_thresholdFld->setValue(m_histogram->threshold());
|
||||
return;
|
||||
}
|
||||
if (itemId == CameraCaptureLevelHistogram::BlackSlider) {
|
||||
m_blackFld->setValue(m_histogram->black());
|
||||
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);
|
||||
} else if (itemId == CameraCaptureLevelHistogram::GammaSlider) {
|
||||
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);
|
||||
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 <QVector>
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
namespace DVGui {
|
||||
class IntLineEdit;
|
||||
class DoubleLineEdit;
|
||||
}
|
||||
} // namespace DVGui
|
||||
//=============================================================================
|
||||
// CameraCaptureLevelHistogram
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -22,15 +23,12 @@ public:
|
|||
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;
|
||||
|
@ -42,7 +40,7 @@ private:
|
|||
public:
|
||||
CameraCaptureLevelHistogram(QWidget* parent = 0);
|
||||
|
||||
void updateHistogram(QImage& image);
|
||||
void updateHistogram(cv::Mat& image);
|
||||
|
||||
int black() { return m_black; }
|
||||
int white() { return m_white; }
|
||||
|
@ -78,19 +76,18 @@ class CameraCaptureLevelControl : public QFrame {
|
|||
CameraCaptureLevelHistogram* m_histogram;
|
||||
DVGui::IntLineEdit *m_blackFld, *m_whiteFld, *m_thresholdFld;
|
||||
DVGui::DoubleLineEdit* m_gammaFld;
|
||||
cv::Mat m_lut;
|
||||
|
||||
void computeLut();
|
||||
|
||||
public:
|
||||
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 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(); }
|
||||
void adjustLevel(cv::Mat& image);
|
||||
void binarize(cv::Mat& image);
|
||||
|
||||
protected slots:
|
||||
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"
|
||||
|
||||
#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
|
||||
#include "tapp.h"
|
||||
#include "menubarcommandids.h"
|
||||
|
@ -87,6 +99,10 @@ TEnv::StringVar CamCapCameraName("CamCapCameraName", "");
|
|||
TEnv::StringVar CamCapCameraResolution("CamCapCameraResolution", "");
|
||||
// Whether to open save-in popup on launch
|
||||
TEnv::IntVar CamCapOpenSaveInPopupOnLaunch("CamCapOpenSaveInPopupOnLaunch", 0);
|
||||
TEnv::IntVar CamCapUseMjpg("CamCapUseMjpg", 1);
|
||||
#ifdef _WIN32
|
||||
TEnv::IntVar CamCapUseDirectShow("CamCapUseDirectShow", 1);
|
||||
#endif
|
||||
// SaveInFolderPopup settings
|
||||
TEnv::StringVar CamCapSaveInParentFolder("CamCapSaveInParentFolder", "");
|
||||
TEnv::IntVar CamCapSaveInPopupSubFolder("CamCapSaveInPopupSubFolder", 0);
|
||||
|
@ -118,7 +134,9 @@ void convertImageToRaster(TRaster32P dstRas, const QImage& srcImg) {
|
|||
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;
|
||||
// first, make the reduction table
|
||||
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));
|
||||
}
|
||||
// then, compute for all pixels
|
||||
int lx = srcImg.width();
|
||||
int ly = srcImg.height();
|
||||
for (int j = 0; j < ly; j++) {
|
||||
// TPixel32 * pix = ras->pixels(j);
|
||||
QRgb* pix = (QRgb*)srcImg.scanLine(j);
|
||||
QRgb* bgPix = (QRgb*)bgImg.scanLine(j);
|
||||
for (int i = 0; i < lx; i++, pix++, bgPix++) {
|
||||
*pix = qRgb(std::min(255, qRed(*pix) + reductionAmount[qRed(*bgPix)]),
|
||||
std::min(255, qGreen(*pix) + reductionAmount[qGreen(*bgPix)]),
|
||||
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;
|
||||
int lx = srcImg.cols;
|
||||
int ly = srcImg.rows;
|
||||
for (int j = 0; j < srcImg.rows; j++) {
|
||||
cv::Vec3b* pix = srcImg.ptr<cv::Vec3b>(j);
|
||||
cv::Vec3b* bgPix = bgImg.ptr<cv::Vec3b>(j);
|
||||
for (int i = 0; i < srcImg.cols; i++, pix++, bgPix++) {
|
||||
*pix = cv::Vec3b(std::min(255, (*pix)[0] + reductionAmount[(*bgPix)[0]]),
|
||||
std::min(255, (*pix)[1] + reductionAmount[(*bgPix)[1]]),
|
||||
std::min(255, (*pix)[2] + reductionAmount[(*bgPix)[2]]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
: QWidget(parent)
|
||||
, m_previousImage(QImage())
|
||||
, m_surface(0)
|
||||
, m_showOnionSkin(false)
|
||||
, m_onionOpacity(128)
|
||||
, m_upsideDown(false)
|
||||
|
@ -604,44 +412,21 @@ MyVideoWidget::MyVideoWidget(QWidget* parent)
|
|||
, m_subCameraRect(QRect()) {
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
m_surface = new MyVideoSurface(this);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
MyVideoWidget::~MyVideoWidget() { delete m_surface; }
|
||||
|
||||
QSize MyVideoWidget::sizeHint() const {
|
||||
return m_surface->surfaceFormat().sizeHint();
|
||||
}
|
||||
|
||||
void MyVideoWidget::paintEvent(QPaintEvent* event) {
|
||||
QPainter p(this);
|
||||
|
||||
p.fillRect(rect(), Qt::black);
|
||||
|
||||
if (m_surface->isActive()) {
|
||||
const QRect videoRect = m_surface->videoRect();
|
||||
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_image.isNull()) {
|
||||
p.drawImage(m_targetRect, m_image);
|
||||
|
||||
if (m_showOnionSkin && m_onionOpacity > 0.0f && !m_previousImage.isNull() &&
|
||||
m_previousImage.size() == m_image.size()) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -669,12 +454,23 @@ void MyVideoWidget::paintEvent(QPaintEvent* event) {
|
|||
|
||||
void MyVideoWidget::resizeEvent(QResizeEvent* 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) {
|
||||
QSize frameSize = m_surface->surfaceFormat().frameSize();
|
||||
QSize frameSize = m_image.size();
|
||||
assert(frameSize == size.expandedTo(frameSize));
|
||||
|
||||
m_subCameraRect.setSize(size);
|
||||
|
@ -698,7 +494,7 @@ void MyVideoWidget::drawSubCamera(QPainter& p) {
|
|||
p.drawRect(handleRect);
|
||||
};
|
||||
|
||||
QRect vidSubRect = m_surface->transform().mapRect(m_subCameraRect);
|
||||
QRect vidSubRect = m_S2V_Transform.mapRect(m_subCameraRect);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
drawSubFrameLine(HandleLeft, vidSubRect.topLeft(), vidSubRect.bottomLeft());
|
||||
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 (!m_surface->isActive() || m_subCameraRect.isNull()) return;
|
||||
if (m_image.isNull() || m_subCameraRect.isNull()) return;
|
||||
|
||||
// with no mouse button, update the active handles
|
||||
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;
|
||||
if (!vidSubRect.adjusted(-d, -d, d, d).contains(event->pos()))
|
||||
m_activeSubHandle = HandleNone;
|
||||
|
@ -795,7 +591,7 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
|||
int minimumSize = 100;
|
||||
|
||||
QPoint offset =
|
||||
m_surface->transform().inverted().map(event->pos()) - m_dragStartPos;
|
||||
m_S2V_Transform.inverted().map(event->pos()) - m_dragStartPos;
|
||||
if (m_activeSubHandle >= HandleTopLeft &&
|
||||
m_activeSubHandle <= HandleBottomRight) {
|
||||
QSize offsetSize = m_preSubCameraRect.size();
|
||||
|
@ -808,7 +604,7 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
|||
m_activeSubHandle == HandleTopRight)
|
||||
offset.rx() *= -1;
|
||||
}
|
||||
QSize camSize = m_surface->surfaceFormat().sizeHint();
|
||||
QSize camSize = m_image.size();
|
||||
|
||||
if (m_activeSubHandle == HandleFrame) {
|
||||
clampPoint(offset, -m_preSubCameraRect.left(),
|
||||
|
@ -855,13 +651,13 @@ void MyVideoWidget::mouseMoveEvent(QMouseEvent* event) {
|
|||
void MyVideoWidget::mousePressEvent(QMouseEvent* event) {
|
||||
// if the sub camera is not active, do nothing and return
|
||||
// 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)
|
||||
return;
|
||||
|
||||
// record the original sub camera size
|
||||
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
|
||||
emit stopCamera();
|
||||
|
@ -870,7 +666,7 @@ void MyVideoWidget::mousePressEvent(QMouseEvent* event) {
|
|||
void MyVideoWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
// if the sub camera is not active, do nothing and return
|
||||
// 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)
|
||||
return;
|
||||
|
||||
|
@ -1421,7 +1217,12 @@ PencilTestPopup::PencilTestPopup()
|
|||
: Dialog(0, false, false, "PencilTest")
|
||||
, m_currentCamera(NULL)
|
||||
, m_captureWhiteBGCue(false)
|
||||
, m_captureCue(false) {
|
||||
, m_captureCue(false)
|
||||
, m_useMjpg(CamCapUseMjpg != 0)
|
||||
#ifdef _WIN32
|
||||
, m_useDirectShow(CamCapUseDirectShow != 0)
|
||||
#endif
|
||||
{
|
||||
setWindowTitle(tr("Camera Capture"));
|
||||
|
||||
// add maximize button to the dialog
|
||||
|
@ -1476,15 +1277,12 @@ PencilTestPopup::PencilTestPopup()
|
|||
m_timerIntervalFld = new IntField(this);
|
||||
m_captureTimer = new QTimer(this);
|
||||
m_countdownTimer = new QTimer(this);
|
||||
m_timer = new QTimer(this);
|
||||
|
||||
m_captureButton = new QPushButton(tr("Capture\n[Return key]"), this);
|
||||
QPushButton* closeButton = new QPushButton(tr("Close"), this);
|
||||
|
||||
#ifdef _WIN32
|
||||
m_captureFilterSettingsBtn = new QPushButton(this);
|
||||
#else
|
||||
m_captureFilterSettingsBtn = 0;
|
||||
#endif
|
||||
|
||||
QPushButton* subfolderButton = new QPushButton(tr("Subfolder"), this);
|
||||
|
||||
|
@ -1543,13 +1341,11 @@ PencilTestPopup::PencilTestPopup()
|
|||
m_captureButton->setIcon(style.standardIcon(QStyle::SP_DialogOkButton));
|
||||
m_captureButton->setIconSize(QSize(30, 30));
|
||||
|
||||
if (m_captureFilterSettingsBtn) {
|
||||
m_captureFilterSettingsBtn->setObjectName("GearButton");
|
||||
m_captureFilterSettingsBtn->setFixedSize(23, 23);
|
||||
m_captureFilterSettingsBtn->setIconSize(QSize(15, 15));
|
||||
m_captureFilterSettingsBtn->setToolTip(
|
||||
tr("Video Capture Filter Settings..."));
|
||||
}
|
||||
m_captureFilterSettingsBtn->setObjectName("GearButton");
|
||||
m_captureFilterSettingsBtn->setFixedSize(23, 23);
|
||||
m_captureFilterSettingsBtn->setIconSize(QSize(15, 15));
|
||||
m_captureFilterSettingsBtn->setToolTip(tr("Options"));
|
||||
m_captureFilterSettingsBtn->setMenu(createOptionsMenu());
|
||||
|
||||
subfolderButton->setObjectName("SubfolderButton");
|
||||
subfolderButton->setIconSize(QSize(15, 15));
|
||||
|
@ -1746,13 +1542,13 @@ PencilTestPopup::PencilTestPopup()
|
|||
SLOT(refreshCameraList()));
|
||||
ret = ret && connect(m_cameraListCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(onCameraListComboActivated(int)));
|
||||
ret = ret && connect(m_resolutionCombo, SIGNAL(activated(const QString&)),
|
||||
this, SLOT(onResolutionComboActivated(const QString&)));
|
||||
ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this,
|
||||
ret = ret && connect(m_resolutionCombo, SIGNAL(activated(int)), this,
|
||||
SLOT(onResolutionComboActivated()));
|
||||
ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this,
|
||||
SLOT(onFileFormatOptionButtonPressed()));
|
||||
ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this,
|
||||
ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this,
|
||||
SLOT(onLevelNameEdited()));
|
||||
ret = ret &&
|
||||
ret = ret &&
|
||||
connect(nextLevelButton, SIGNAL(pressed()), this, SLOT(onNextName()));
|
||||
ret = ret && connect(m_previousLevelButton, SIGNAL(pressed()), this,
|
||||
SLOT(onPreviousName()));
|
||||
|
@ -1778,9 +1574,6 @@ PencilTestPopup::PencilTestPopup()
|
|||
ret = ret && connect(closeButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
ret = ret && connect(m_captureButton, SIGNAL(clicked(bool)), this,
|
||||
SLOT(onCaptureButtonClicked(bool)));
|
||||
if (m_captureFilterSettingsBtn)
|
||||
ret = ret && connect(m_captureFilterSettingsBtn, SIGNAL(pressed()), this,
|
||||
SLOT(onCaptureFilterSettingsBtnPressed()));
|
||||
ret = ret && connect(subfolderButton, SIGNAL(clicked(bool)), this,
|
||||
SLOT(openSaveInFolderPopup()));
|
||||
ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this,
|
||||
|
@ -1799,15 +1592,10 @@ PencilTestPopup::PencilTestPopup()
|
|||
SLOT(onSubCameraSizeEdited()));
|
||||
ret = ret && connect(m_subHeightFld, SIGNAL(editingFinished()), this,
|
||||
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,
|
||||
SLOT(onSubCameraResized(bool)));
|
||||
|
||||
ret = ret && connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
|
||||
assert(ret);
|
||||
|
||||
refreshCameraList();
|
||||
|
@ -1824,7 +1612,7 @@ PencilTestPopup::PencilTestPopup()
|
|||
int startupResolutionIndex = m_resolutionCombo->findText(resStr);
|
||||
if (startupResolutionIndex >= 0) {
|
||||
m_resolutionCombo->setCurrentIndex(startupResolutionIndex);
|
||||
onResolutionComboActivated(resStr);
|
||||
onResolutionComboActivated();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1833,14 +1621,45 @@ PencilTestPopup::PencilTestPopup()
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PencilTestPopup::~PencilTestPopup() {
|
||||
if (m_currentCamera) {
|
||||
if (m_currentCamera->state() == QCamera::ActiveState)
|
||||
m_currentCamera->stop();
|
||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
||||
m_currentCamera->unload();
|
||||
delete m_currentCamera;
|
||||
}
|
||||
PencilTestPopup::~PencilTestPopup() { m_cvWebcam.release(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QMenu* PencilTestPopup::createOptionsMenu() {
|
||||
QMenu* menu = new QMenu();
|
||||
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();
|
||||
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 (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_videoWidget->setImage(QImage());
|
||||
// update env
|
||||
|
@ -1894,9 +1709,6 @@ void PencilTestPopup::onCameraListComboActivated(int comboIndex) {
|
|||
// in case the camera is not changed (just click the combobox)
|
||||
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_deviceName = cameras.at(index).deviceName();
|
||||
|
||||
|
@ -1907,63 +1719,46 @@ void PencilTestPopup::onCameraListComboActivated(int comboIndex) {
|
|||
m_resolutionCombo->clear();
|
||||
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(
|
||||
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()) {
|
||||
// select the largest available resolution
|
||||
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_timer->start(40);
|
||||
// update env
|
||||
CamCapCameraName = m_cameraListCombo->itemText(comboIndex).toStdString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PencilTestPopup::onResolutionComboActivated(const QString& itemText) {
|
||||
// resolution is written in the itemText with the format "<width> x <height>"
|
||||
// (e.g. "800 x 600")
|
||||
QStringList texts = itemText.split(' ');
|
||||
// the splited text must be "<width>" "x" and "<height>"
|
||||
if (texts.size() != 3) return;
|
||||
void PencilTestPopup::onResolutionComboActivated() {
|
||||
m_cvWebcam.release();
|
||||
if (m_timer->isActive()) m_timer->stop();
|
||||
|
||||
#ifndef MACOSX
|
||||
m_currentCamera->stop();
|
||||
m_currentCamera->unload();
|
||||
#endif
|
||||
QSize newResolution = m_resolutionCombo->currentData().toSize();
|
||||
|
||||
QCameraViewfinderSettings settings = m_currentCamera->viewfinderSettings();
|
||||
QSize newResolution(texts[0].toInt(), texts[2].toInt());
|
||||
settings.setResolution(newResolution);
|
||||
m_currentCamera->setViewfinderSettings(settings);
|
||||
if (!newResolution.isValid()) return;
|
||||
if (newResolution == m_resolution) {
|
||||
m_timer->start(40);
|
||||
return;
|
||||
}
|
||||
|
||||
m_resolution = newResolution;
|
||||
|
||||
// reset white bg
|
||||
m_whiteBGImg = QImage();
|
||||
m_whiteBGImg = cv::Mat();
|
||||
m_bgReductionFld->setDisabled(true);
|
||||
#ifndef MACOSX
|
||||
m_currentCamera->start();
|
||||
#endif
|
||||
m_videoWidget->setImage(QImage());
|
||||
m_videoWidget->computeTransform(m_resolution);
|
||||
|
||||
// update env
|
||||
CamCapCameraResolution = itemText.toStdString();
|
||||
CamCapCameraResolution = m_resolutionCombo->currentText().toStdString();
|
||||
|
||||
refreshFrameInfo();
|
||||
|
||||
|
@ -1982,13 +1777,14 @@ void PencilTestPopup::onResolutionComboActivated(const QString& itemText) {
|
|||
TDimension camres = camera->getRes();
|
||||
newResolution =
|
||||
QSize(camres.lx, camres.ly).scaled(newResolution, Qt::KeepAspectRatio);
|
||||
// newResolution.scale(QSize(res.lx, res.ly), Qt::KeepAspectRatio);
|
||||
m_subWidthFld->setValue(newResolution.width());
|
||||
m_subHeightFld->setValue(newResolution.height());
|
||||
} else {
|
||||
m_subWidthFld->setValue(m_allowedCameraSize.width());
|
||||
m_subHeightFld->setValue(m_allowedCameraSize.height());
|
||||
}
|
||||
|
||||
m_timer->start(40);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -2018,7 +1814,6 @@ void PencilTestPopup::onNextName() {
|
|||
}
|
||||
|
||||
std::wstring levelName = nameCreator->getNext();
|
||||
|
||||
updateLevelNameAndFrame(levelName);
|
||||
}
|
||||
|
||||
|
@ -2125,33 +1920,158 @@ void PencilTestPopup::onColorTypeComboChanged(int index) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PencilTestPopup::onFrameCaptured(QImage& image) {
|
||||
if (!m_videoWidget || image.isNull()) return;
|
||||
void PencilTestPopup::onTimeout() { getWebcamImage(); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
if (m_captureWhiteBGCue) {
|
||||
m_whiteBGImg = image.copy();
|
||||
;
|
||||
m_whiteBGImg = image.clone();
|
||||
m_captureWhiteBGCue = false;
|
||||
m_bgReductionFld->setEnabled(true);
|
||||
}
|
||||
|
||||
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) {
|
||||
#ifndef MACOSX
|
||||
m_currentCamera->stop();
|
||||
#endif
|
||||
m_captureCue = false;
|
||||
|
||||
bool scanBtoT =
|
||||
m_videoWidget->videoSurface()->surfaceFormat().scanLineDirection() ==
|
||||
QVideoSurfaceFormat::BottomToTop;
|
||||
bool upsideDown = m_upsideDownCB->isChecked();
|
||||
|
||||
image = image.mirrored(upsideDown, upsideDown != scanBtoT);
|
||||
|
||||
if (importImage(image)) {
|
||||
m_videoWidget->setPreviousImage(image.copy());
|
||||
if (importImage(qimg)) {
|
||||
m_videoWidget->setPreviousImage(qimg.copy());
|
||||
if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) {
|
||||
int f = m_frameNumberEdit->getValue();
|
||||
if (f % 10 == 0) // next number
|
||||
|
@ -2179,34 +2099,18 @@ void PencilTestPopup::onFrameCaptured(QImage& image) {
|
|||
m_captureButton->setChecked(false);
|
||||
onCaptureButtonClicked(false);
|
||||
}
|
||||
#ifndef MACOSX
|
||||
m_currentCamera->start();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PencilTestPopup::showEvent(QShowEvent* event) {
|
||||
// m_timerId = startTimer(10);
|
||||
|
||||
// if there is another action of which "return" key is assigned as short cut
|
||||
// key,
|
||||
// then release the shortcut key temporary while the popup opens
|
||||
QAction* action = CommandManager::instance()->getActionFromShortcut("Return");
|
||||
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();
|
||||
connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(onSceneSwitched()));
|
||||
connect(sceneHandle, SIGNAL(castChanged()), this, SLOT(refreshFrameInfo()));
|
||||
|
@ -2214,6 +2118,9 @@ void PencilTestPopup::showEvent(QShowEvent* event) {
|
|||
bool tmp_alwaysOverwrite = m_alwaysOverwrite;
|
||||
onSceneSwitched();
|
||||
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");
|
||||
if (action) action->setShortcut(QKeySequence("Return"));
|
||||
|
||||
disconnect(m_videoWidget->videoSurface(), SIGNAL(frameCaptured(QImage&)),
|
||||
this, SLOT(onFrameCaptured(QImage&)));
|
||||
|
||||
// stop interval timer if it is active
|
||||
if (m_timerCB->isChecked() && m_captureButton->isChecked()) {
|
||||
m_captureButton->setChecked(false);
|
||||
onCaptureButtonClicked(false);
|
||||
}
|
||||
|
||||
// release camera
|
||||
if (m_currentCamera) {
|
||||
if (m_currentCamera->state() == QCamera::ActiveState)
|
||||
m_currentCamera->stop();
|
||||
if (m_currentCamera->state() == QCamera::LoadedState)
|
||||
m_currentCamera->unload();
|
||||
}
|
||||
m_cvWebcam.release();
|
||||
if (m_timer->isActive()) m_timer->stop();
|
||||
|
||||
Dialog::hideEvent(event);
|
||||
|
||||
TSceneHandle* sceneHandle = TApp::instance()->getCurrentScene();
|
||||
|
@ -2281,27 +2181,26 @@ bool PencilTestPopup::event(QEvent* event) {
|
|||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PencilTestPopup::processImage(QImage& image) {
|
||||
/* "upside down" is not executed here. It will be done when capturing the
|
||||
* image */
|
||||
void PencilTestPopup::processImage(cv::Mat& image) {
|
||||
// void PencilTestPopup::processImage(QImage& image) {
|
||||
if (m_upsideDownCB->isChecked())
|
||||
cv::flip(image, image, -1); // flip in both directions
|
||||
// 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());
|
||||
}
|
||||
|
||||
// obtain histogram AFTER bg reduction
|
||||
m_camCapLevelControl->updateHistogram(image);
|
||||
|
||||
// change channel
|
||||
if (m_colorTypeCombo->currentIndex() != 0)
|
||||
cv::cvtColor(image, image, cv::COLOR_RGB2GRAY);
|
||||
|
||||
// color and grayscale mode
|
||||
if (m_colorTypeCombo->currentIndex() != 2) {
|
||||
int black, white;
|
||||
float gamma;
|
||||
m_camCapLevelControl->getValues(black, white, gamma);
|
||||
if (black != 0 || white != 255 || gamma != 1.0)
|
||||
onChange(image, black, white, gamma,
|
||||
m_colorTypeCombo->currentIndex() != 0);
|
||||
} else {
|
||||
onChangeBW(image, m_camCapLevelControl->getThreshold());
|
||||
}
|
||||
if (m_colorTypeCombo->currentIndex() != 2)
|
||||
m_camCapLevelControl->adjustLevel(image);
|
||||
else
|
||||
m_camCapLevelControl->binarize(image);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -6,16 +6,17 @@
|
|||
#include "toonzqt/dvdialog.h"
|
||||
#include "toonzqt/lineedit.h"
|
||||
#include "toonz/namebuilder.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
#include <QAbstractVideoSurface>
|
||||
#include <QRunnable>
|
||||
#include <QLineEdit>
|
||||
|
||||
// forward decl.
|
||||
class QCamera;
|
||||
class QCameraImageCapture;
|
||||
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class QSlider;
|
||||
class QCheckBox;
|
||||
class QPushButton;
|
||||
|
@ -36,70 +37,6 @@ class IntLineEdit;
|
|||
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -118,6 +55,8 @@ class MyVideoWidget : public QWidget {
|
|||
QRect m_preSubCameraRect;
|
||||
QPoint m_dragStartPos;
|
||||
|
||||
QRect m_targetRect;
|
||||
QTransform m_S2V_Transform; // surface to video transform
|
||||
enum SUBHANDLE {
|
||||
HandleNone,
|
||||
HandleFrame,
|
||||
|
@ -134,15 +73,11 @@ class MyVideoWidget : public QWidget {
|
|||
|
||||
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; }
|
||||
|
@ -156,6 +91,8 @@ public:
|
|||
void setSubCameraSize(QSize size);
|
||||
QRect subCameraRect() { return m_subCameraRect; }
|
||||
|
||||
void computeTransform(QSize imgSize);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
@ -164,9 +101,6 @@ protected:
|
|||
void mousePressEvent(QMouseEvent* event) override;
|
||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
MyVideoSurface* m_surface;
|
||||
|
||||
protected slots:
|
||||
void onUpsideDownChecked(bool on) { m_upsideDown = on; }
|
||||
|
||||
|
@ -281,6 +215,12 @@ protected slots:
|
|||
class PencilTestPopup : public DVGui::Dialog {
|
||||
Q_OBJECT
|
||||
|
||||
QTimer* m_timer;
|
||||
cv::VideoCapture m_cvWebcam;
|
||||
QSize m_resolution;
|
||||
|
||||
//--------
|
||||
|
||||
QCamera* m_currentCamera;
|
||||
QString m_deviceName;
|
||||
MyVideoWidget* m_videoWidget;
|
||||
|
@ -297,7 +237,7 @@ class PencilTestPopup : public DVGui::Dialog {
|
|||
|
||||
QTimer *m_captureTimer, *m_countdownTimer;
|
||||
|
||||
QImage m_whiteBGImg;
|
||||
cv::Mat m_whiteBGImg;
|
||||
|
||||
// used only for Windows
|
||||
QPushButton* m_captureFilterSettingsBtn;
|
||||
|
@ -317,13 +257,23 @@ class PencilTestPopup : public DVGui::Dialog {
|
|||
bool m_captureWhiteBGCue;
|
||||
bool m_captureCue;
|
||||
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);
|
||||
|
||||
void setToNextNewLevel();
|
||||
void updateLevelNameAndFrame(std::wstring levelName);
|
||||
|
||||
void getWebcamImage();
|
||||
|
||||
QMenu* createOptionsMenu();
|
||||
|
||||
int translateIndex(int camIndex);
|
||||
|
||||
public:
|
||||
PencilTestPopup();
|
||||
~PencilTestPopup();
|
||||
|
@ -338,13 +288,13 @@ protected:
|
|||
protected slots:
|
||||
void refreshCameraList();
|
||||
void onCameraListComboActivated(int index);
|
||||
void onResolutionComboActivated(const QString&);
|
||||
void onResolutionComboActivated();
|
||||
void onFileFormatOptionButtonPressed();
|
||||
void onLevelNameEdited();
|
||||
void onNextName();
|
||||
void onPreviousName();
|
||||
void onColorTypeComboChanged(int index);
|
||||
void onFrameCaptured(QImage& image);
|
||||
void onFrameCaptured(cv::Mat& image);
|
||||
void onCaptureWhiteBGButtonPressed();
|
||||
void onOnionCBToggled(bool);
|
||||
void onLoadImageButtonPressed();
|
||||
|
@ -365,6 +315,7 @@ protected slots:
|
|||
void onSubCameraResized(bool isDragging);
|
||||
void onSubCameraSizeEdited();
|
||||
|
||||
void onTimeout();
|
||||
public slots:
|
||||
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