diff --git a/toonz/sources/common/tapptools/tcolorutils.cpp b/toonz/sources/common/tapptools/tcolorutils.cpp index 1f238d2..46a4f83 100644 --- a/toonz/sources/common/tapptools/tcolorutils.cpp +++ b/toonz/sources/common/tapptools/tcolorutils.cpp @@ -780,6 +780,11 @@ static void buildPaletteForBlendedImages(std::set &palette, //------------------------------------------------------------------------------ +#include +#include +#include +#include + namespace { #define DISTANCE 3 @@ -803,6 +808,135 @@ bool find(const std::set &palette, const TPixel &color) { return false; } +static TPixel32 getPixel(int x, int y, const TRaster32P &raster) { + return raster->pixels(y)[x]; +} + +struct EdgePoint { + QPoint pos; + enum QUADRANT { + RightUpper = 0x01, + LeftUpper = 0x02, + LeftLower = 0x04, + RightLower = 0x08 + }; + enum EDGE { + UpperEdge = 0x10, + LeftEdge = 0x20, + LowerEdge = 0x40, + RightEdge = 0x80 + }; + + unsigned char info = 0; + + EdgePoint(int x, int y) { + pos.setX(x); + pos.setY(y); + } + // identify the edge pixel by checking if the four neighbor pixels + // (distanced by step * 3 pixels) has the same color as the center pixel + void initInfo(const TRaster32P &raster, const int step) { + int lx = raster->getLx(); + int ly = raster->getLy(); + TPixel32 keyColor = getPixel(pos.x(), pos.y(), raster); + info = 0; + int dist = step * 3; + if (pos.y() < ly - dist && + keyColor == getPixel(pos.x(), pos.y() + dist, raster)) + info = info | UpperEdge; + if (pos.x() >= dist && + keyColor == getPixel(pos.x() - dist, pos.y(), raster)) + info = info | LeftEdge; + if (pos.y() >= dist && + keyColor == getPixel(pos.x(), pos.y() - dist, raster)) + info = info | LowerEdge; + if (pos.x() < lx - dist && + keyColor == getPixel(pos.x() + dist, pos.y(), raster)) + info = info | RightEdge; + + // identify available corners + if (info & UpperEdge) { + if (info & RightEdge) info = info | RightUpper; + if (info & LeftEdge) info = info | LeftUpper; + } + if (info & LowerEdge) { + if (info & RightEdge) info = info | RightLower; + if (info & LeftEdge) info = info | LeftLower; + } + } + + bool isCorner() { + return info & RightUpper || info & LeftUpper || info & RightLower || + info & LeftLower; + } +}; + +struct ColorChip { + QRect rect; + TPixel32 color; + QPoint center; + + ColorChip(const QPoint &topLeft, const QPoint &bottomRight) + : rect(topLeft, bottomRight) {} + + bool validate(const TRaster32P &raster, const int step) { + int lx = raster->getLx(); + int ly = raster->getLy(); + + // just in case - boundary conditions + if (!QRect(0, 0, lx - 1, ly - 1).contains(rect)) return false; + + // rectangular must be equal or bigger than 3 * lineWidth + if (rect.width() < step * 3 || rect.height() < step * 3) return false; + + // obtain center color + center = rect.center(); + color = getPixel(center.x(), center.y(), raster); + + // it should not be transparent + if (color == TPixel::Transparent) return false; + + // rect should be filled with single color + raster->lock(); + for (int y = rect.top() + step; y <= rect.bottom() - 1; y += step) { + TPixel *pix = raster->pixels(y) + rect.left() + step; + for (int x = rect.left() + step; x <= rect.right() - 1; + x += step, pix += step) { + if (*pix != color) { + raster->unlock(); + return false; + } + } + } + raster->unlock(); + + return true; + } +}; + +bool lowerLeftThan(const EdgePoint &ep1, const EdgePoint &ep2) { + if (ep1.pos.y() != ep2.pos.y()) return ep1.pos.y() < ep2.pos.y(); + return ep1.pos.x() < ep2.pos.x(); +} + +bool colorChipUpperLeftThan(const ColorChip &chip1, const ColorChip &chip2) { + if (chip1.center.y() != chip2.center.y()) + return chip1.center.y() > chip2.center.y(); + return chip1.center.x() < chip2.center.x(); +} + +bool colorChipLowerLeftThan(const ColorChip &chip1, const ColorChip &chip2) { + if (chip1.center.y() != chip2.center.y()) + return chip1.center.y() < chip2.center.y(); + return chip1.center.x() < chip2.center.x(); +} + +bool colorChipLeftUpperThan(const ColorChip &chip1, const ColorChip &chip2) { + if (chip1.center.x() != chip2.center.x()) + return chip1.center.x() < chip2.center.x(); + return chip1.center.y() > chip2.center.y(); +} + } // namespace /*-- 似ている色をまとめて1つのStyleにする --*/ @@ -844,6 +978,7 @@ void TColorUtils::buildPalette(std::set &palette, buildPaletteForBlendedImages(palette, raster, maxColorCount); } } +//------------------------------------------------------------------------------ /*-- 全ての異なるピクセルの色を別のStyleにする --*/ void TColorUtils::buildPrecisePalette(std::set &palette, @@ -878,3 +1013,134 @@ void TColorUtils::buildPrecisePalette(std::set &palette, } //------------------------------------------------------------------------------ + +void TColorUtils::buildColorChipPalette(QList> &palette, + const TRaster32P &raster, + int maxColorCount, + const TPixel32 &gridColor, + const int gridLineWidth, + const int colorChipOrder) { + int lx = raster->getLx(); + int ly = raster->getLy(); + int wrap = raster->getWrap(); + + QList edgePoints; + + // search for gridColor in the image + int step = gridLineWidth; + int x, y; + for (y = 0; y < ly; y += step) { + TPixel *pix = raster->pixels(y); + for (x = 0; x < lx; x += step, pix += step) { + if (*pix == gridColor) { + EdgePoint edgePoint(x, y); + edgePoint.initInfo(raster, step); + // store the edgePoint if it can be a corner + if (edgePoint.isCorner()) edgePoints.append(edgePoint); + } + } + } + + // std::cout << "edgePoints.count = " << edgePoints.count() << std::endl; + // This may be unnecessary + qSort(edgePoints.begin(), edgePoints.end(), lowerLeftThan); + + QList colorChips; + + // make rectangles by serching in the corner points + for (int ep0 = 0; ep0 < edgePoints.size(); ep0++) { + QMap corners; + + // if a point cannot be the first corner, continue + if ((edgePoints.at(ep0).info & EdgePoint::RightUpper) == 0) continue; + + // find vertices of rectangle in counter clockwise direction + + // if a point is found which can be the first corner + // search for the second corner point at the right side of the first one + for (int ep1 = ep0 + 1; ep1 < edgePoints.size(); ep1++) { + // end searching at the end of scan line + if (edgePoints.at(ep0).pos.y() != edgePoints.at(ep1).pos.y()) break; + // if a point cannot be the second corner, continue + if ((edgePoints.at(ep1).info & EdgePoint::LeftUpper) == 0) continue; + + // if a point is found which can be the second corner + // search for the third corner point at the upper side of the second one + for (int ep2 = ep1 + 1; ep2 < edgePoints.size(); ep2++) { + // the third point must be at the same x position as the second one + if (edgePoints.at(ep1).pos.x() != edgePoints.at(ep2).pos.x()) continue; + + // if a point cannot be the third corner, continue + if ((edgePoints.at(ep2).info & EdgePoint::LeftLower) == 0) continue; + + // if a point is found which can be the third corner + // search for the forth corner point at the left side of the third one + for (int ep3 = ep1 + 1; ep3 < ep2; ep3++) { + // if the forth point is found + if ((edgePoints.at(ep3).info & EdgePoint::RightLower) && + edgePoints.at(ep0).pos.x() == edgePoints.at(ep3).pos.x() && + edgePoints.at(ep2).pos.y() == edgePoints.at(ep3).pos.y()) { + corners[EdgePoint::RightLower] = ep3; + break; + } + } // search for ep3 loop + + if (corners.contains(EdgePoint::RightLower)) { + corners[EdgePoint::LeftLower] = ep2; + break; + } + + } // search for ep2 loop + + if (corners.contains(EdgePoint::LeftLower)) { + corners[EdgePoint::LeftUpper] = ep1; + break; + } + + } // search for ep1 loop + + // check if all the 4 corner points are found + if (corners.contains(EdgePoint::LeftUpper)) { + corners[EdgePoint::RightUpper] = ep0; + + assert(corners.size() == 4); + + // register color chip + ColorChip chip(edgePoints.at(corners[EdgePoint::RightUpper]).pos, + edgePoints.at(corners[EdgePoint::LeftLower]).pos); + if (chip.validate(raster, step)) colorChips.append(chip); + + // remove the coner information from the corner point + QMap::const_iterator i = corners.constBegin(); + while (i != corners.constEnd()) { + edgePoints[i.value()].info & ~i.key(); + ++i; + } + if (colorChips.count() >= maxColorCount) break; + } + } + + // std::cout << "colorChips.count = " << colorChips.count() << std::endl; + if (!colorChips.empty()) { + // 0:UpperLeft 1:LowerLeft 2:LeftUpper + // sort the color chips + switch (colorChipOrder) { + case 0: + qSort(colorChips.begin(), colorChips.end(), colorChipUpperLeftThan); + break; + case 1: + qSort(colorChips.begin(), colorChips.end(), colorChipLowerLeftThan); + break; + case 2: + qSort(colorChips.begin(), colorChips.end(), colorChipLeftUpperThan); + break; + } + + for (int c = 0; c < colorChips.size(); c++) + palette.append(qMakePair( + colorChips.at(c).color, + TPoint(colorChips.at(c).center.x(), colorChips.at(c).center.y()))); + } +} + +//------------------------------------------------------------------------------ diff --git a/toonz/sources/common/tvrender/tpalette.cpp b/toonz/sources/common/tvrender/tpalette.cpp index ad236ef..fd5735a 100644 --- a/toonz/sources/common/tvrender/tpalette.cpp +++ b/toonz/sources/common/tvrender/tpalette.cpp @@ -29,21 +29,29 @@ DEFINE_CLASS_CODE(TPalette, 30) namespace { -const int maxStyleIndex = 32765; - -const std::string pointToString(const TPoint &point) { - return std::to_string(point.x) + "," + std::to_string(point.y); +const std::string pointToString(const TColorStyle::PickedPosition &point) { + if (point.frame == 0) + return std::to_string(point.pos.x) + "," + std::to_string(point.pos.y); + else + return std::to_string(point.pos.x) + "," + std::to_string(point.pos.y) + + "," + std::to_string(point.frame); } // splitting string with ',' -const TPoint stringToPoint(const std::string &string) { +const TColorStyle::PickedPosition stringToPoint(const std::string &string) { std::string buffer; std::stringstream ss(string); - std::getline(ss, buffer, ','); // getting the first part of string - int x = std::stoi(buffer); - std::getline(ss, buffer); // getting the second part of string - int y = std::stoi(buffer); - return TPoint(x, y); + std::vector result; + while (std::getline(ss, buffer, ',')) // split with comma + result.push_back(buffer); + + int x = std::stoi(result[0]); + int y = std::stoi(result[1]); + int frame = 0; + if (result.size() == 3) // getting the third part of string - if any. + frame = std::stoi(result[2]); + + return {TPoint(x, y), frame}; } } // namespace @@ -581,7 +589,7 @@ void TPalette::saveData(TOStream &os) { { for (int i = 0; i < getStyleCount(); ++i) { TColorStyleP style = m_styles[i].second; - if (style->getPickedPosition() == TPoint()) + if (style->getPickedPosition().pos == TPoint()) os.openChild("style"); else { std::map attr; @@ -1129,7 +1137,7 @@ void TPalette::setShortcutValue(int key, int styleId) { bool TPalette::hasPickedPosStyle() { for (int i = 0; i < getStyleCount(); ++i) { TColorStyleP style = m_styles[i].second; - if (style->getPickedPosition() != TPoint()) return true; + if (style->getPickedPosition().pos != TPoint()) return true; } return false; } diff --git a/toonz/sources/include/tcolorstyles.h b/toonz/sources/include/tcolorstyles.h index 1b9bb6c..66784ed 100644 --- a/toonz/sources/include/tcolorstyles.h +++ b/toonz/sources/include/tcolorstyles.h @@ -103,6 +103,19 @@ public: struct int_tag {}; struct TFilePath_tag {}; + struct PickedPosition { + TPoint pos = TPoint(); + int frame = 0; + PickedPosition(TPoint _pos = TPoint(), int _frame = 0) + : pos(_pos), frame(_frame) {} + inline bool operator==(const PickedPosition &p) const { + return (this->pos == p.pos) && (this->frame == p.frame); + } + inline bool operator!=(const PickedPosition &p) const { + return (this->pos != p.pos) || (this->frame != p.frame); + } + }; + private: std::wstring m_name; //!< User-define style name. std::wstring m_globalName; //!< User-define style \a global name. @@ -117,9 +130,9 @@ private: bool m_isEditedFromOriginal; // + #undef DVAPI #undef DVVAR #ifdef TAPPTOOLS_EXPORTS @@ -26,6 +28,12 @@ DVAPI void buildPalette(std::set &palette, const TRaster32P &raster, /*-- 全ての異なるピクセルの色を別のStyleにする --*/ DVAPI void buildPrecisePalette(std::set &palette, const TRaster32P &raster, int maxColorCount); +// pick up color chip sorrounded by frames with specified color +DVAPI void buildColorChipPalette(QList> &palette, + const TRaster32P &raster, int maxColorCount, + const TPixel32 &gridColor, + const int gridLineWidth, + const int colorChipOrder); } //------------------------------------------------------------------------------ diff --git a/toonz/sources/include/toonz/palettecmd.h b/toonz/sources/include/toonz/palettecmd.h index ada5ee4..fc8a9f9 100644 --- a/toonz/sources/include/toonz/palettecmd.h +++ b/toonz/sources/include/toonz/palettecmd.h @@ -72,9 +72,25 @@ enum ColorModelPltBehavior { AddColorModelPlt }; +enum ColorModelRasterPickType { + PickEveryColors = 0, + IntegrateSimilarColors, + PickColorChipGrid +}; + +enum ColorChipOrder { UpperLeft = 0, LowerLeft, LeftUpper }; + +struct ColorModelLoadingConfiguration { + ColorModelPltBehavior behavior = ReplaceColorModelPlt; + ColorModelRasterPickType rasterPickType = PickEveryColors; + TPixel32 gridColor = TPixel::Magenta; + int gridLineWidth = 1; + ColorChipOrder colorChipOrder = UpperLeft; +}; + DVAPI int loadReferenceImage( - TPaletteHandle *paletteHandle, ColorModelPltBehavior pltBehavior, - const TFilePath &_fp, int &frame, ToonzScene *scene, + TPaletteHandle *paletteHandle, const ColorModelLoadingConfiguration &config, + const TFilePath &_fp, ToonzScene *scene, const std::vector &frames = std::vector()); DVAPI void removeReferenceImage(TPaletteHandle *paletteHandle); @@ -90,14 +106,14 @@ DVAPI void renamePaletteStyle(TPaletteHandle *paletteHandle, /* called in ColorModelViewer::pick() - move selected style to the first page */ DVAPI void organizePaletteStyle(TPaletteHandle *paletteHandle, int styleId, - const TPoint &point); + const TColorStyle::PickedPosition &point); /* called in ColorModelViewer::repickFromColorModel(). Pick color from the img for all styles with "picked position" value. */ DVAPI void pickColorByUsingPickedPosition(TPaletteHandle *paletteHandle, - TImageP img); + TImageP img, int frame); } // namespace diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index a40476b..5d42c9b 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -298,11 +298,6 @@ public: return m_removeSceneNumberFromLoadedLevelName; } - void setPaletteTypeOnLoadRasterImageAsColorModel(int type); - int getPaletteTypeOnLoadRasterImageAsColorModel() const { - return m_paletteTypeOnLoadRasterImageAsColorModel; - } - void setDefaultImportPolicy(int policy); int getDefaultImportPolicy() { return m_importPolicy; } @@ -651,12 +646,6 @@ private: bool m_onionSkinEnabled; bool m_multiLayerStylePickerEnabled; bool m_precompute; - /*-- - Color Modelにラスタ画像を読み込んだとき、パレットをどのように作るか - 0 : 全ての異なるピクセルの色を別のStyleにする, 1 : -似ている色をまとめて1つのStyleにする ---*/ - int m_paletteTypeOnLoadRasterImageAsColorModel; bool m_showKeyframesOnXsheetCellArea; std::string m_layerNameEncoding = "SJIS"; // Fixed to SJIS for now. You can diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index df4b1f4..3c4acb2 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -157,6 +157,7 @@ set(MOC_HEADERS cameracapturelevelcontrol.h reframepopup.h autoinputcellnumberpopup.h + colormodelbehaviorpopup.h # Tracker file dummyprocessor.h metnum.h @@ -329,6 +330,7 @@ set(SOURCES cameracapturelevelcontrol.cpp reframepopup.cpp autoinputcellnumberpopup.cpp + colormodelbehaviorpopup.cpp # Tracker file dummyprocessor.cpp metnum.cpp diff --git a/toonz/sources/toonz/Resources/colorchiporder_leftup.svg b/toonz/sources/toonz/Resources/colorchiporder_leftup.svg new file mode 100644 index 0000000..10417a0 --- /dev/null +++ b/toonz/sources/toonz/Resources/colorchiporder_leftup.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/Resources/colorchiporder_lowleft.svg b/toonz/sources/toonz/Resources/colorchiporder_lowleft.svg new file mode 100644 index 0000000..30ee612 --- /dev/null +++ b/toonz/sources/toonz/Resources/colorchiporder_lowleft.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/Resources/colorchiporder_upleft.svg b/toonz/sources/toonz/Resources/colorchiporder_upleft.svg new file mode 100644 index 0000000..c9a68b7 --- /dev/null +++ b/toonz/sources/toonz/Resources/colorchiporder_upleft.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/toonz/sources/toonz/colormodelbehaviorpopup.cpp b/toonz/sources/toonz/colormodelbehaviorpopup.cpp new file mode 100644 index 0000000..7fe2aa3 --- /dev/null +++ b/toonz/sources/toonz/colormodelbehaviorpopup.cpp @@ -0,0 +1,264 @@ +#include "colormodelbehaviorpopup.h" + +#include "toonzqt/colorfield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/gutil.h" + +#include "tenv.h" +#include "tpixel.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +TEnv::IntVar ColorModelBehavior_PaletteOperation( + "ColorModelBehavior_PaletteOperation", 0); +// moved from preferences to env +TEnv::IntVar ColorModelBehavior_RasterImagePickType( + "ColorModelBehavior_RasterImagePickType", 0); +TEnv::StringVar ColorModelBehavior_ChipGridColor( + "ColorModelBehavior_ChipGridColor", "#FF00FF"); +TEnv::IntVar ColorModelBehavior_ChipGridLineWidth( + "ColorModelBehavior_ChipGridLineWidth", 2); +TEnv::IntVar ColorModelBehavior_ChipOrder("ColorModelBehavior_ChipOrder", 0); +//------------------------------------------------------------------- + +ColorModelBehaviorPopup::ColorModelBehaviorPopup( + const std::set& paths, QWidget* parent) + : Dialog(parent, true, true) { + setWindowTitle(tr("Select the Palette Operation")); + + // check if the paths contain standard raster image (i.e. without palette) + // N.B. note that paths must contain only one path for now + for (auto itr = paths.begin(); itr != paths.end(); ++itr) { + std::string type((*itr).getType()); + if (type != "tlv" && type != "pli") { + m_hasRasterImage = true; + break; + } + } + m_buttonGroup = new QButtonGroup(this); + QRadioButton* keepColorModelPltButton = + new QRadioButton(tr("Overwrite the destination palette.")); + QRadioButton* replaceColorModelPltButton = new QRadioButton( + tr("Keep the destination palette and apply it to the color model.")); + + m_buttonGroup->addButton(keepColorModelPltButton); + m_buttonGroup->addButton(replaceColorModelPltButton); + m_buttonGroup->setId(keepColorModelPltButton, PaletteCmd::KeepColorModelPlt); + m_buttonGroup->setId(replaceColorModelPltButton, + PaletteCmd::ReplaceColorModelPlt); + + QLabel* label = + new QLabel(tr("The color model palette is different from the destination " + "palette.\nWhat do you want to do? ")); + label->setAlignment(Qt::AlignLeft); + m_topLayout->addWidget(label); + + QGroupBox* paletteBox = new QGroupBox(this); + QVBoxLayout* paletteLay = new QVBoxLayout(); + paletteLay->setMargin(15); + paletteLay->setSpacing(15); + + paletteLay->addWidget(keepColorModelPltButton); + paletteLay->addWidget(replaceColorModelPltButton); + + paletteBox->setLayout(paletteLay); + m_topLayout->addWidget(paletteBox); + + bool ret = true; + + QGroupBox* pickColorBox = NULL; + + if (m_hasRasterImage) { + QRadioButton* addColorModelPltButton = new QRadioButton( + tr("Add color model's palette to the destination palette.")); + m_buttonGroup->addButton(addColorModelPltButton); + m_buttonGroup->setId(addColorModelPltButton, PaletteCmd::AddColorModelPlt); + paletteLay->addWidget(addColorModelPltButton); + + //------- + m_topLayout->addSpacing(10); + + pickColorBox = new QGroupBox(tr("Picking Colors from Raster Image"), this); + + m_pickColorCombo = new QComboBox(this); + m_colorChipBehaviorFrame = new QFrame(this); + m_colorChipGridColor = + new DVGui::ColorField(this, false, TPixel32::Magenta, 40, false); + m_colorChipGridLineWidth = new DVGui::IntLineEdit(this, 2, 1, 20); + m_colorChipOrder = new QButtonGroup(this); + + QPushButton* upperLeftOrderBtn = + new QPushButton(createQIcon("colorchiporder_upleft"), "", this); + QPushButton* lowerLeftOrderBtn = + new QPushButton(createQIcon("colorchiporder_lowleft"), "", this); + QPushButton* leftUpperOrderBtn = + new QPushButton(createQIcon("colorchiporder_leftup"), "", this); + + QStringList paletteTypes; + paletteTypes << tr("Pick Every Colors as Different Styles") + << tr("Integrate Similar Colors as One Style") + << tr("Pick Colors in Color Chip Grid"); + m_pickColorCombo->addItems(paletteTypes); + + upperLeftOrderBtn->setCheckable(true); + lowerLeftOrderBtn->setCheckable(true); + leftUpperOrderBtn->setCheckable(true); + upperLeftOrderBtn->setIconSize(QSize(48, 42)); + lowerLeftOrderBtn->setIconSize(QSize(48, 42)); + leftUpperOrderBtn->setIconSize(QSize(48, 42)); + upperLeftOrderBtn->setFixedSize(QSize(54, 48)); + lowerLeftOrderBtn->setFixedSize(QSize(54, 48)); + leftUpperOrderBtn->setFixedSize(QSize(54, 48)); + upperLeftOrderBtn->setToolTip(tr("Horizontal - Top to bottom")); + lowerLeftOrderBtn->setToolTip(tr("Horizontal - Bottom to top")); + leftUpperOrderBtn->setToolTip(tr("Vertical - Left to right")); + upperLeftOrderBtn->setObjectName("MatchLineButton"); + lowerLeftOrderBtn->setObjectName("MatchLineButton"); + leftUpperOrderBtn->setObjectName("MatchLineButton"); + + m_colorChipOrder->addButton(upperLeftOrderBtn); + m_colorChipOrder->addButton(lowerLeftOrderBtn); + m_colorChipOrder->addButton(leftUpperOrderBtn); + m_colorChipOrder->setId(upperLeftOrderBtn, PaletteCmd::UpperLeft); + m_colorChipOrder->setId(lowerLeftOrderBtn, PaletteCmd::LowerLeft); + m_colorChipOrder->setId(leftUpperOrderBtn, PaletteCmd::LeftUpper); + m_colorChipOrder->setExclusive(true); + + QGridLayout* pickColorLay = new QGridLayout(); + pickColorLay->setMargin(10); + pickColorLay->setHorizontalSpacing(5); + pickColorLay->setVerticalSpacing(10); + { + pickColorLay->addWidget(new QLabel(tr("Pick Type:"), this), 0, 0, + Qt::AlignRight | Qt::AlignVCenter); + pickColorLay->addWidget(m_pickColorCombo, 0, 1, Qt::AlignLeft); + + QGridLayout* colorChipGridLay = new QGridLayout(); + colorChipGridLay->setMargin(0); + colorChipGridLay->setHorizontalSpacing(5); + colorChipGridLay->setVerticalSpacing(10); + { + colorChipGridLay->addWidget(new QLabel(tr("Grid Line Color:"), this), 0, + 0, Qt::AlignRight | Qt::AlignVCenter); + colorChipGridLay->addWidget(m_colorChipGridColor, 0, 1, Qt::AlignLeft); + + colorChipGridLay->addWidget(new QLabel(tr("Grid Line Width:"), this), 1, + 0, Qt::AlignRight | Qt::AlignVCenter); + colorChipGridLay->addWidget(m_colorChipGridLineWidth, 1, 1, + Qt::AlignLeft); + + colorChipGridLay->addWidget(new QLabel(tr("Chip Order:"), this), 2, 0, + Qt::AlignRight | Qt::AlignVCenter); + QHBoxLayout* orderLay = new QHBoxLayout(); + orderLay->setMargin(0); + orderLay->setSpacing(0); + { + orderLay->addWidget(upperLeftOrderBtn, 0); + orderLay->addWidget(lowerLeftOrderBtn, 0); + orderLay->addWidget(leftUpperOrderBtn, 0); + } + colorChipGridLay->addLayout(orderLay, 2, 1, Qt::AlignLeft); + } + colorChipGridLay->setColumnStretch(0, 0); + colorChipGridLay->setColumnStretch(1, 1); + m_colorChipBehaviorFrame->setLayout(colorChipGridLay); + + pickColorLay->addWidget(m_colorChipBehaviorFrame, 1, 0, 1, 2); + } + pickColorLay->setColumnStretch(0, 0); + pickColorLay->setColumnStretch(1, 1); + pickColorBox->setLayout(pickColorLay); + m_topLayout->addWidget(pickColorBox); + + ret = ret && connect(m_pickColorCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onPickColorComboActivated(int))); + ret = ret && connect(replaceColorModelPltButton, SIGNAL(toggled(bool)), + pickColorBox, SLOT(setDisabled(bool))); + } + + QPushButton* applyButton = new QPushButton(QObject::tr("Apply")); + ret = ret && connect(applyButton, SIGNAL(clicked()), this, SLOT(accept())); + QPushButton* cancelButton = new QPushButton(QObject::tr("Cancel")); + ret = ret && connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); + assert(ret); + + addButtonBarWidget(applyButton, cancelButton); + + // obtain initial values from env + QAbstractButton* button = + m_buttonGroup->button(ColorModelBehavior_PaletteOperation); + if (button) + button->setChecked(true); + else + keepColorModelPltButton->setChecked(true); + + if (m_hasRasterImage) { + m_pickColorCombo->setCurrentIndex(ColorModelBehavior_RasterImagePickType); + QColor chipGridColor( + QString::fromStdString(ColorModelBehavior_ChipGridColor)); + m_colorChipGridColor->setColor(TPixel32( + chipGridColor.red(), chipGridColor.green(), chipGridColor.blue())); + m_colorChipGridLineWidth->setValue(ColorModelBehavior_ChipGridLineWidth); + button = m_colorChipOrder->button(ColorModelBehavior_ChipOrder); + if (button) button->setChecked(true); + onPickColorComboActivated(ColorModelBehavior_RasterImagePickType); + pickColorBox->setDisabled(ColorModelBehavior_PaletteOperation == 1); + } +} + +//------------------------------------------------------------------- + +void ColorModelBehaviorPopup::getLoadingConfiguration( + PaletteCmd::ColorModelLoadingConfiguration& config) { + config.behavior = static_cast( + m_buttonGroup->checkedId()); + + if (m_colorChipOrder) + config.colorChipOrder = + static_cast(m_colorChipOrder->checkedId()); + + if (m_pickColorCombo) + config.rasterPickType = static_cast( + m_pickColorCombo->currentIndex()); + + if (m_colorChipGridColor) config.gridColor = m_colorChipGridColor->getColor(); + + if (m_colorChipGridLineWidth) + config.gridLineWidth = m_colorChipGridLineWidth->getValue(); +} + +//------------------------------------------------------------------- + +void ColorModelBehaviorPopup::onPickColorComboActivated(int index) { + if (!m_colorChipBehaviorFrame) return; + m_colorChipBehaviorFrame->setEnabled(index == 2); +} + +//------------------------------------------------------------------- +// save current state to env +ColorModelBehaviorPopup::~ColorModelBehaviorPopup() { + int id = m_buttonGroup->checkedId(); + if (id != -1) ColorModelBehavior_PaletteOperation = id; + + if (!m_hasRasterImage) return; + + ColorModelBehavior_RasterImagePickType = m_pickColorCombo->currentIndex(); + + TPixel32 gridColor = m_colorChipGridColor->getColor(); + ColorModelBehavior_ChipGridColor = + QColor(gridColor.r, gridColor.g, gridColor.b) + .name(QColor::HexRgb) + .toStdString(); + + ColorModelBehavior_ChipGridLineWidth = m_colorChipGridLineWidth->getValue(); + + id = m_colorChipOrder->checkedId(); + if (id != -1) ColorModelBehavior_ChipOrder = id; +} \ No newline at end of file diff --git a/toonz/sources/toonz/colormodelbehaviorpopup.h b/toonz/sources/toonz/colormodelbehaviorpopup.h new file mode 100644 index 0000000..3fdf268 --- /dev/null +++ b/toonz/sources/toonz/colormodelbehaviorpopup.h @@ -0,0 +1,43 @@ +#pragma once + +#ifndef COLORMODELBEHAVIORPOPUP_H +#define COLORMODELBEHAVIORPOPUP_H + +#include "tfilepath.h" +#include "toonzqt/dvdialog.h" +#include "toonz/palettecmd.h" + +class QButtonGroup; +class QComboBox; + +namespace DVGui { +class ColorField; +class IntLineEdit; +}; + +class ColorModelBehaviorPopup : public DVGui::Dialog { + Q_OBJECT + + QButtonGroup* m_buttonGroup; + + QComboBox* m_pickColorCombo = NULL; + QFrame* m_colorChipBehaviorFrame = NULL; + DVGui::ColorField* m_colorChipGridColor = NULL; + DVGui::IntLineEdit* m_colorChipGridLineWidth = NULL; + QButtonGroup* m_colorChipOrder = NULL; + + bool m_hasRasterImage = false; + +public: + ColorModelBehaviorPopup(const std::set& paths, + QWidget* parent = 0); + ~ColorModelBehaviorPopup(); + + void getLoadingConfiguration( + PaletteCmd::ColorModelLoadingConfiguration& config); + +public slots: + void onPickColorComboActivated(int); +}; + +#endif diff --git a/toonz/sources/toonz/colormodelviewer.cpp b/toonz/sources/toonz/colormodelviewer.cpp index d8e0f53..9ac1d77 100644 --- a/toonz/sources/toonz/colormodelviewer.cpp +++ b/toonz/sources/toonz/colormodelviewer.cpp @@ -6,6 +6,7 @@ #include "floatingpanelcommand.h" #include "tapp.h" #include "pane.h" +#include "colormodelbehaviorpopup.h" // TnzTools includes #include "tools/cursormanager.h" @@ -145,59 +146,54 @@ void ColorModelViewer::dropEvent(QDropEvent *event) { /*! Set current palette reference image to \b fp recall: \b PaletteCmd::loadReferenceImage(). */ +// This function will be called when drag & drop the file into the color model +// viewer + void ColorModelViewer::loadImage(const TFilePath &fp) { if (fp.isEmpty()) return; TPaletteHandle *paletteHandle = getPaletteHandle(); - if (!paletteHandle->getPalette()) return; - - std::string type(fp.getType()); - - QString question( - QObject::tr("The color model palette is different from the destination " - "palette.\nWhat do you want to do? ")); - QList list; - list.append(QObject::tr("Overwrite the destination palette.")); - list.append(QObject::tr( - "Keep the destination palette and apply it to the color model.")); - /*- if the file is raster image (i.e. without palette), then add another - * option "add styles" -*/ - if (type != "tlv" && type != "pli") - list.append( - QObject::tr("Add color model's palette to the destination palette.")); - - int ret = DVGui::RadioButtonMsgBox(DVGui::WARNING, question, list); - - PaletteCmd::ColorModelPltBehavior pltBehavior; - switch (ret) { - case 0: + TPalette *palette = paletteHandle->getPalette(); + + if (!palette || palette->isCleanupPalette()) { + DVGui::error(QObject::tr("Cannot load Color Model in current palette.")); return; - case 1: - pltBehavior = PaletteCmd::KeepColorModelPlt; - break; - case 2: - pltBehavior = PaletteCmd::ReplaceColorModelPlt; - break; - case 3: - pltBehavior = PaletteCmd::AddColorModelPlt; - break; - default: - pltBehavior = PaletteCmd::KeepColorModelPlt; - break; + } + + PaletteCmd::ColorModelLoadingConfiguration config; + + // if the palette is locked, replace the color model's palette with the + // destination + if (palette->isLocked()) { + // do nothing as config will use behavior = ReplaceColorModelPlt by default + // config.behavior = PaletteCmd::ReplaceColorModelPlt; + } else { + std::set fpSet; + fpSet.insert(fp); + ColorModelBehaviorPopup popup(fpSet, 0); + int ret = popup.exec(); + if (ret == QDialog::Rejected) return; + popup.getLoadingConfiguration(config); } ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); - int paletteFrame = 0; + int isLoaded = + PaletteCmd::loadReferenceImage(paletteHandle, config, fp, scene); - PaletteCmd::loadReferenceImage(paletteHandle, pltBehavior, fp, paletteFrame, - scene); + if (0 != isLoaded) { + std::cout << "loadReferenceImage Failed for some reason." << std::endl; + return; + } - TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel(); - if (!level) return; - std::vector fids; - level->getFids(fids); - invalidateIcons(level, fids); + // no changes in the icon with replace (Keep the destination palette) option + if (config.behavior != PaletteCmd::ReplaceColorModelPlt) { + TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel(); + if (!level) return; + std::vector fids; + level->getFids(fids); + invalidateIcons(level, fids); + } } //----------------------------------------------------------------------------- @@ -333,7 +329,9 @@ void ColorModelViewer::pick(const QPoint &p) { StylePickerTool *spTool = dynamic_cast(tool); if (spTool && spTool->isOrganizePaletteActive()) { TPoint point = picker.getRasterPoint(pos); - PaletteCmd::organizePaletteStyle(ph, styleIndex, point); + int frame = m_flipConsole->getCurrentFrame() - 1; + PaletteCmd::organizePaletteStyle( + ph, styleIndex, TColorStyle::PickedPosition(point, frame)); } } @@ -620,7 +618,8 @@ void ColorModelViewer::repickFromColorModel() { TPaletteHandle *ph = TApp::instance()->getPaletteController()->getCurrentLevelPalette(); - PaletteCmd::pickColorByUsingPickedPosition(ph, img); + PaletteCmd::pickColorByUsingPickedPosition( + ph, img, m_flipConsole->getCurrentFrame() - 1); } //============================================================================= diff --git a/toonz/sources/toonz/filebrowserpopup.cpp b/toonz/sources/toonz/filebrowserpopup.cpp index 0b3b5b5..4c276c3 100644 --- a/toonz/sources/toonz/filebrowserpopup.cpp +++ b/toonz/sources/toonz/filebrowserpopup.cpp @@ -14,6 +14,7 @@ #include "columnselection.h" #include "convertpopup.h" #include "matchline.h" +#include "colormodelbehaviorpopup.h" // TnzQt includes #include "toonzqt/gutil.h" @@ -1822,7 +1823,6 @@ bool LoadColorModelPopup::execute() { const TFilePath &fp = *m_selectedPaths.begin(); - int index = 0; TPaletteHandle *paletteHandle = TApp::instance()->getPaletteController()->getCurrentLevelPalette(); @@ -1832,43 +1832,18 @@ bool LoadColorModelPopup::execute() { return false; } - PaletteCmd::ColorModelPltBehavior pltBehavior; + PaletteCmd::ColorModelLoadingConfiguration config; // if the palette is locked, replace the color model's palette with the // destination - if (palette->isLocked()) - pltBehavior = PaletteCmd::ReplaceColorModelPlt; - else { - std::string type(fp.getType()); - QString question( - QObject::tr("The color model palette is different from the destination " - "palette.\nWhat do you want to do? ")); - QList list; - list.append(QObject::tr("Overwrite the destination palette.")); - list.append(QObject::tr( - "Keep the destination palette and apply it to the color model.")); - /*- if the file is raster image (i.e. without palette), then add another - * option "add styles" -*/ - if (type != "tlv" && type != "pli") - list.append( - QObject::tr("Add color model's palette to the destination palette.")); - int ret = DVGui::RadioButtonMsgBox(DVGui::WARNING, question, list); - switch (ret) { - case 0: - return false; - case 1: - pltBehavior = PaletteCmd::KeepColorModelPlt; - break; - case 2: - pltBehavior = PaletteCmd::ReplaceColorModelPlt; - break; - case 3: - pltBehavior = PaletteCmd::AddColorModelPlt; - break; - default: - pltBehavior = PaletteCmd::KeepColorModelPlt; - break; - } + if (palette->isLocked()) { + // do nothing as config will use behavior = ReplaceColorModelPlt by default + // config.behavior = PaletteCmd::ReplaceColorModelPlt; + } else { + ColorModelBehaviorPopup popup(m_selectedPaths, 0); + int ret = popup.exec(); + if (ret == QDialog::Rejected) return false; + popup.getLoadingConfiguration(config); } std::vector framesInput = string2Indexes(m_paletteFrame->text()); @@ -1880,9 +1855,8 @@ bool LoadColorModelPopup::execute() { ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); - int isLoaded = PaletteCmd::loadReferenceImage(paletteHandle, pltBehavior, fp, - index, scene, framesInput); - + int isLoaded = PaletteCmd::loadReferenceImage(paletteHandle, config, fp, + scene, framesInput); // return value - isLoaded // 2: failed to get palette // 1: failed to get image @@ -1899,7 +1873,7 @@ bool LoadColorModelPopup::execute() { } // no changes in the icon with replace (Keep the destination palette) option - if (pltBehavior != PaletteCmd::ReplaceColorModelPlt) { + if (config.behavior != PaletteCmd::ReplaceColorModelPlt) { TXshLevel *level = TApp::instance()->getCurrentLevel()->getLevel(); if (!level) return true; std::vector fids; diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index cc03d35..8193bb6 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -837,12 +837,6 @@ void PreferencesPopup::onShowFrameNumberWithLettersChanged(int index) { //----------------------------------------------------------------------------- -void PreferencesPopup::onPaletteTypeForRasterColorModelChanged(int index) { - m_pref->setPaletteTypeOnLoadRasterImageAsColorModel(index); -} - -//----------------------------------------------------------------------------- - void PreferencesPopup::onShowKeyframesOnCellAreaChanged(int index) { m_pref->enableShowKeyframesOnXsheetCellArea(index == Qt::Checked); } @@ -1343,8 +1337,6 @@ PreferencesPopup::PreferencesPopup() m_removeLevelFormat = new QPushButton("-"); m_editLevelFormat = new QPushButton(tr("Edit")); - QComboBox *paletteTypeForRasterColorModelComboBox = new QComboBox(this); - m_importPolicy = new QComboBox; //--- Import/Export ------------------------------ @@ -1707,13 +1699,6 @@ PreferencesPopup::PreferencesPopup() rebuildFormatsList(); - QStringList paletteTypes; - paletteTypes << tr("Pick Every Colors as Different Styles") - << tr("Integrate Similar Colors as One Style"); - paletteTypeForRasterColorModelComboBox->addItems(paletteTypes); - paletteTypeForRasterColorModelComboBox->setCurrentIndex( - m_pref->getPaletteTypeOnLoadRasterImageAsColorModel()); - QStringList policies; policies << tr("Always ask before loading or importing") << tr("Always import the file to the current project") @@ -2172,12 +2157,6 @@ PreferencesPopup::PreferencesPopup() cacheLay->addWidget(m_addLevelFormat, 2, 2); cacheLay->addWidget(m_removeLevelFormat, 2, 3); cacheLay->addWidget(m_editLevelFormat, 2, 4); - - cacheLay->addWidget( - new QLabel( - tr("Palette Type on Loading Raster Image as Color Model:")), - 3, 0, 1, 6); - cacheLay->addWidget(paletteTypeForRasterColorModelComboBox, 4, 1, 1, 5); } cacheLay->setColumnStretch(0, 0); cacheLay->setColumnStretch(1, 0); @@ -2755,9 +2734,6 @@ PreferencesPopup::PreferencesPopup() SLOT(onRemoveLevelFormat())); ret = ret && connect(m_editLevelFormat, SIGNAL(clicked()), SLOT(onEditLevelFormat())); - ret = ret && connect(paletteTypeForRasterColorModelComboBox, - SIGNAL(currentIndexChanged(int)), this, - SLOT(onPaletteTypeForRasterColorModelChanged(int))); ret = ret && connect(m_importPolicy, SIGNAL(currentIndexChanged(int)), SLOT(onImportPolicyChanged(int))); ret = ret && connect(TApp::instance()->getCurrentScene(), diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h index 91ed6ae..4030d2c 100644 --- a/toonz/sources/toonz/preferencespopup.h +++ b/toonz/sources/toonz/preferencespopup.h @@ -185,7 +185,6 @@ private slots: void onRemoveSceneNumberFromLoadedLevelNameChanged(int index); void onShowRasterImageDarkenBlendedInViewerChanged(int index); void onShowFrameNumberWithLettersChanged(int index); - void onPaletteTypeForRasterColorModelChanged(int index); void onShowKeyframesOnCellAreaChanged(int); void onFfmpegPathChanged(); void onFfmpegTimeoutChanged(); diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc index 217c266..929bd1b 100644 --- a/toonz/sources/toonz/toonz.qrc +++ b/toonz/sources/toonz/toonz.qrc @@ -459,5 +459,8 @@ Resources/zoom_out.svg Resources/zoom_in_rollover.svg Resources/zoom_out_rollover.svg + Resources/colorchiporder_leftup.svg + Resources/colorchiporder_lowleft.svg + Resources/colorchiporder_upleft.svg diff --git a/toonz/sources/toonzlib/palettecmd.cpp b/toonz/sources/toonzlib/palettecmd.cpp index 63fdd52..bd8a16f 100644 --- a/toonz/sources/toonzlib/palettecmd.cpp +++ b/toonz/sources/toonzlib/palettecmd.cpp @@ -803,119 +803,144 @@ public: //------------------------------------------------------------------- int loadRefImage(TPaletteHandle *paletteHandle, - PaletteCmd::ColorModelPltBehavior pltBehavior, - TPaletteP levelPalette, const TFilePath &_fp, int &frame, + const PaletteCmd::ColorModelLoadingConfiguration &config, + TPaletteP levelPalette, const TFilePath &_fp, ToonzScene *scene, const std::vector &frames) { - bool paletteAlreadyLoaded = false; - TFilePath fp = scene->decodeFilePath(_fp); - if (_fp == TFilePath()) { - paletteAlreadyLoaded = true; - fp = levelPalette->getRefImgPath(); - } + TFilePath fp = scene->decodeFilePath(_fp); - TImageP img; + // enable to store multiple frames in the level + QList imgs; try { TLevelReaderP lr(fp); - if (fp != TFilePath() && lr) { - TLevelP level = lr->loadInfo(); - if (level && level->getFrameCount() > 0) { - TLevel::Iterator it; - if (!paletteAlreadyLoaded) { - std::vector fids; - for (it = level->begin(); it != level->end(); ++it) { - if (it->first == -1 || it->first == -2) { - assert(level->getFrameCount() == 1); - fids.push_back(0); - break; - } - // if the frame list is empty, store all fids of the level - if (frames.empty()) { - fids.push_back(it->first); - continue; - } - // if the frame list is specified, load only the frames matches with - // the list - else { - std::vector::const_iterator framesIt; - for (framesIt = frames.begin(); framesIt != frames.end(); - framesIt++) { - if (it->first.getNumber() == *framesIt) { - fids.push_back(it->first); - break; - } - } - } + if (!lr) return 1; + + TLevelP level = lr->loadInfo(); + if (!level || level->getFrameCount() <= 0) return 1; + + TLevel::Iterator it; + std::vector fids; + for (it = level->begin(); it != level->end(); ++it) { + if (it->first == -1 || it->first == -2) { + assert(level->getFrameCount() == 1); + fids.push_back(it->first); + break; + } + // if the frame list is empty, store all fids of the level + if (frames.empty()) { + fids.push_back(it->first); + continue; + } + // if the frame list is specified, load only the frames matches with + // the list + else { + std::vector::const_iterator framesIt; + for (framesIt = frames.begin(); framesIt != frames.end(); framesIt++) { + if (it->first.getNumber() == *framesIt) { + fids.push_back(it->first); + break; } - levelPalette->setRefLevelFids(fids); } + } + } + levelPalette->setRefLevelFids(fids); - if (frame <= 0) frame = level->begin()->first.getNumber(); - - const TLevel::Table *table = level->getTable(); - TFrameId fid(frame); + const TLevel::Table *table = level->getTable(); - if (table->find(fid) != table->end()) { - img = lr->getFrameReader(fid)->load(); - if (img && img->getPalette() == 0) { - if (paletteAlreadyLoaded || level->getPalette() != 0) + for (int f = 0; f < fids.size(); f++) { + TFrameId fid = fids.at(f); + if (table->find(fid) != table->end()) { + TImageP img = lr->getFrameReader(fid)->load(); + if (img) { + if (img->getPalette() == 0) { + if (level->getPalette() != 0) img->setPalette(level->getPalette()); else if ((fp.getType() == "tzp" || fp.getType() == "tzu")) img->setPalette(ToonzImageUtils::loadTzPalette( fp.withType("plt").withNoFrame())); } + imgs.push_back(img); } } - } else - img = levelPalette->getRefImg(); + } + } catch (TException &e) { std::wcout << L"error: " << e.getMessage() << std::endl; } catch (...) { std::cout << "error for other reasons" << std::endl; } - if (!img) return 1; - - if (paletteAlreadyLoaded) { - img->setPalette(0); - levelPalette->setRefImgPath(_fp); - return 0; - } + if (imgs.empty()) return 1; TUndo *undo = new SetReferenceImageUndo(levelPalette, paletteHandle); - if (pltBehavior != PaletteCmd::ReplaceColorModelPlt) // ret==1 or 3) + bool isRasterLevel = false; + if (TRasterImageP ri = imgs.first()) isRasterLevel = true; + + if (config.behavior != PaletteCmd::ReplaceColorModelPlt) // ret==1 or 3) { TPaletteP imagePalette; - if (TRasterImageP ri = img) { - TRaster32P raster = ri->getRaster(); - if (raster) { - std::set colors; - int colorCount = 256; - if (Preferences::instance() - ->getPaletteTypeOnLoadRasterImageAsColorModel() == 0) - /*-- 全ての異なるピクセルの色を別のStyleにする --*/ - TColorUtils::buildPrecisePalette(colors, raster, colorCount); - else - /*-- 似ている色をまとめて1つのStyleにする --*/ - TColorUtils::buildPalette(colors, raster, colorCount); - colors.erase(TPixel::Black); // il nero viene messo dal costruttore - // della TPalette - int pageIndex = 0; - if (pltBehavior == PaletteCmd::KeepColorModelPlt) - imagePalette = new TPalette(); - else { - imagePalette = levelPalette->clone(); - /*- Add new page and store color model's styles in it -*/ - pageIndex = - imagePalette->addPage(QObject::tr("color model").toStdWString()) - ->getIndex(); + // raster level case + if (isRasterLevel) { + int pageIndex = 0; + if (config.behavior == PaletteCmd::KeepColorModelPlt) + imagePalette = new TPalette(); + else { + imagePalette = levelPalette->clone(); + /*- Add new page and store color model's styles in it -*/ + pageIndex = + imagePalette->addPage(QObject::tr("color model").toStdWString()) + ->getIndex(); + } + + static const int maxColorCount = 1024; + + for (int i = 0; i < imgs.size(); i++) { + TRasterImageP ri = imgs.at(i); + if (!ri) continue; + TRaster32P raster = ri->getRaster(); + if (!raster) continue; + + int availableColorCount = maxColorCount - imagePalette->getStyleCount(); + if (availableColorCount <= 0) break; + + if (config.rasterPickType == PaletteCmd::PickColorChipGrid) { + // colors will be sorted according to config.colorChipOrder + QList> colors; + TColorUtils::buildColorChipPalette( + colors, raster, availableColorCount, config.gridColor, + config.gridLineWidth, config.colorChipOrder); + + QList>::const_iterator it = colors.begin(); + for (; it != colors.end(); ++it) { + int indexInPage = + imagePalette->getPage(pageIndex)->addStyle((*it).first); + imagePalette->getPage(pageIndex) + ->getStyle(indexInPage) + ->setPickedPosition((*it).second, i); + } + } else { + // colors will be automatically sorted by comparing (uint)TPixel32 + // values + std::set colors; + if (config.rasterPickType == PaletteCmd::PickEveryColors) { + // different colors will become sparate styles + TColorUtils::buildPrecisePalette(colors, raster, + availableColorCount); + } else { // config.rasterPickType == + // PaletteCmd::IntegrateSimilarColors + // relevant colors will united as one style + TColorUtils::buildPalette(colors, raster, availableColorCount); + } + colors.erase(TPixel::Black); // il nero viene messo dal costruttore + // della TPalette + + std::set::const_iterator it = colors.begin(); + for (; it != colors.end(); ++it) + imagePalette->getPage(pageIndex)->addStyle(*it); } - std::set::const_iterator it = colors.begin(); - for (; it != colors.end(); ++it) - imagePalette->getPage(pageIndex)->addStyle(*it); } } else - imagePalette = img->getPalette(); + imagePalette = imgs.first()->getPalette(); if (imagePalette) { std::wstring gName = levelPalette->getGlobalName(); @@ -940,7 +965,7 @@ int loadRefImage(TPaletteHandle *paletteHandle, } } - img->setPalette(0); + // img->setPalette(0); levelPalette->setRefImgPath(_fp); @@ -962,20 +987,19 @@ int loadRefImage(TPaletteHandle *paletteHandle, //------------------------------------------------------------------- int PaletteCmd::loadReferenceImage(TPaletteHandle *paletteHandle, - ColorModelPltBehavior pltBehavior, - const TFilePath &_fp, int &frame, - ToonzScene *scene, + const ColorModelLoadingConfiguration &config, + const TFilePath &_fp, ToonzScene *scene, const std::vector &frames) { TPaletteP levelPalette = paletteHandle->getPalette(); if (!levelPalette) return 2; - int ret = loadRefImage(paletteHandle, pltBehavior, levelPalette, _fp, frame, - scene, frames); + int ret = + loadRefImage(paletteHandle, config, levelPalette, _fp, scene, frames); if (ret != 0) return ret; // when choosing replace(Keep the destination palette), dirty flag is // unchanged - if (pltBehavior != ReplaceColorModelPlt) { + if (config.behavior != ReplaceColorModelPlt) { levelPalette->setDirtyFlag(true); paletteHandle->notifyPaletteDirtyFlagChanged(); } @@ -1185,12 +1209,12 @@ class setStylePickedPositionUndo final : public TUndo { TPaletteHandle *m_paletteHandle; // Used in undo and redo to notify change int m_styleId; TPaletteP m_palette; - TPoint m_newPos; - TPoint m_oldPos; + TColorStyle::PickedPosition m_newPos; + TColorStyle::PickedPosition m_oldPos; public: setStylePickedPositionUndo(TPaletteHandle *paletteHandle, int styleId, - const TPoint &newPos) + const TColorStyle::PickedPosition &newPos) : m_paletteHandle(paletteHandle), m_styleId(styleId), m_newPos(newPos) { m_palette = paletteHandle->getPalette(); assert(m_palette); @@ -1215,15 +1239,16 @@ public: return QObject::tr("Set Picked Position of Style#%1 in Palette%2 : %3,%4") .arg(QString::number(m_styleId)) .arg(QString::fromStdWString(m_palette->getPaletteName())) - .arg(QString::number(m_newPos.x)) - .arg(QString::number(m_newPos.y)); + .arg(QString::number(m_newPos.pos.x)) + .arg(QString::number(m_newPos.pos.y)); } int getHistoryType() override { return HistoryType::Palette; } }; } -void PaletteCmd::organizePaletteStyle(TPaletteHandle *paletteHandle, - int styleId, const TPoint &point) { +void PaletteCmd::organizePaletteStyle( + TPaletteHandle *paletteHandle, int styleId, + const TColorStyle::PickedPosition &point) { if (!paletteHandle) return; TPalette *palette = paletteHandle->getPalette(); if (!palette) return; @@ -1315,7 +1340,7 @@ TPixel32 pickColor(TRasterImageP ri, const TPoint &rasterPoint) { } void PaletteCmd::pickColorByUsingPickedPosition(TPaletteHandle *paletteHandle, - TImageP img) { + TImageP img, int frame) { TRasterImageP ri = img; if (!ri) return; @@ -1328,10 +1353,12 @@ void PaletteCmd::pickColorByUsingPickedPosition(TPaletteHandle *paletteHandle, // For all styles (starting from #1 as #0 is reserved for the transparent) for (int sId = 1; sId < currentPalette->getStyleCount(); sId++) { TColorStyle *style = currentPalette->getStyle(sId); - TPoint pp = style->getPickedPosition(); + TPoint pp = style->getPickedPosition().pos; + int pickedFrame = style->getPickedPosition().frame; // If style has a valid picked position - if (pp != TPoint() && pp.x >= 0 && pp.x < imgSize.lx && pp.y >= 0 && - pp.y < imgSize.ly && style->hasMainColor()) { + if (pp != TPoint() && frame == pickedFrame && pp.x >= 0 && + pp.x < imgSize.lx && pp.y >= 0 && pp.y < imgSize.ly && + style->hasMainColor()) { TPixel32 beforeColor = style->getMainColor(); TPixel32 afterColor = pickColor(ri, pp); style->setMainColor(afterColor); diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index 989f437..c48f822 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -312,7 +312,6 @@ Preferences::Preferences() , m_onionSkinDuringPlayback(false) , m_dropdownShortcutsCycleOptions(false) , m_multiLayerStylePickerEnabled(false) - , m_paletteTypeOnLoadRasterImageAsColorModel(0) , m_showKeyframesOnXsheetCellArea(true) , m_projectRoot(0x08) , m_customProjectRoot("") @@ -620,8 +619,6 @@ Preferences::Preferences() getValue(*m_settings, "onionSkinDuringPlayback", m_onionSkinDuringPlayback); getValue(*m_settings, "multiLayerStylePickerEnabled", m_multiLayerStylePickerEnabled); - getValue(*m_settings, "paletteTypeOnLoadRasterImageAsColorModel", - m_paletteTypeOnLoadRasterImageAsColorModel); getValue(*m_settings, "showKeyframesOnXsheetCellArea", m_showKeyframesOnXsheetCellArea); QString ffmpegPath = m_settings->value("ffmpegPath").toString(); @@ -1462,13 +1459,6 @@ void Preferences::setVectorSnappingTarget(int target) { //----------------------------------------------------------------- -void Preferences::setPaletteTypeOnLoadRasterImageAsColorModel(int type) { - m_paletteTypeOnLoadRasterImageAsColorModel = type; - m_settings->setValue("paletteTypeOnLoadRasterImageAsColorModel", type); -} - -//----------------------------------------------------------------- - void Preferences::setFfmpegPath(std::string path) { m_ffmpegPath = QString::fromStdString(path); std::string strPath = m_ffmpegPath.toStdString(); diff --git a/toonz/sources/toonzqt/paletteviewergui.cpp b/toonz/sources/toonzqt/paletteviewergui.cpp index c6859e2..f85439e 100644 --- a/toonz/sources/toonzqt/paletteviewergui.cpp +++ b/toonz/sources/toonzqt/paletteviewergui.cpp @@ -465,7 +465,7 @@ void PageViewer::drawColorName(QPainter &p, QRect &nameRect, TColorStyle *style, name += " " + toQString(g.first) + ":" + QString::number(g.second); if (style->getFlags() != 0) name += "(autopaint)"; - TPoint pickedPos = style->getPickedPosition(); + TPoint pickedPos = style->getPickedPosition().pos; if (pickedPos != TPoint()) name += QString(" (%1,%2)").arg(pickedPos.x).arg(pickedPos.y); @@ -833,7 +833,8 @@ void PageViewer::paintEvent(QPaintEvent *e) { } // draw "Picked Position" indicator (not show on small chip mode) - if (style->getPickedPosition() != TPoint() && m_viewMode != SmallChips) { + if (style->getPickedPosition().pos != TPoint() && + m_viewMode != SmallChips) { QRect ppRect(chipRect.bottomLeft() + QPoint(offset, -14), QSize(12, 15)); p.drawRect(ppRect); diff --git a/toonz/sources/toonzqt/styleeditor.cpp b/toonz/sources/toonzqt/styleeditor.cpp index 704e4d2..26586b2 100644 --- a/toonz/sources/toonzqt/styleeditor.cpp +++ b/toonz/sources/toonzqt/styleeditor.cpp @@ -3335,7 +3335,7 @@ void StyleEditor::onStyleSwitched() { statusText += QString::fromStdWString(L" | #"); statusText += QString::number(styleIndex); statusText += QString::fromStdWString(L" : " + m_editedStyle->getName()); - TPoint pickedPos = m_editedStyle->getPickedPosition(); + TPoint pickedPos = m_editedStyle->getPickedPosition().pos; if (pickedPos != TPoint()) statusText += QString(" (Picked from %1,%2)").arg(pickedPos.x).arg(pickedPos.y);