diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 8829c07..b55a9dd 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -149,6 +149,7 @@ set(MOC_HEADERS penciltestpopup.h locatorpopup.h styleshortcutswitchablepanel.h + cameracapturelevelcontrol.h # Tracker file dummyprocessor.h metnum.h @@ -313,6 +314,7 @@ set(SOURCES audiorecordingpopup.cpp locatorpopup.cpp styleshortcutswitchablepanel.cpp + cameracapturelevelcontrol.cpp # Tracker file dummyprocessor.cpp metnum.cpp diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.cpp b/toonz/sources/toonz/cameracapturelevelcontrol.cpp new file mode 100644 index 0000000..c138596 --- /dev/null +++ b/toonz/sources/toonz/cameracapturelevelcontrol.cpp @@ -0,0 +1,369 @@ +#include "cameracapturelevelcontrol.h" + +#include "toonzqt/intfield.h" +#include "toonzqt/doublefield.h" + +#include +#include +#include +#include +#include +#include + +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(); +} +}; +//----------------------------------------------------------------------------- + +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 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(); +} diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.h b/toonz/sources/toonz/cameracapturelevelcontrol.h new file mode 100644 index 0000000..4254dd7 --- /dev/null +++ b/toonz/sources/toonz/cameracapturelevelcontrol.h @@ -0,0 +1,100 @@ +#pragma once + +#ifndef CAMERA_CAPTURE_LEVEL_CONTROL_H +#define CAMERA_CAPTURE_LEVEL_CONTROL_H + +#include +#include + +namespace DVGui { +class IntLineEdit; +class DoubleLineEdit; +} +//============================================================================= +// 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 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 \ No newline at end of file diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index d83a900..b8b51de 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -7,6 +7,7 @@ #include "filebrowsermodel.h" #include "cellselection.h" #include "toonzqt/tselectionhandle.h" +#include "cameracapturelevelcontrol.h" // TnzQt includes #include "toonzqt/menubarcommand.h" #include "toonzqt/filefield.h" @@ -131,69 +132,40 @@ void bgReduction(QImage& srcImg, QImage& bgImg, int reduction) { } } -// referenced from brightnessandcontrastpopup.cpp -void my_compute_lut(double contrast, double brightness, std::vector& lut) { - const int maxChannelValue = lut.size() - 1; - const double half_maxChannelValueD = 0.5 * maxChannelValue; - const double maxChannelValueD = maxChannelValue; +void my_compute_lut(int black, int white, float gamma, std::vector& lut) { + const int maxChannelValue = lut.size() - 1; + const float half_maxChannelValueF = 0.5f * maxChannelValue; + const float maxChannelValueF = maxChannelValue; - int i; - double value, nvalue, power; + float value; int lutSize = lut.size(); - for (i = 0; i < lutSize; i++) { - value = i / maxChannelValueD; - - // brightness - if (brightness < 0.0) - value = value * (1.0 + brightness); - else - value = value + ((1.0 - value) * brightness); - - // contrast - if (contrast < 0.0) { - if (value > 0.5) - nvalue = 1.0 - value; - else - nvalue = value; - if (nvalue < 0.0) nvalue = 0.0; - nvalue = 0.5 * pow(nvalue * 2.0, (double)(1.0 + contrast)); - if (value > 0.5) - value = 1.0 - nvalue; - else - value = nvalue; - } else { - if (value > 0.5) - nvalue = 1.0 - value; - else - nvalue = value; - if (nvalue < 0.0) nvalue = 0.0; - power = - (contrast == 1.0) ? half_maxChannelValueD : 1.0 / (1.0 - contrast); - nvalue = 0.5 * pow(2.0 * nvalue, power); - if (value > 0.5) - value = 1.0 - nvalue; - else - value = nvalue; + 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] = value * maxChannelValueD; + lut[i] = (int)std::floor(value * maxChannelValueF); } } //----------------------------------------------------------------------------- inline void doPixGray(QRgb* pix, const std::vector& lut) { - int gray = qGray(qRgb(lut[qRed(*pix)], lut[qGreen(*pix)], lut[qBlue(*pix)])); + int gray = lut[qGray(*pix)]; *pix = qRgb(gray, gray, gray); } //----------------------------------------------------------------------------- -inline void doPixBinary(QRgb* pix, const std::vector& lut, - unsigned char threshold) { - int gray = qGray(qRgb(lut[qRed(*pix)], lut[qGreen(*pix)], lut[qBlue(*pix)])); - if ((unsigned char)gray >= threshold) +inline void doPixBinary(QRgb* pix, int threshold) { + int gray = qGray(*pix); + if (gray >= threshold) gray = 255; else gray = 0; @@ -209,34 +181,18 @@ inline void doPix(QRgb* pix, const std::vector& lut) { //----------------------------------------------------------------------------- -void onChange(QImage& img, int contrast, int brightness, bool doGray, - unsigned char threshold = 0) { - double b = brightness / 127.0; - double c = contrast / 127.0; - if (c > 1) c = 1; - if (c < -1) c = -1; - +void onChange(QImage& img, int black, int white, float gamma, bool doGray) { std::vector lut(TPixel32::maxChannelValue + 1); - my_compute_lut(c, b, lut); + my_compute_lut(black, white, gamma, lut); int lx = img.width(), y, ly = img.height(); if (doGray) { - if (threshold == 0) { // Grayscale - for (y = 0; y < ly; ++y) { - QRgb *pix = (QRgb *)img.scanLine(y), *endPix = (QRgb *)(pix + lx); - while (pix < endPix) { - doPixGray(pix, lut); - ++pix; - } - } - } else { // Binary - for (y = 0; y < ly; ++y) { - QRgb *pix = (QRgb *)img.scanLine(y), *endPix = (QRgb *)(pix + lx); - while (pix < endPix) { - doPixBinary(pix, lut, threshold); - ++pix; - } + for (y = 0; y < ly; ++y) { + QRgb *pix = (QRgb *)img.scanLine(y), *endPix = (QRgb *)(pix + lx); + while (pix < endPix) { + doPixGray(pix, lut); + ++pix; } } } else { // color @@ -252,6 +208,19 @@ void onChange(QImage& img, int contrast, int brightness, bool doGray, //----------------------------------------------------------------------------- +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; + } + } +} + +//----------------------------------------------------------------------------- + TPointD getCurrentCameraDpi() { TCamera* camera = TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); @@ -947,10 +916,8 @@ PencilTestPopup::PencilTestPopup() QGroupBox* imageFrame = new QGroupBox(tr("Image adjust"), this); m_colorTypeCombo = new QComboBox(this); - m_thresholdFld = new IntField(this); - m_contrastFld = new IntField(this); - m_brightnessFld = new IntField(this); - m_upsideDownCB = new QCheckBox(tr("Upside down"), this); + m_camCapLevelControl = new CameraCaptureLevelControl(this); + m_upsideDownCB = new QCheckBox(tr("Upside down"), this); m_bgReductionFld = new IntField(this); m_captureWhiteBGButton = new QPushButton(tr("Capture white BG"), this); @@ -993,13 +960,6 @@ PencilTestPopup::PencilTestPopup() imageFrame->setObjectName("CleanupSettingsFrame"); m_colorTypeCombo->addItems({"Color", "Grayscale", "Black & White"}); m_colorTypeCombo->setCurrentIndex(0); - m_thresholdFld->setRange(1, 255); - m_thresholdFld->setValue(128); - m_thresholdFld->setDisabled(true); - m_contrastFld->setRange(-127, 127); - m_contrastFld->setValue(0); - m_brightnessFld->setRange(-127, 127); - m_brightnessFld->setValue(0); m_upsideDownCB->setChecked(false); m_bgReductionFld->setRange(0, 100); @@ -1130,25 +1090,15 @@ PencilTestPopup::PencilTestPopup() Qt::AlignRight); imageLay->addWidget(m_colorTypeCombo, 0, 1); - imageLay->addWidget(new QLabel(tr("Threshold:"), this), 1, 0, - Qt::AlignRight); - imageLay->addWidget(m_thresholdFld, 1, 1, 1, 2); - - imageLay->addWidget(new QLabel(tr("Contrast:"), this), 2, 0, - Qt::AlignRight); - imageLay->addWidget(m_contrastFld, 2, 1, 1, 2); - - imageLay->addWidget(new QLabel(tr("Brightness:"), this), 3, 0, - Qt::AlignRight); - imageLay->addWidget(m_brightnessFld, 3, 1, 1, 2); + imageLay->addWidget(m_camCapLevelControl, 1, 0, 1, 3); - imageLay->addWidget(m_upsideDownCB, 4, 0, 1, 3, Qt::AlignLeft); + imageLay->addWidget(m_upsideDownCB, 2, 0, 1, 3, Qt::AlignLeft); - imageLay->addWidget(new QLabel(tr("BG reduction:"), this), 5, 0, + imageLay->addWidget(new QLabel(tr("BG reduction:"), this), 3, 0, Qt::AlignRight); - imageLay->addWidget(m_bgReductionFld, 5, 1, 1, 2); + imageLay->addWidget(m_bgReductionFld, 3, 1, 1, 2); - imageLay->addWidget(m_captureWhiteBGButton, 6, 0, 1, 3); + imageLay->addWidget(m_captureWhiteBGButton, 4, 0, 1, 3); } imageLay->setColumnStretch(0, 0); imageLay->setColumnStretch(1, 0); @@ -1495,7 +1445,7 @@ void PencilTestPopup::onNextName() { //----------------------------------------------------------------------------- void PencilTestPopup::onColorTypeComboChanged(int index) { - m_thresholdFld->setEnabled(index == 2); + m_camCapLevelControl->setMode(index != 2); } //----------------------------------------------------------------------------- @@ -1622,11 +1572,18 @@ void PencilTestPopup::processImage(QImage& image) { if (!m_whiteBGImg.isNull() && m_bgReductionFld->getValue() != 0) { bgReduction(image, m_whiteBGImg, m_bgReductionFld->getValue()); } - - int threshold = - (m_colorTypeCombo->currentIndex() != 2) ? 0 : m_thresholdFld->getValue(); - onChange(image, m_contrastFld->getValue(), m_brightnessFld->getValue(), - m_colorTypeCombo->currentIndex() != 0, threshold); + // obtain histogram AFTER bg reduction + m_camCapLevelControl->updateHistogram(image); + + // color and grayscale mode + if (m_colorTypeCombo->currentIndex() != 2) { + int black, white; + float gamma; + m_camCapLevelControl->getValues(black, white, gamma); + onChange(image, black, white, gamma, m_colorTypeCombo->currentIndex() != 0); + } else { + onChangeBW(image, m_camCapLevelControl->getThreshold()); + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h index 00aa53f..76e063c 100644 --- a/toonz/sources/toonz/penciltestpopup.h +++ b/toonz/sources/toonz/penciltestpopup.h @@ -28,6 +28,8 @@ class FileField; class IntField; } +class CameraCaptureLevelControl; + //============================================================================= // MyViewFinder //----------------------------------------------------------------------------- @@ -168,8 +170,7 @@ class PencilTestPopup : public DVGui::Dialog { *m_captureButton, *m_loadImageButton; DVGui::FileField* m_saveInFileFld; FrameNumberLineEdit* m_frameNumberEdit; - DVGui::IntField *m_thresholdFld, *m_contrastFld, *m_brightnessFld, - *m_bgReductionFld, *m_onionOpacityFld, *m_timerIntervalFld; + DVGui::IntField *m_bgReductionFld, *m_onionOpacityFld, *m_timerIntervalFld; QTimer *m_captureTimer, *m_countdownTimer; @@ -180,6 +181,8 @@ class PencilTestPopup : public DVGui::Dialog { PencilTestSaveInFolderPopup* m_saveInFolderPopup; + CameraCaptureLevelControl* m_camCapLevelControl; + int m_timerId; QString m_cacheImagePath; bool m_captureWhiteBGCue;