From 21a6b6ba06680141fd2d05e095ee085877ae4c7b Mon Sep 17 00:00:00 2001 From: shun_iwasawa Date: Wed, 29 Jun 2016 16:36:05 +0900 Subject: [PATCH] pencil test popup --- ci-scripts/linux/travis-install.sh | 2 +- stuff/config/loc/日本語/toonz.qm | Bin 177224 -> 180062 bytes stuff/config/qss/gray_048/gray_048.less | 4 + stuff/config/qss/gray_048/gray_048.qss | 3 + stuff/config/qss/gray_048/gray_048_mac.qss | 3 + stuff/config/qss/gray_072/gray_072.less | 4 + stuff/config/qss/gray_072/gray_072.qss | 3 + stuff/config/qss/gray_072/gray_072_mac.qss | 3 + stuff/config/qss/gray_128/gray_128.less | 17 + stuff/config/qss/gray_128/gray_128.qss | 21 + stuff/config/qss/gray_128/gray_128_mac.qss | 21 + .../rooms/StudioGhibli/menubar_template.xml | 2 + .../rooms/StudioGhibli/room1_menubar.xml | 2 + toonz/sources/CMakeLists.txt | 3 +- toonz/sources/common/trop/quickput.cpp | 15 +- toonz/sources/include/tpixelutils.h | 5 +- toonz/sources/toonz/CMakeLists.txt | 8 +- toonz/sources/toonz/mainwindow.cpp | 3 + toonz/sources/toonz/menubarcommandids.h | 1 + toonz/sources/toonz/penciltestpopup.cpp | 993 ++++++++++++++++++ toonz/sources/toonz/penciltestpopup.h | 117 +++ toonz/sources/toonzqt/stylenameeditor.cpp | 2 +- toonz/sources/translations/japanese/toonz.ts | 174 +++ 23 files changed, 1392 insertions(+), 14 deletions(-) create mode 100644 toonz/sources/toonz/penciltestpopup.cpp create mode 100644 toonz/sources/toonz/penciltestpopup.h diff --git a/ci-scripts/linux/travis-install.sh b/ci-scripts/linux/travis-install.sh index a004c7dc..b25bf7f2 100644 --- a/ci-scripts/linux/travis-install.sh +++ b/ci-scripts/linux/travis-install.sh @@ -1,6 +1,6 @@ sudo add-apt-repository --yes ppa:beineri/opt-qt551-trusty sudo apt-get update -sudo apt-get install -y liblzo2-dev liblz4-dev libfreetype6-dev libpng-dev libsdl2-dev libglew-dev freeglut3-dev qt55script libsuperlu3-dev libpng-dev qt55svg qt55tools wget libusb-1.0-0-dev libboost-all-dev liblzma-dev +sudo apt-get install -y liblzo2-dev liblz4-dev libfreetype6-dev libpng-dev libsdl2-dev libglew-dev freeglut3-dev qt55script libsuperlu3-dev libpng-dev qt55svg qt55tools qt55multimedia wget libusb-1.0-0-dev libboost-all-dev liblzma-dev # someone forgot to include liblz4.pc with the package, use the version from xenial, as it only depends on libc wget http://mirrors.kernel.org/ubuntu/pool/main/l/lz4/liblz4-1_0.0~r131-2ubuntu2_amd64.deb -O liblz4.deb wget http://mirrors.kernel.org/ubuntu/pool/main/l/lz4/liblz4-dev_0.0~r131-2ubuntu2_amd64.deb -O liblz4-dev.deb diff --git a/stuff/config/loc/日本語/toonz.qm b/stuff/config/loc/日本語/toonz.qm index 5c6d3cd26c1140e6b096321ac0f024f5a28c3204..50d23e5db0d2a05bbd8f7bfa23442cbfd87a71e9 100644 GIT binary patch delta 16371 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 MI_CameraTest MI_Cleanup + + MI_PencilTest MI_AddFrames diff --git a/stuff/profiles/layouts/rooms/StudioGhibli/room1_menubar.xml b/stuff/profiles/layouts/rooms/StudioGhibli/room1_menubar.xml index 373e4b15..aadc81dd 100644 --- a/stuff/profiles/layouts/rooms/StudioGhibli/room1_menubar.xml +++ b/stuff/profiles/layouts/rooms/StudioGhibli/room1_menubar.xml @@ -25,6 +25,8 @@ MI_Scan MI_SetScanCropbox MI_ResetScanCropbox + + MI_PencilTest MI_CleanupSettings diff --git a/toonz/sources/CMakeLists.txt b/toonz/sources/CMakeLists.txt index a29c4b21..012ce19c 100644 --- a/toonz/sources/CMakeLists.txt +++ b/toonz/sources/CMakeLists.txt @@ -136,7 +136,8 @@ find_package(Qt5 REQUIRED Script Widgets PrintSupport - LinguistTools) + LinguistTools + Multimedia) if(WIN32) include_directories( diff --git a/toonz/sources/common/trop/quickput.cpp b/toonz/sources/common/trop/quickput.cpp index f8900f69..e90c3064 100644 --- a/toonz/sources/common/trop/quickput.cpp +++ b/toonz/sources/common/trop/quickput.cpp @@ -4276,18 +4276,21 @@ void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff, else doQuickPutNoFilter(dn32, up8, aff, colorScale); } else if (dn32 && up32) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)){ if (bilinear) doQuickPutFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); - else + else { doQuickPutNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23, - colorScale, doPremultiply, whiteTransp, firstColumn, - doRasterDarkenBlendedView); + colorScale, doPremultiply, whiteTransp, firstColumn, + doRasterDarkenBlendedView); + } + } else if (bilinear) doQuickPutFilter(dn32, up32, aff); - else + else { doQuickPutNoFilter(dn32, up32, aff, colorScale, doPremultiply, - whiteTransp, firstColumn, doRasterDarkenBlendedView); + whiteTransp, firstColumn, doRasterDarkenBlendedView); + } } else if (dn32 && up64) doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn); else diff --git a/toonz/sources/include/tpixelutils.h b/toonz/sources/include/tpixelutils.h index 7f14af57..f8552cb0 100644 --- a/toonz/sources/include/tpixelutils.h +++ b/toonz/sources/include/tpixelutils.h @@ -125,10 +125,11 @@ DVAPI inline T quickOverPixPremultT(const T &bot, const T &top) { (bot.m == max) ? max : max - (max - bot.m) * (max - top.m) / max); } //------------------------------------------------------------------------------------ -/*-- Viewer上でラスタ素材を「比較暗」合成表示する --*/ +/*-- Show raster images darken-blended on the viewer --*/ template DVAPI inline T quickOverPixDarkenBlendedT(const T &bot, const T &top) { - UINT max = T::maxChannelValue; + UINT max = T::maxChannelValue; + if (bot.m == 0) return top; TUINT32 r = (top.r < bot.r) ? top.r : bot.r; TUINT32 g = (top.g < bot.g) ? top.g : bot.g; TUINT32 b = (top.b < bot.b) ? top.b : bot.b; diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 052c856b..b15498e9 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -138,6 +138,7 @@ set(MOC_HEADERS comboviewerpane.h historypane.h cleanupsettingspane.h + penciltestpopup.h # Tracker file dummyprocessor.h metnum.h @@ -294,6 +295,7 @@ set(SOURCES comboviewerpane.cpp historypane.cpp cleanupsettingspane.cpp + penciltestpopup.cpp # Tracker file dummyprocessor.cpp metnum.cpp @@ -359,7 +361,7 @@ endif() if(WIN32) target_link_libraries(OpenToonz_${VERSION} - Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport + Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia ${GL_LIB} ${GLUT_LIB} tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm) elseif(APPLE) @@ -370,7 +372,7 @@ elseif(APPLE) # 変なところにライブラリ生成するカスども set(EXTRA_LIBS ${EXTRA_LIBS} "$" "$") - target_link_libraries(OpenToonz_${VERSION} Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport ${GL_LIB} ${GLUT_LIB} ${COCOA_LIB} ${EXTRA_LIBS}) + target_link_libraries(OpenToonz_${VERSION} Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia ${GL_LIB} ${GLUT_LIB} ${COCOA_LIB} ${EXTRA_LIBS}) elseif(UNIX) _find_toonz_library(EXTRA_LIBS "tnzcore;tnzbase;toonzlib;colorfx;tnzext;image;sound;toonzqt;tnztools") @@ -379,7 +381,7 @@ elseif(UNIX) set(EXTRA_LIBS ${EXTRA_LIBS} ${Boost_LIBRARIES} ${OPENBLAS_LIB}) - target_link_libraries(OpenToonz_${VERSION} Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport ${GL_LIB} ${GLUT_LIB} ${GLU_LIB} ${EXTRA_LIBS}) + target_link_libraries(OpenToonz_${VERSION} Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia ${GL_LIB} ${GLUT_LIB} ${GLU_LIB} ${EXTRA_LIBS}) endif() if(APPLE) diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 67e17160..3cb54f63 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1650,6 +1650,9 @@ void MainWindow::defineActions() { MenuScanCleanupCommandType); createMenuScanCleanupAction(MI_Cleanup, tr("&Cleanup"), ""); + + createMenuScanCleanupAction(MI_PencilTest, tr("&Pencil Test..."), ""); + createMenuLevelAction(MI_AddFrames, tr("&Add Frames..."), ""); createMenuLevelAction(MI_Renumber, tr("&Renumber..."), ""); createMenuLevelAction(MI_ReplaceLevel, tr("&Replace Level..."), ""); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 8daabe2b..a67dc434 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -308,4 +308,5 @@ #define MI_PreviewFx "MI_PreviewFx" #define MI_About "MI_About" +#define MI_PencilTest "MI_PencilTest" #endif diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp new file mode 100644 index 00000000..ac7dd7f3 --- /dev/null +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -0,0 +1,993 @@ +#include "penciltestpopup.h" + +// Tnz6 includes +#include "tapp.h" +#include "menubarcommandids.h" +#include "formatsettingspopups.h" +#include "filebrowsermodel.h" + +// TnzQt includes +#include "toonzqt/menubarcommand.h" +#include "toonzqt/filefield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/gutil.h" + +// Tnzlib includes +#include "toonz/tproject.h" +#include "toonz/tscenehandle.h" +#include "toonz/toonzscene.h" +#include "toutputproperties.h" +#include "toonz/sceneproperties.h" +#include "toonz/namebuilder.h" +#include "toonz/levelset.h" +#include "toonz/txshleveltypes.h" +#include "toonz/toonzfolders.h" +#include "toonz/tframehandle.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/txsheethandle.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/levelproperties.h" +#include "toonz/tcamera.h" + +// TnzCore includes +#include "tsystem.h" +#include "tpixelutils.h" + +#include + +// Qt includes +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace DVGui; + +namespace { + +void convertImageToRaster(TRaster32P dstRas, const QImage& srcImg) { + dstRas->lock(); + int lx = dstRas->getLx(); + int ly = dstRas->getLy(); + assert(lx == srcImg.width() && ly == srcImg.height()); + for (int j = 0; j < ly; j++) { + TPixel32* dstPix = dstRas->pixels(j); + for (int i = 0; i < lx; i++, dstPix++) { + QRgb srcPix = srcImg.pixel(lx - 1 - i, j); + dstPix->r = qRed(srcPix); + dstPix->g = qGreen(srcPix); + dstPix->b = qBlue(srcPix); + dstPix->m = TPixel32::maxChannelValue; + } + } + dstRas->unlock(); +} + +void bgReduction(QImage& srcImg, QImage& bgImg, int reduction) { + float reductionRatio = (float)reduction / 100.0f; + // first, make the reduction table + std::vector reductionAmount(256); + for (int i = 0; i < reductionAmount.size(); i++) { + 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)])); + } + } +} + +// 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; + + int i; + double value, nvalue, power; + + 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; + } + + lut[i] = value * maxChannelValueD; + } +} + +//----------------------------------------------------------------------------- + +inline void doPixGray(QRgb* pix, const std::vector& lut) { + int gray = qGray(qRgb(lut[qRed(*pix)], lut[qGreen(*pix)], lut[qBlue(*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) + gray = 255; + else + gray = 0; + *pix = qRgb(gray, gray, gray); +} + +//----------------------------------------------------------------------------- + +inline void doPix(QRgb* pix, const std::vector& lut) { + // The captured image MUST be full opaque! + *pix = qRgb(lut[qRed(*pix)], lut[qGreen(*pix)], lut[qBlue(*pix)]); +} + +//----------------------------------------------------------------------------- + +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; + + std::vector lut(TPixel32::maxChannelValue + 1); + my_compute_lut(c, b, 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; + } + } + } + } else { // color + for (y = 0; y < ly; ++y) { + QRgb *pix = (QRgb *)img.scanLine(y), *endPix = (QRgb *)(pix + lx); + while (pix < endPix) { + doPix(pix, lut); + ++pix; + } + } + } +} + +//----------------------------------------------------------------------------- + +TPointD getCurrentCameraDpi() { + TCamera* camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + TDimension res = camera->getRes(); + return TPointD(res.lx / size.lx, res.ly / size.ly); +} + +} // namespace + +//============================================================================= + +MyViewFinder::MyViewFinder(QWidget* parent) + : QFrame(parent) + , m_image(QImage()) + , m_camera(0) + , m_showOnionSkin(false) + , m_onionOpacity(128) + , m_upsideDown(false) {} + +void MyViewFinder::paintEvent(QPaintEvent* event) { + QPainter p(this); + + p.fillRect(rect(), Qt::black); + + if (m_image.isNull()) { + p.setPen(Qt::white); + QFont font = p.font(); + font.setPixelSize(30); + p.setFont(font); + p.drawText(rect(), Qt::AlignCenter, tr("Camera is not available")); + return; + } + + if (m_upsideDown) { + p.translate(m_imageRect.center()); + p.rotate(180); + p.translate(-m_imageRect.center()); + } + + p.drawImage(m_imageRect, m_image); + + if (m_showOnionSkin && m_onionOpacity > 0.0f && !m_previousImage.isNull() && + m_previousImage.size() == m_image.size()) { + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.setPen(Qt::NoPen); + p.setBrush(QBrush(QColor(255, 255, 255, 255 - m_onionOpacity))); + p.drawRect(m_imageRect); + p.setCompositionMode(QPainter::CompositionMode_DestinationOver); + p.drawImage(m_imageRect, m_previousImage); + } +} + +void MyViewFinder::resizeEvent(QResizeEvent* event) { + if (!m_camera) return; + QSize cameraReso = m_camera->viewfinderSettings().resolution(); + double cameraAR = (double)cameraReso.width() / (double)cameraReso.height(); + // in case the camera aspect is wider than this widget + if (cameraAR >= (double)width() / (double)height()) { + m_imageRect.setWidth(width()); + m_imageRect.setHeight((int)((double)width() / cameraAR)); + m_imageRect.moveTo(0, (height() - m_imageRect.height()) / 2); + } + // in case the camera aspect is thinner than this widget + else { + m_imageRect.setHeight(height()); + m_imageRect.setWidth((int)((double)height() * cameraAR)); + m_imageRect.moveTo((width() - m_imageRect.width()) / 2, 0); + } +} + +//============================================================================= + +PencilTestPopup::PencilTestPopup() + : Dialog(TApp::instance()->getMainWindow(), false, false, "PencilTest") + , m_currentCamera(0) + , m_cameraImageCapture(0) + , m_captureWhiteBGCue(false) + , m_captureCue(false) { + setWindowTitle(tr("Pencil Test")); + layout()->setSizeConstraint(QLayout::SetNoConstraint); + + std::wstring dateTime = + QDateTime::currentDateTime().toString("yyMMddhhmmss").toStdWString(); + TFilePath cacheImageFp = ToonzFolder::getCacheRootFolder() + + TFilePath(L"penciltest" + dateTime + L".jpg"); + m_cacheImagePath = cacheImageFp.getQString(); + + m_cameraViewfinder = new MyViewFinder(this); + // CameraViewfinderContainer* cvfContainer = new + // CameraViewfinderContainer(m_cameraViewfinder, this); + + m_cameraListCombo = new QComboBox(this); + QPushButton* refreshCamListButton = new QPushButton(tr("Refresh"), this); + m_resolutionCombo = new QComboBox(this); + + QGroupBox* fileFrame = new QGroupBox(tr("File"), this); + m_levelNameEdit = new QLineEdit(this); + m_frameNumberEdit = new IntLineEdit(this, 1, 1, INT_MAX, 4); + m_fileTypeCombo = new QComboBox(this); + m_fileFormatOptionButton = new QPushButton(tr("Options"), this); + m_saveInFileFld = new FileField( + 0, QString("+%1").arg(QString::fromStdString(TProject::Extras))); + QToolButton* nextLevelButton = new QToolButton(this); + + 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_bgReductionFld = new IntField(this); + m_captureWhiteBGButton = new QPushButton(tr("Capture white BG"), this); + + QGroupBox* displayFrame = new QGroupBox(tr("Display"), this); + m_onionSkinCB = new QCheckBox(tr("Show onion skin"), this); + m_onionOpacityFld = new IntField(this); + + QPushButton* captureButton = new QPushButton(tr("Capture"), this); + QPushButton* closeButton = new QPushButton(tr("Close"), this); + //---- + + m_resolutionCombo->setMaximumWidth(fontMetrics().width("0000 x 0000") + 25); + m_fileTypeCombo->addItems({"jpg", "png", "tga", "tif"}); + m_fileTypeCombo->setCurrentIndex(1); + + fileFrame->setObjectName("CleanupSettingsFrame"); + // Exclude all character which cannot fit in a filepath (Win). + // Dots are also prohibited since they are internally managed by Toonz. + QRegExp rx("[^\\\\/:?*.\"<>|]+"); + m_levelNameEdit->setValidator(new QRegExpValidator(rx, this)); + m_levelNameEdit->setObjectName("LargeSizedText"); + m_frameNumberEdit->setObjectName("LargeSizedText"); + nextLevelButton->setFixedSize(24, 24); + nextLevelButton->setArrowType(Qt::RightArrow); + nextLevelButton->setToolTip(tr("Next Level")); + + 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); + m_bgReductionFld->setValue(0); + m_bgReductionFld->setDisabled(true); + + displayFrame->setObjectName("CleanupSettingsFrame"); + m_onionSkinCB->setChecked(false); + m_onionOpacityFld->setRange(1, 100); + m_onionOpacityFld->setValue(50); + m_onionOpacityFld->setDisabled(true); + + captureButton->setObjectName("LargeSizedText"); + captureButton->setFixedHeight(80); + + //---- layout ---- + QHBoxLayout* mainLay = new QHBoxLayout(); + mainLay->setMargin(0); + mainLay->setSpacing(10); + { + QVBoxLayout* leftLay = new QVBoxLayout(); + leftLay->setMargin(5); + leftLay->setSpacing(10); + { + QHBoxLayout* camLay = new QHBoxLayout(); + camLay->setMargin(0); + camLay->setSpacing(3); + { + camLay->addWidget(new QLabel(tr("Camera:"), this), 0); + camLay->addWidget(m_cameraListCombo, 1); + camLay->addWidget(refreshCamListButton, 0); + camLay->addSpacing(10); + camLay->addWidget(new QLabel(tr("Resolution:"), this), 0); + camLay->addWidget(m_resolutionCombo, 1); + camLay->addStretch(0); + } + leftLay->addLayout(camLay, 0); + leftLay->addWidget(m_cameraViewfinder, 1); + } + mainLay->addLayout(leftLay, 1); + + QVBoxLayout* rightLay = new QVBoxLayout(); + rightLay->setMargin(0); + rightLay->setSpacing(5); + { + QVBoxLayout* fileLay = new QVBoxLayout(); + fileLay->setMargin(10); + fileLay->setSpacing(10); + { + QGridLayout* levelLay = new QGridLayout(); + levelLay->setMargin(0); + levelLay->setHorizontalSpacing(3); + levelLay->setVerticalSpacing(10); + { + levelLay->addWidget(new QLabel(tr("Name:"), this), 0, 0, + Qt::AlignRight); + levelLay->addWidget(m_levelNameEdit, 0, 1); + levelLay->addWidget(nextLevelButton, 0, 2); + + levelLay->addWidget(new QLabel(tr("Frame:"), this), 1, 0, + Qt::AlignRight); + levelLay->addWidget(m_frameNumberEdit, 1, 1); + } + levelLay->setColumnStretch(0, 0); + levelLay->setColumnStretch(1, 1); + levelLay->setColumnStretch(2, 0); + fileLay->addLayout(levelLay, 0); + + QHBoxLayout* fileTypeLay = new QHBoxLayout(); + fileTypeLay->setMargin(0); + fileTypeLay->setSpacing(3); + { + fileTypeLay->addWidget(new QLabel(tr("File Type:"), this), 0); + fileTypeLay->addWidget(m_fileTypeCombo, 1); + fileTypeLay->addSpacing(10); + fileTypeLay->addWidget(m_fileFormatOptionButton); + } + fileLay->addLayout(fileTypeLay, 0); + + QHBoxLayout* saveInLay = new QHBoxLayout(); + saveInLay->setMargin(0); + saveInLay->setSpacing(3); + { + saveInLay->addWidget(new QLabel(tr("Save In:"), this), 0); + saveInLay->addWidget(m_saveInFileFld, 1); + } + fileLay->addLayout(saveInLay, 0); + } + fileFrame->setLayout(fileLay); + rightLay->addWidget(fileFrame, 0); + + QGridLayout* imageLay = new QGridLayout(); + imageLay->setMargin(10); + imageLay->setHorizontalSpacing(3); + imageLay->setVerticalSpacing(10); + { + imageLay->addWidget(new QLabel(tr("Color type:"), this), 0, 0, + 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_upsideDownCB, 4, 0, 1, 3, Qt::AlignLeft); + + imageLay->addWidget(new QLabel(tr("BG reduction:"), this), 5, 0, + Qt::AlignRight); + imageLay->addWidget(m_bgReductionFld, 5, 1, 1, 2); + + imageLay->addWidget(m_captureWhiteBGButton, 6, 0, 1, 3); + } + imageLay->setColumnStretch(0, 0); + imageLay->setColumnStretch(1, 0); + imageLay->setColumnStretch(2, 1); + imageFrame->setLayout(imageLay); + rightLay->addWidget(imageFrame, 0); + + QGridLayout* displayLay = new QGridLayout(); + displayLay->setMargin(10); + displayLay->setHorizontalSpacing(3); + displayLay->setVerticalSpacing(10); + { + displayLay->addWidget(m_onionSkinCB, 0, 0, 1, 3); + + displayLay->addWidget(new QLabel(tr("Opacity(%):"), this), 1, 0, + Qt::AlignRight); + displayLay->addWidget(m_onionOpacityFld, 1, 1, 1, 2); + } + displayLay->setColumnStretch(0, 0); + displayLay->setColumnStretch(1, 0); + displayLay->setColumnStretch(2, 1); + displayFrame->setLayout(displayLay); + rightLay->addWidget(displayFrame); + + rightLay->addStretch(1); + + rightLay->addWidget(captureButton, 0); + rightLay->addSpacing(20); + rightLay->addWidget(closeButton, 0); + } + mainLay->addLayout(rightLay, 0); + } + m_topLayout->addLayout(mainLay); + + //---- signal-slot connections ---- + bool ret = true; + ret = ret && connect(refreshCamListButton, SIGNAL(pressed()), this, + 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, + SLOT(onFileFormatOptionButtonPressed())); + ret = ret && + connect(nextLevelButton, SIGNAL(pressed()), this, SLOT(onNextName())); + ret = ret && connect(m_colorTypeCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onColorTypeComboChanged(int))); + ret = ret && connect(m_captureWhiteBGButton, SIGNAL(pressed()), this, + SLOT(onCaptureWhiteBGButtonPressed())); + ret = ret && connect(m_onionSkinCB, SIGNAL(toggled(bool)), this, + SLOT(onOnionCBToggled(bool))); + ret = ret && connect(m_onionOpacityFld, SIGNAL(valueEditedByHand()), this, + SLOT(onOnionOpacityFldEdited())); + ret = ret && connect(m_upsideDownCB, SIGNAL(toggled(bool)), + m_cameraViewfinder, SLOT(onUpsideDownChecked(bool))); + ret = ret && connect(closeButton, SIGNAL(clicked()), this, SLOT(reject())); + ret = + ret && connect(captureButton, SIGNAL(clicked()), this, SLOT(onCapture())); + assert(ret); + + refreshCameraList(); + onNextName(); +} + +//----------------------------------------------------------------------------- + +PencilTestPopup::~PencilTestPopup() { + if (m_currentCamera && m_currentCamera->state() == QCamera::ActiveState) + m_currentCamera->stop(); + // remove the cache image, if it exists + TFilePath fp(m_cacheImagePath); + if (TFileStatus(fp).doesExist()) TSystem::deleteFile(fp); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::refreshCameraList() { + m_cameraListCombo->clear(); + + QList cameras = QCameraInfo::availableCameras(); + if (cameras.empty()) { + m_cameraListCombo->addItem(tr("No camera found")); + m_cameraListCombo->setMaximumWidth(250); + m_cameraListCombo->setDisabled(true); + } + + int maxTextLength = 0; + int defaultIndex; + for (int c = 0; c < cameras.size(); c++) { + QString camDesc = cameras.at(c).description(); + m_cameraListCombo->addItem(camDesc); + maxTextLength = std::max(maxTextLength, fontMetrics().width(camDesc)); + if (cameras.at(c).deviceName() == QCameraInfo::defaultCamera().deviceName()) + defaultIndex = c; + } + m_cameraListCombo->setMaximumWidth(maxTextLength + 25); + m_cameraListCombo->setEnabled(true); + m_cameraListCombo->setCurrentIndex(defaultIndex); + + onCameraListComboActivated(defaultIndex); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onCameraListComboActivated(int index) { + QList cameras = QCameraInfo::availableCameras(); + if (cameras.size() != m_cameraListCombo->count()) return; + + // in case the camera is not changed (just click the combobox) + if (cameras.at(index).deviceName() == m_deviceName) return; + + QCamera* oldCamera = m_currentCamera; + m_currentCamera = new QCamera(cameras.at(index), this); + m_deviceName = cameras.at(index).deviceName(); + if (m_cameraImageCapture) { + disconnect(m_cameraImageCapture, SIGNAL(imageCaptured(int, const QImage&)), + this, SLOT(onImageCaptured(int, const QImage&))); + delete m_cameraImageCapture; + } + m_cameraImageCapture = new QCameraImageCapture(m_currentCamera, this); + /* Capturing to buffer currently seems not to be supported on Windows */ + // if + // (!m_cameraImageCapture->isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)) + // std::cout << "it does not support CaptureToBuffer" << std::endl; + m_cameraImageCapture->setCaptureDestination( + QCameraImageCapture::CaptureToBuffer); + connect(m_cameraImageCapture, SIGNAL(imageCaptured(int, const QImage&)), this, + SLOT(onImageCaptured(int, const QImage&))); + + // loading new camera + m_currentCamera->load(); + + // refresh resolution + m_resolutionCombo->clear(); + QList sizes = m_currentCamera->supportedViewfinderResolutions(); + + for (int s = 0; s < sizes.size(); s++) { + m_resolutionCombo->addItem( + QString("%1 x %2").arg(sizes.at(s).width()).arg(sizes.at(s).height())); + } + if (!sizes.isEmpty()) { + m_resolutionCombo->setCurrentIndex(0); + QCameraViewfinderSettings settings = m_currentCamera->viewfinderSettings(); + settings.setResolution(sizes[0]); + m_currentCamera->setViewfinderSettings(settings); + QImageEncoderSettings imageEncoderSettings; + imageEncoderSettings.setCodec("PNG"); + imageEncoderSettings.setResolution(sizes[0]); + m_cameraImageCapture->setEncodingSettings(imageEncoderSettings); + } + m_cameraViewfinder->setCamera(m_currentCamera); + + // deleting old camera + if (oldCamera) { + if (oldCamera->state() == QCamera::ActiveState) oldCamera->stop(); + delete oldCamera; + } + // start new camera + m_currentCamera->start(); + m_cameraViewfinder->setImage(QImage()); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onResolutionComboActivated(const QString& itemText) { + // resolution is written in the itemText with the format " x " + // (e.g. "800 x 600") + QStringList texts = itemText.split(' '); + // the splited text must be "" "x" and "" + if (texts.size() != 3) return; + + m_currentCamera->stop(); + m_currentCamera->unload(); + QCameraViewfinderSettings settings = m_currentCamera->viewfinderSettings(); + QSize newResolution(texts[0].toInt(), texts[2].toInt()); + settings.setResolution(newResolution); + m_currentCamera->setViewfinderSettings(settings); + QImageEncoderSettings imageEncoderSettings; + imageEncoderSettings.setCodec("image/jpeg"); + imageEncoderSettings.setQuality(QMultimedia::NormalQuality); + imageEncoderSettings.setResolution(newResolution); + m_cameraImageCapture->setEncodingSettings(imageEncoderSettings); + + // reset white bg + m_whiteBGImg = QImage(); + m_bgReductionFld->setDisabled(true); + + m_currentCamera->start(); + m_cameraViewfinder->setImage(QImage()); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onFileFormatOptionButtonPressed() { + if (m_fileTypeCombo->currentIndex() == 0) return; + // Tentatively use the preview output settings + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties* prop = scene->getProperties()->getPreviewProperties(); + std::string ext = m_fileTypeCombo->currentText().toStdString(); + openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext)); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onNextName() { + const std::auto_ptr nameBuilder(NameBuilder::getBuilder(L"")); + + TLevelSet* levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); + std::wstring levelName = L""; + + // Select a different unique level name in case it already exists (either in + // scene or on disk) + TFilePath fp; + TFilePath actualFp; + for (;;) { + levelName = nameBuilder->getNext(); + + if (levelSet->getLevel(levelName) != 0) continue; + + fp = TFilePath(m_saveInFileFld->getPath()) + + TFilePath(levelName + L".." + + m_fileTypeCombo->currentText().toStdWString()); + actualFp = scene->decodeFilePath(fp); + + if (TSystem::doesExistFileOrLevel(actualFp)) { + continue; + } + + break; + } + + m_levelNameEdit->setText(QString::fromStdWString(levelName)); + m_frameNumberEdit->setValue(1); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onColorTypeComboChanged(int index) { + m_thresholdFld->setEnabled(index == 2); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onImageCaptured(int id, const QImage& image) { + // capture the white BG + if (m_captureWhiteBGCue) { + m_whiteBGImg = image.copy(); + m_captureWhiteBGCue = false; + m_bgReductionFld->setEnabled(true); + } + + QImage procImg = image.copy(); + processImage(procImg); + m_cameraViewfinder->setImage(procImg); + + if (m_captureCue) { + m_captureCue = false; + if (importImage(procImg)) { + m_cameraViewfinder->setPreviousImage(procImg); + m_frameNumberEdit->setValue(m_frameNumberEdit->getValue() + 1); + } + } +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::timerEvent(QTimerEvent* event) { + if (!m_currentCamera || !m_cameraImageCapture || + !m_cameraImageCapture->isAvailable() || + !m_cameraImageCapture->isReadyForCapture()) + return; + + m_currentCamera->setCaptureMode(QCamera::CaptureStillImage); + m_currentCamera->start(); + m_currentCamera->searchAndLock(); + m_cameraImageCapture->capture(m_cacheImagePath); + m_currentCamera->unlock(); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::showEvent(QShowEvent* event) { + m_timerId = startTimer(10); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::hideEvent(QHideEvent* event) { killTimer(m_timerId); } + +//----------------------------------------------------------------------------- + +void PencilTestPopup::processImage(QImage& image) { + /* "upside down" is not executed here. It will be done when capturing the + * image */ + + // white bg reduction + 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); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onCaptureWhiteBGButtonPressed() { + m_captureWhiteBGCue = true; +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onOnionCBToggled(bool on) { + m_cameraViewfinder->setShowOnionSkin(on); + m_onionOpacityFld->setEnabled(on); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onOnionOpacityFldEdited() { + int value = (int)(255.0f * (float)m_onionOpacityFld->getValue() / 100.0f); + m_cameraViewfinder->setOnionOpacity(value); +} + +//----------------------------------------------------------------------------- + +void PencilTestPopup::onCapture() { m_captureCue = true; } + +//----------------------------------------------------------------------------- +/*! referenced from LevelCreatePopup::apply() +*/ +bool PencilTestPopup::importImage(QImage& image) { + TApp* app = TApp::instance(); + ToonzScene* scene = app->getCurrentScene()->getScene(); + TXsheet* xsh = scene->getXsheet(); + + std::wstring levelName = m_levelNameEdit->text().toStdWString(); + if (levelName.empty()) { + error(tr("No level name specified: please choose a valid level name")); + return false; + } + + int frameNumber = m_frameNumberEdit->getValue(); + + /* create parent directory if it does not exist */ + TFilePath parentDir = + scene->decodeFilePath(TFilePath(m_saveInFileFld->getPath())); + if (!TFileStatus(parentDir).doesExist()) { + QString question; + question = tr("Folder %1 doesn't exist.\nDo you want to create it?") + .arg(toQString(parentDir)); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No")); + if (ret == 0 || ret == 2) return false; + try { + TSystem::mkDir(parentDir); + DvDirModel::instance()->refreshFolder(parentDir.getParentDir()); + } catch (...) { + error(tr("Unable to create") + toQString(parentDir)); + return false; + } + } + + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + + TFilePath(levelName + L".." + + m_fileTypeCombo->currentText().toStdWString()); + TFilePath actualLevelFp = scene->decodeFilePath(levelFp); + + TXshSimpleLevel* sl = 0; + + TXshLevel* level = scene->getLevelSet()->getLevel(levelName); + /* if the level already exists in the scene cast */ + if (level) { + /* if the existing level is not a raster level, then return */ + if (level->getType() != OVL_XSHLEVEL) { + error( + tr("The level name specified is already used: please choose a " + "different level name.")); + return false; + } + /* if the existing level does not match file path and pixel size, then + * return */ + sl = level->getSimpleLevel(); + if (scene->decodeFilePath(sl->getPath()) != actualLevelFp) { + error( + tr("The save in path specified does not match with the existing " + "level.")); + return false; + } + if (sl->getProperties()->getImageRes() != + TDimension(image.width(), image.height())) { + error(tr( + "The captured image size does not match with the existing level.")); + return false; + } + /* if the level already have the same frame, then ask if overwrite it */ + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + if (TFileStatus(frameFp).doesExist()) { + QString question = tr("File %1 does exist.\nDo you want to overwrite it?") + .arg(toQString(frameFp)); + int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), + QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return false; + } + } + /* if the level does not exist in the scene cast */ + else { + /* if the file does exist, load it first */ + if (TFileStatus(actualLevelFp).doesExist()) { + level = scene->loadLevel(actualLevelFp); + if (!level) { + error(tr("Failed to load %1.").arg(toQString(actualLevelFp))); + return false; + } + + /* if the loaded level does not match in pixel size, then return */ + sl = level->getSimpleLevel(); + if (!sl || + sl->getProperties()->getImageRes() != + TDimension(image.width(), image.height())) { + error(tr( + "The captured image size does not match with the existing level.")); + return false; + } + } + /* if the file does not exist, then create a new level */ + else { + TXshLevel* level = scene->createNewLevel(OVL_XSHLEVEL, levelName, + TDimension(), 0, levelFp); + sl = level->getSimpleLevel(); + sl->setPath(levelFp, true); + sl->getProperties()->setDpiPolicy(LevelProperties::DP_CustomDpi); + TPointD currentCamDpi = getCurrentCameraDpi(); + sl->getProperties()->setDpi(currentCamDpi.x); + sl->getProperties()->setImageDpi(currentCamDpi); + sl->getProperties()->setImageRes( + TDimension(image.width(), image.height())); + } + } + + TFrameId fid(frameNumber); + TPointD levelDpi = sl->getDpi(); + /* create the raster */ + TRaster32P raster(image.width(), image.height()); + convertImageToRaster(raster, (m_upsideDownCB->isChecked()) + ? image + : image.mirrored(true, true)); + TRasterImageP ri(raster); + ri->setDpi(levelDpi.x, levelDpi.y); + /* setting the frame */ + sl->setFrame(fid, ri); + + /* set dirty flag */ + sl->getProperties()->setDirtyFlag(true); + + /* placement in xsheet */ + int row = app->getCurrentFrame()->getFrame(); + int col = app->getCurrentColumn()->getColumnIndex(); + + /* try to find the vacant cell */ + int tmpRow = row; + bool isFoundEmptyCell = false; + while (1) { + if (xsh->getCell(tmpRow, col).isEmpty()) { + isFoundEmptyCell = true; + break; + } + if (xsh->getCell(tmpRow, col).m_level->getSimpleLevel() != sl) break; + tmpRow++; + } + + /* in case setting the same level as the the current column */ + if (isFoundEmptyCell) { + xsh->setCell(tmpRow, col, TXshCell(sl, fid)); + } + /* in case the level is different from the current column, then insert a new + column */ + else { + col += 1; + xsh->insertColumn(col); + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); + } + /* notify */ + app->getCurrentScene()->notifySceneChanged(); + app->getCurrentScene()->notifyCastChange(); + app->getCurrentXsheet()->notifyXsheetChanged(); + + return true; +} + +//----------------------------------------------------------------------------- + +OpenPopupCommandHandler openPencilTestPopup(MI_PencilTest); \ No newline at end of file diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h new file mode 100644 index 00000000..c0170605 --- /dev/null +++ b/toonz/sources/toonz/penciltestpopup.h @@ -0,0 +1,117 @@ +#pragma once + +#ifndef PENCILTESTPOPUP_H +#define PENCILTESTPOPUP_H + +#include "toonzqt/dvdialog.h" + +#include + +// forward decl. +class QCamera; +class QCameraImageCapture; + +class QComboBox; +class QLineEdit; +class QSlider; +class QCheckBox; +class QPushButton; +class QVideoFrame; + +namespace DVGui { +class FileField; +class IntLineEdit; +class IntField; +} + +//============================================================================= +// MyViewFinder +//----------------------------------------------------------------------------- + +class MyViewFinder : public QFrame { + Q_OBJECT + + QImage m_image; + QImage m_previousImage; + QCamera* m_camera; + QRect m_imageRect; + + bool m_showOnionSkin; + int m_onionOpacity; + bool m_upsideDown; + +public: + MyViewFinder(QWidget* parent = 0); + void setImage(const QImage& image) { + m_image = image; + update(); + } + void setCamera(QCamera* camera) { m_camera = camera; } + void setShowOnionSkin(bool on) { m_showOnionSkin = on; } + void setOnionOpacity(int value) { m_onionOpacity = value; } + void setPreviousImage(QImage& prevImage) { m_previousImage = prevImage; } + +protected: + void paintEvent(QPaintEvent* event); + void resizeEvent(QResizeEvent* event); +protected slots: + void onUpsideDownChecked(bool on) { m_upsideDown = on; } +}; + +//============================================================================= +// PencilTestPopup +//----------------------------------------------------------------------------- + +class PencilTestPopup : public DVGui::Dialog { + Q_OBJECT + + QCamera* m_currentCamera; + QString m_deviceName; + MyViewFinder* m_cameraViewfinder; + QCameraImageCapture* m_cameraImageCapture; + + QComboBox *m_cameraListCombo, *m_resolutionCombo, *m_fileTypeCombo, + *m_colorTypeCombo; + QLineEdit* m_levelNameEdit; + QCheckBox *m_upsideDownCB, *m_onionSkinCB; + QPushButton *m_fileFormatOptionButton, *m_captureWhiteBGButton; + DVGui::FileField* m_saveInFileFld; + DVGui::IntLineEdit* m_frameNumberEdit; + DVGui::IntField *m_thresholdFld, *m_contrastFld, *m_brightnessFld, + *m_bgReductionFld, *m_onionOpacityFld; + + QImage m_whiteBGImg; + + int m_timerId; + QString m_cacheImagePath; + bool m_captureWhiteBGCue; + bool m_captureCue; + + void processImage(QImage& procImage); + bool importImage(QImage& image); + +public: + PencilTestPopup(); + ~PencilTestPopup(); + +protected: + void timerEvent(QTimerEvent* event); + void showEvent(QShowEvent* event); + void hideEvent(QHideEvent* event); + +protected slots: + void refreshCameraList(); + void onCameraListComboActivated(int index); + void onResolutionComboActivated(const QString&); + void onFileFormatOptionButtonPressed(); + void onNextName(); + void onColorTypeComboChanged(int index); + void onImageCaptured(int, const QImage&); + void onCaptureWhiteBGButtonPressed(); + void onOnionCBToggled(bool); + void onOnionOpacityFldEdited(); + + void onCapture(); +}; + +#endif \ No newline at end of file diff --git a/toonz/sources/toonzqt/stylenameeditor.cpp b/toonz/sources/toonzqt/stylenameeditor.cpp index 57fa3db8..b325d9b4 100644 --- a/toonz/sources/toonzqt/stylenameeditor.cpp +++ b/toonz/sources/toonzqt/stylenameeditor.cpp @@ -27,7 +27,7 @@ StyleNameEditor::StyleNameEditor(QWidget *parent) m_applyButton->setEnabled(false); m_cancelButton->setFocusPolicy(Qt::NoFocus); - m_styleName->setObjectName("RenameColorTextField"); + m_styleName->setObjectName("LargeSizedText"); QVBoxLayout *mainLayout = new QVBoxLayout(); mainLayout->setMargin(10); diff --git a/toonz/sources/translations/japanese/toonz.ts b/toonz/sources/translations/japanese/toonz.ts index 49bfaa6d..d20577db 100644 --- a/toonz/sources/translations/japanese/toonz.ts +++ b/toonz/sources/translations/japanese/toonz.ts @@ -4253,6 +4253,26 @@ Do you want to create it? Refresh Folder Tree フォルダ構成の再読み込み + + &Pencil Test... + ラインテスト (&P)... + + + Drawing Substitution Forward + + + + Drawing Substitution Backward + + + + Similar Drawing Substitution Forward + + + + Similar Drawing Substitution Backward + + MatchlinesDialog @@ -4503,6 +4523,13 @@ What do you want to do? ピクセル形式が対応されていません。 + + MyViewFinder + + Camera is not available + + + OutputSettingsPopup @@ -4880,6 +4907,145 @@ Do you want to overwrite it? 上書きしますか? + + PencilTestPopup + + Pencil Test + ラインテスト + + + Refresh + リスト更新 + + + File + ファイル + + + Options + ファイル設定 + + + Image adjust + 画像調整 + + + Upside down + 180度回転 + + + Capture white BG + 基準背景取り込み + + + Display + 表示 + + + Show onion skin + 前の画像と比べる + + + Capture + 取り込み + + + Close + 閉じる + + + Next Level + 次のレベル + + + Camera: + カメラ: + + + Resolution: + サイズ: + + + Name: + レベル名: + + + Frame: + フレーム: + + + File Type: + ファイルタイプ: + + + Save In: + 保存先: + + + Color type: + タイプ: + + + Threshold: + しきい値: + + + Contrast: + コントラスト: + + + Brightness: + 明るさ: + + + BG reduction: + 背景の除去: + + + Opacity(%): + 不透明度(%): + + + No camera found + カメラが見つかりません + + + No level name specified: please choose a valid level name + レベル名は指定されていません。有効なレベル名を指定して下さい。 + + + Folder %1 doesn't exist. +Do you want to create it? + フォルダー %1 は存在しません。 +作成しますか? + + + Unable to create + 作成できません。 + + + The level name specified is already used: please choose a different level name. + 指定されたレベル名はすでに使用中です:別の名前を指定してください + + + The save in path specified does not match with the existing level. + 指定された保存先パスが既存のレベルと異なります。 + + + The captured image size does not match with the existing level. + 取り込まれた画像サイズが既存のレベルと異なります。 + + + File %1 does exist. +Do you want to overwrite it? + ファイル %1 は、既に存在します。 +上書きしてもよろしいですか? + + + Failed to load %1. + ファイル %1 の読み込みに失敗しました + + PltGizmoPopup @@ -7070,6 +7236,10 @@ Are you sure to Add color model's palette to the destination palette. カラーモデルのパレットを、対象のパレットに追加する。 + + Change current drawing %1 + + RenameAsToonzPopup @@ -9408,6 +9578,10 @@ Please refer to the user guide for details. Double Click to Toggle Onion Skin [ダブルクリック] オニオンスキン表示/非表示 + + Pinned Center : Col%1%2 + + XsheetViewer