From f2d66cc922df8eccd58e018d2d82a14cbcb8ad0d Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Thu, 17 Aug 2023 15:14:15 -0400 Subject: [PATCH 1/8] Initial version Initial version of changes pending further work. --- toonz/sources/tnztools/filltool.cpp | 111 +++- toonz/sources/toonzlib/fill.cpp | 757 +++++++++++++++++++++++++--- 2 files changed, 795 insertions(+), 73 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 0539e25a..ee80618a 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -1029,24 +1029,113 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, if (fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); + std::cout << "\nfilltool.cpp:fillAreaWithUndo"; + std::cout << "\n---- y:"; + std::cout << tempRaster->getLy(); + std::cout << " x:"; + std::cout << tempRaster->getLx(); + std::cout << " paint:"; + std::cout << cs; + std::cout << "----"; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { + std::cout << "\n row:"; + std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - keepPix->setPaint(tempPix->getPaint()); - if (tempPix->getInk() != styleIndex) { - if (colorType == AREAS && closeGaps && tempPix->getInk() == 4095) { - keepPix->setInk(closeStyleIndex); - keepPix->setTone(tempPix->getTone()); - } else if (colorType != AREAS && tempPix->getInk() == 4095) { - keepPix->setInk(cs); - keepPix->setTone(tempPix->getTone()); - } else if (tempPix->getInk() != 4095) { - keepPix->setInk(tempPix->getInk()); + + std::cout << " a"; + std::cout << tempX; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); + std::cout << ":"; + std::cout << keepPix->getInk(); + std::cout << "."; + std::cout << keepPix->getPaint(); + std::cout << "."; + std::cout << keepPix->getTone(); + + if (tempPix->getInk() == 4095 || + tempPix->getInk() == styleIndex) { + if (fillGaps || closeGaps) { + // does this pixel have a fill pixel neighbor? + if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && + (tempPix - 1)->isPurePaint()) // west + || ((tempX < tempRaster->getLx()) && + ((tempPix + 1)->getPaint() == cs) && + (tempPix + 1)->isPurePaint()) // east + || + ((tempPix + tempRaster->getWrap())->getPaint() == cs && + (tempPix + tempRaster->getWrap())->isPurePaint()) // north + || + ((tempPix - tempRaster->getWrap())->getPaint() == cs && + (tempPix - tempRaster->getWrap())->isPurePaint()) // south + ) { // yes, keep this pixel + if (closeGaps && + (((tempX > 0) && (tempPix - 1)->getPaint() == 0 && + (tempPix - 1)->isPurePaint()) // west + || ((tempX < tempRaster->getLx()) && + ((tempPix + 1)->getPaint() == 0) && + (tempPix + 1)->isPurePaint()) // east + || ((tempPix + tempRaster->getWrap())->getPaint() == 0 && + (tempPix + tempRaster->getWrap()) + ->isPurePaint()) // north + || ((tempPix - tempRaster->getWrap())->getPaint() == 0 && + (tempPix - tempRaster->getWrap()) + ->isPurePaint()) // south + )) { // keep as ink line + std::cout << " i:"; + std::cout << tempY; + std::cout << ":"; + std::cout << tempX; + keepPix->setInk(closeStyleIndex); + keepPix->setPaint(cs); + keepPix->setTone(0); + } else { // keep as paint + // keepPix->setInk(paint); + std::cout << " p:"; + std::cout << tempY; + std::cout << ":"; + std::cout << tempX; + keepPix->setPaint(cs); + keepPix->setTone(255); + } + } + } else { + // Ignore unwanted gap close pixels. + // Should not reach this code because those pixels should not be + // generated prior to this code without fillGaps or closeGaps set + // to true. } + } else { + // Handle all other pixels + keepPix->setInk(tempPix->getInk()); + keepPix->setPaint(tempPix->getPaint()); + keepPix->setTone(tempPix->getTone()); + } + + std::cout << " b"; + std::cout << tempX; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); + std::cout << ":"; + std::cout << keepPix->getInk(); + std::cout << "."; + std::cout << keepPix->getPaint(); + std::cout << "."; + std::cout << keepPix->getTone(); + } } } - } + TPalette *plt = ti->getPalette(); diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index abe7bf0f..220d8fbb 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -47,14 +47,14 @@ inline TPoint nearestInkNotDiagonal(const TRasterCM32P &r, const TPoint &p) { } // -// from point x, y expands to the rightand left. +// from point x, y expands to the right and left. // the redrawn line goes from* xa to* xb inclusive // x1 <= *xa <= *xb <= x2 // N.B. if not even one pixel is drawn* xa > * xb // // "prevailing" is set to false on revert-filling the border of // region in the Rectangular, Freehand and Polyline fill procedures -// in order to make the paint to protlude behind the line. +// in order to make the paint extend behind the line. // Calculates the endpoints for the line of pixels in which to fill bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, @@ -71,15 +71,63 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, limit = line + r->getBounds().x1; oldtone = pix->getTone(); tone = oldtone; + std::cout << "calcFillRow xa:"; + std::cout << xa; + std::cout << " xb:"; + std::cout << xb; for (; pix <= limit; pix++) { - if (pix->getPaint() == paint) break; - if (emptyOnly && pix->getPaint() != 0) break; + std::cout << " x:"; + std::cout << p.x + pix - pix0; + if (pix->getPaint() == paint) { + std::cout << " r_eq_paint:"; + std::cout << paint; + std::cout << "_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + //break; + } + if (emptyOnly && pix->getPaint() != 0) { + std::cout << " r_(emptyOnly&&pix->getPaint()!=0)_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + //break; + } tone = pix->getTone(); - if (tone == 0) break; + if (tone == 0) { + std::cout << " r_(tone==0)_x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } // prevent fill area from protruding behind the colored line if (tone > oldtone) { + std::cout << " r_tone>oldtone_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); // not-yet-colored line case if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint()) + std::cout << " prevailing_or_notPurePaint_or_inkNotEqPaint_x:"; + std::cout << p.x + pix - pix0; break; while (pix != pix0) { // iterate back in order to leave the pixel with the lowest tone @@ -95,8 +143,17 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, TPixelCM32 *downPix = pix + r->getWrap(); if (upPix->getTone() > pix->getTone() && downPix->getTone() > pix->getTone()) + std::cout << " l_getTone()>oldtone_continue"; continue; } + std::cout << " r_getTone()>oldtone_x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); break; } } @@ -109,12 +166,22 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, tmp_limit = pix + 10; // edge stop fill == 10 per default if (limit > tmp_limit) limit = tmp_limit; for (; pix <= limit; pix++) { - if (pix->getPaint() == paint) break; - if (pix->getTone() != 0) break; + //if (pix->getPaint() == paint) break; // commented out for issue 1151 + if (pix->getTone() != 0) { + std::cout << " r_(tone!=0)_x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } } } - xb = p.x + pix - pix0 - 1; + xb = p.x + pix - pix0 - 1; //go backward one pixel from the current pixel which triggered the boundary condition. /* go left */ @@ -123,15 +190,57 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, oldtone = pix->getTone(); tone = oldtone; for (pix--; pix >= limit; pix--) { - if (pix->getPaint() == paint) break; - if (emptyOnly && pix->getPaint() != 0) break; + if (pix->getPaint() == paint) { + std::cout << " l_eq_paint:"; + std::cout << paint; + std::cout << "_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } + if (emptyOnly && pix->getPaint() != 0) { + std::cout << " l_getPaint!=0_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } tone = pix->getTone(); - if (tone == 0) break; + if (tone == 0) { + std::cout << " l_(tone==0)_x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } // prevent fill area from protruding behind the colored line if (tone > oldtone) { + std::cout << " l_tone>oldtone_x:"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); // not-yet-colored line case - if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint()) - break; + if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint()){ + std::cout << " prevailing_notPurePaint_or_pix_ink!=pix_paint"; + break; + } while (pix != pix0) { // iterate forward in order to leave the pixel with the lowest tone // unpainted @@ -145,9 +254,19 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, TPixelCM32 *upPix = pix - r->getWrap(); TPixelCM32 *downPix = pix + r->getWrap(); if (upPix->getTone() > pix->getTone() && - downPix->getTone() > pix->getTone()) - continue; + downPix->getTone() > pix->getTone()) { + std::cout << " l_getTone()>oldtone_continue"; + continue; + } } + std::cout << " l_getTone()>oldtone_x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); break; } } @@ -160,12 +279,22 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, tmp_limit = pix - 10; if (limit < tmp_limit) limit = tmp_limit; for (; pix >= limit; pix--) { - if (pix->getPaint() == paint) break; - if (pix->getTone() != 0) break; + //if (pix->getPaint() == paint) break; // commented out for issue 1151 + if (pix->getTone() != 0) { + std::cout << " l_(tone!=0) x"; + std::cout << p.x + pix - pix0; + std::cout << ":"; + std::cout << pix->getInk(); + std::cout << "."; + std::cout << pix->getPaint(); + std::cout << "."; + std::cout << pix->getTone(); + break; + } } } - xa = p.x + pix - pix0 + 1; + xa = p.x + pix - pix0 + 1; //go backward one pixel from the current pixel which triggered the boundary condition. return (xb >= xa); } @@ -177,6 +306,7 @@ void findSegment(const TRaster32P &r, const TPoint &p, int &xa, int &xb, int matte, oldmatte; TPixel32 *pix, *pix0, *limit, *tmp_limit; + std::cout << "\nanonymous-namespace.findSegment "; /* vai a destra */ TPixel32 *line = r->pixels(p.y); @@ -221,6 +351,11 @@ void findSegment(const TRaster32P &r, const TPoint &p, int &xa, int &xb, } } xa = p.x + pix - pix0 + 1; + + std::cout << " xa:"; + std::cout << xa; + std::cout << " xb:"; + std::cout << xb; } //----------------------------------------------------------------------------- @@ -326,6 +461,8 @@ inline int threshTone(const TPixelCM32 &pix, int fillDepth) { void fillRow(const TRasterCM32P &r, const TPoint &p, int xa, int xb, int paint, TPalette *palette, TTileSaverCM32 *saver) { + std::cout << " paint_4:"; + std::cout << paint; /* vai a destra */ TPixelCM32 *line = r->pixels(p.y); TPixelCM32 *pix = line + p.x; @@ -435,6 +572,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TTileSaverCM32 *saver, bool fillGaps, bool closeGaps, int closeStyleIndex, double autoCloseDistance, TXsheet *xsheet, int frameIndex) { + std::cout << "\nGlobalScope.fill_2"; auto fullColorThreshMatte = [](int matte, int fillDepth) -> int { return (matte <= fillDepth) ? matte : 255; }; @@ -447,6 +585,8 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TPoint p = params.m_p; int x = p.x, y = p.y; int paint = params.m_styleId; + std::cout << " paint_1=:"; + std::cout << paint; int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth; TRasterCM32P tempRaster; @@ -575,29 +715,135 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, std::stack seeds; + std::cout << "\ny:"; + std::cout << y; + std::cout << " "; + + std::cout << " paint_2=:"; + std::cout << paint; + bool fillIt = !xsheet ? calcFillRow(tempRaster, p, xa, xb, paint, params.m_palette, params.m_prevailing, params.m_emptyOnly) : calcRefFillRow(refRaster, p, xa, xb, color, clickedPosColor, fillDepth); + std::cout << " paint_3=:"; + std::cout << paint; + if (fillIt) fillRow(tempRaster, p, xa, xb, paint, params.m_palette, saver); if (xsheet) segments[y].push_back(std::pair(xa, xb)); seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - // Set the ink on gaps that were used to 4095 - { + + // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 1 of 2 + if (fillGaps || closeGaps) { + std::cout << "\nY:"; + std::cout << y; + std::cout << " xa:"; + std::cout << xa; + std::cout << " xb:"; + std::cout << xb; + TPixelCM32 *tempPix = tempRaster->pixels(0); tempPix += (y * tempRaster->getLx()) + xa - 1; int i = xa; + // std::cout << "\n1:"; + // std::cout << y; + // std::cout << ":i:"; + // std::cout << i; + // std::cout << ":xb:"; + // std::cout << xb; + while (i <= xb) { - if (tempPix->getInk() == styleIndex) { - tempPix->setInk(fakeStyleIndex); + std::cout << " a1:"; + std::cout << i; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); + + // if (tempPix->getInk() == styleIndex) { + // tempPix->setInk(fakeStyleIndex); + // //std::cout << " *4095* "; + //} + + if (tempPix->getPaint() == paint) { + // check for neighboring gap pixels and finalize them + // west + if ((tempPix - 1)->getInk() == styleIndex) { + if (closeGaps) { + // keep as ink pixel + (tempPix - 1)->setInk(closeStyleIndex); + (tempPix - 1)->setPaint(paint); + (tempPix - 1)->setTone(0); + } else { + // keep as paint pixel + (tempPix - 1)->setInk(0); + (tempPix - 1)->setPaint(paint); + (tempPix - 1)->setTone(255); + } + } + // east + if ((tempPix + 1)->getInk() == styleIndex) { + if (closeGaps) { + // keep as ink pixel + (tempPix + 1)->setInk(closeStyleIndex); + (tempPix + 1)->setPaint(paint); + (tempPix + 1)->setTone(0); + } else { + // keep as paint pixel + (tempPix + 1)->setInk(0); + (tempPix + 1)->setPaint(paint); + (tempPix + 1)->setTone(255); + } + } + // north + if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { + if (closeGaps) { + // keep as ink pixel + (tempPix + tempRaster->getWrap())->setInk(closeStyleIndex); + (tempPix + tempRaster->getWrap())->setPaint(paint); + (tempPix + tempRaster->getWrap())->setTone(0); + } else { + // keep as paint pixel + (tempPix + tempRaster->getWrap())->setInk(0); + (tempPix + tempRaster->getWrap())->setPaint(paint); + (tempPix + tempRaster->getWrap())->setTone(255); + } + } + // south + if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { + if (closeGaps) { + // keep as ink pixel + (tempPix - tempRaster->getWrap())->setInk(closeStyleIndex); + (tempPix - tempRaster->getWrap())->setPaint(paint); + (tempPix - tempRaster->getWrap())->setTone(0); + } else { + // keep as paint pixel + (tempPix - tempRaster->getWrap())->setInk(0); + (tempPix - tempRaster->getWrap())->setPaint(paint); + (tempPix - tempRaster->getWrap())->setTone(255); + } + } } + + std::cout << " b1:"; + std::cout << i; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); tempPix++; i++; } } +std::cout << "\nFill-Seeds"; + while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); @@ -638,6 +884,9 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, floodCheck(clickedPosColor, refpix, oldrefpix, fillDepth); } if (canPaint) { + std::cout << "\ny:"; + std::cout << y; + std::cout << " "; bool fillIt = !xsheet ? calcFillRow(tempRaster, TPoint(x, y), xc, xd, paint, params.m_palette, params.m_prevailing) @@ -647,19 +896,185 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, fillRow(tempRaster, TPoint(x, y), xc, xd, paint, params.m_palette, saver); if (xsheet) insertSegment(segments[y], std::pair(xc, xd)); + // Set the ink on gaps that were used to 4095 - { + // + //{ + // TPixelCM32 *tempPix = tempRaster->pixels(0); + // tempPix += (y * tempRaster->getLx()) + xa - 1; + // int i = xa; + // //std::cout << "\n2:"; + // //std::cout << y; + // //std::cout << ":i:"; + // //std::cout << i; + // //std::cout << ":xb:"; + // //std::cout << xb; + + // while (i <= xb) { + // //std::cout << " a2:"; + // //std::cout << i; + // //std::cout << ":"; + // //std::cout << tempPix->getInk(); + // //std::cout << "."; + // //std::cout << tempPix->getPaint(); + // //std::cout << "."; + // //std::cout << tempPix->getTone(); + + // if (tempPix->getInk() == styleIndex) { + // tempPix->setInk(fakeStyleIndex); + // //std::cout << " *4095* "; + // } + // //// check the neighboring pixels for gap close ink + // //// west + // //if (i == xa) { + // // if ((tempPix - 1)->getInk() == styleIndex) { + // // (tempPix - 1)->setInk(fakeStyleIndex); + // // //std::cout << " *4095 w* "; + // // } + // //} + // //// east + // //if (i == xb) { + // // if ((tempPix + 1)->getInk() == styleIndex) { + // // (tempPix + 1)->setInk(fakeStyleIndex); + // // //std::cout << " *4095 e* "; + // // } + // //} + // //// north + // //if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { + // // (tempPix + tempRaster->getWrap())->setInk(fakeStyleIndex); + // // //std::cout << " *4095 n* "; + // //} + // //// south + // //if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { + // // (tempPix - tempRaster->getWrap())->setInk(fakeStyleIndex); + // // //std::cout << " *4095 s* "; + // //} + // //std::cout << " b2:"; + // //std::cout << i; + // //std::cout << ":"; + // //std::cout << tempPix->getInk(); + // //std::cout << "."; + // //std::cout << tempPix->getPaint(); + // //std::cout << "."; + // //std::cout << tempPix->getTone(); + + // tempPix++; + // i++; + // } + //} + + // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 2 of 2 + if (fillGaps || closeGaps) { + std::cout << "\nY:"; + std::cout << y; + std::cout << " xa:"; + std::cout << xa; + std::cout << " xb:"; + std::cout << xb; + TPixelCM32 *tempPix = tempRaster->pixels(0); tempPix += (y * tempRaster->getLx()) + xa - 1; int i = xa; + // std::cout << "\n1:"; + // std::cout << y; + // std::cout << ":i:"; + // std::cout << i; + // std::cout << ":xb:"; + // std::cout << xb; + while (i <= xb) { - if (tempPix->getInk() == styleIndex) { - tempPix->setInk(fakeStyleIndex); + std::cout << " a2:"; + std::cout << i; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); + + // if (tempPix->getInk() == styleIndex) { + // tempPix->setInk(fakeStyleIndex); + // //std::cout << " *4095* "; + //} + + if (tempPix->getPaint() == paint) { + // check for neighboring gap pixels and finalize them + // west + if ((tempPix - 1)->getInk() == styleIndex) { + (tempPix - 1)->setInk(fakeStyleIndex); + //if (closeGaps) { + // // keep as ink pixel + // (tempPix - 1)->setInk(closeStyleIndex); + // (tempPix - 1)->setPaint(paint); + // (tempPix - 1)->setTone(0); + //} else { + // // keep as paint pixel + // (tempPix - 1)->setInk(0); + // (tempPix - 1)->setPaint(paint); + // (tempPix - 1)->setTone(255); + //} + } + // east + if ((tempPix + 1)->getInk() == styleIndex) { + (tempPix + 1)->setInk(fakeStyleIndex); + //if (closeGaps) { + // // keep as ink pixel + // (tempPix + 1)->setInk(closeStyleIndex); + // (tempPix + 1)->setPaint(paint); + // (tempPix + 1)->setTone(0); + //} else { + // // keep as paint pixel + // (tempPix + 1)->setInk(0); + // (tempPix + 1)->setPaint(paint); + // (tempPix + 1)->setTone(255); + //} + } + // north + if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { + (tempPix + tempRaster->getWrap())->setInk(fakeStyleIndex); + //if (closeGaps) { + // // keep as ink pixel + // (tempPix + tempRaster->getWrap())->setInk(closeStyleIndex); + // (tempPix + tempRaster->getWrap())->setPaint(paint); + // (tempPix + tempRaster->getWrap())->setTone(0); + //} else { + // // keep as paint pixel + // (tempPix + tempRaster->getWrap())->setInk(0); + // (tempPix + tempRaster->getWrap())->setPaint(paint); + // (tempPix + tempRaster->getWrap())->setTone(255); + //} + } + // south + if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { + (tempPix - tempRaster->getWrap())->setInk(fakeStyleIndex); + //if (closeGaps) { + // // keep as ink pixel + // (tempPix - tempRaster->getWrap())->setInk(closeStyleIndex); + // (tempPix - tempRaster->getWrap())->setPaint(paint); + // (tempPix - tempRaster->getWrap())->setTone(0); + //} else { + // // keep as paint pixel + // (tempPix - tempRaster->getWrap())->setInk(0); + // (tempPix - tempRaster->getWrap())->setPaint(paint); + // (tempPix - tempRaster->getWrap())->setTone(255); + //} + } } + + std::cout << " b2:"; + std::cout << i; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); tempPix++; i++; } - } + }// End: Set the ink on gaps that were used to their final value + + if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy)); if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy)); if (oldxd >= xc - 1) @@ -705,21 +1120,234 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, if (fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = r->pixels(); + std::cout << "\nfill_final_check----y:"; + std::cout << tempRaster->getLy(); + std::cout << ",x:"; + std::cout << tempRaster->getLx(); + std::cout << "----"; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { + //std::cout << "\n"; + //std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - if (tempPix->getInk() != styleIndex && - tempPix->getInk() != fakeStyleIndex) + //std::cout << " a"; + //std::cout << tempX; + //std::cout << ":"; + //std::cout << tempPix->getInk(); + //std::cout << "."; + //std::cout << tempPix->getPaint(); + //std::cout << "."; + //std::cout << tempPix->getTone(); + //std::cout << ":"; + //std::cout << keepPix->getInk(); + //std::cout << "."; + //std::cout << keepPix->getPaint(); + //std::cout << "."; + //std::cout << keepPix->getTone(); + + // if (tempPix->getInk() != styleIndex && + // tempPix->getInk() != fakeStyleIndex) { + // std::cout << "\ntempY:"; + // std::cout << tempY; + // std::cout << "\ttempX:"; + // std::cout << tempX; + // std::cout << "\ttemPix.getInk():"; + // std::cout << tempPix->getInk(); + // std::cout << "\ttemPix.getPaint():"; + // std::cout << tempPix->getPaint(); + // keepPix->setPaint(tempPix->getPaint()); + //} + // Handle pixels of gap close lines, 4094, 4095 + + if (tempPix->getInk() == fakeStyleIndex || + tempPix->getInk() == styleIndex) { + if (tempPix->getInk() == fakeStyleIndex) { + if(closeGaps){ //keep as ink pixel + keepPix->setInk(closeStyleIndex); + keepPix->setPaint(paint); + keepPix->setTone(0); + } else { //keep as paint pixel + keepPix->setInk(0); + keepPix->setPaint(paint); + keepPix->setTone(255); + } + }else{ + // an unused close gap pixel, so ignore + } + // if (fillGaps || closeGaps) { + // + + // std::cout << "\nNorth "; //north + // std::cout << tempY+1; + // std::cout << " "; + // std::cout << tempX; + // std::cout << ":"; + // std::cout << (tempPix + tempRaster->getWrap())->getInk(); + // std::cout << "."; + // std::cout << (tempPix + tempRaster->getWrap())->getPaint(); + // std::cout << "."; + // std::cout << (tempPix + tempRaster->getWrap())->getTone(); + // std::cout << ";"; + // std::cout << (keepPix + r->getWrap())->getInk(); + // std::cout << "."; + // std::cout << (keepPix + r->getWrap())->getPaint(); + // std::cout << "."; + // std::cout << (keepPix + r->getWrap())->getTone(); + + // std::cout << "\nWest:Center:East "; //west, center, east + // std::cout << tempY; + // std::cout << " "; + // // west + // std::cout << tempX-1; + // std::cout << ":"; + // std::cout << (tempPix - 1)->getInk(); + // std::cout << "."; + // std::cout << (tempPix - 1)->getPaint(); + // std::cout << "."; + // std::cout << (tempPix - 1)->getTone(); + // std::cout << ";"; + // std::cout << (keepPix - 1)->getInk(); + // std::cout << "."; + // std::cout << (keepPix - 1)->getPaint(); + // std::cout << "."; + // std::cout << (keepPix - 1)->getTone(); + // // center + // std::cout << " "; + // std::cout << tempX; + // std::cout << ":"; + // std::cout << tempPix->getInk(); + // std::cout << "."; + // std::cout << tempPix->getPaint(); + // std::cout << "."; + // std::cout << tempPix->getTone(); + // std::cout << ";"; + // std::cout << keepPix->getInk(); + // std::cout << "."; + // std::cout << keepPix->getPaint(); + // std::cout << "."; + // std::cout << keepPix->getTone(); + // // east + // std::cout << " "; + // std::cout << tempX+1; + // std::cout << ":"; + // std::cout << (tempPix + 1)->getInk(); + // std::cout << "."; + // std::cout << (tempPix + 1)->getPaint(); + // std::cout << "."; + // std::cout << (tempPix + 1)->getTone(); + // std::cout << ";"; + // std::cout << (keepPix + 1)->getInk(); + // std::cout << "."; + // std::cout << (keepPix + 1)->getPaint(); + // std::cout << "."; + // std::cout << (keepPix + 1)->getTone(); + // // south + // std::cout << "\nSouth "; + // std::cout << tempY-1; + // std::cout << " "; + // std::cout << tempX; + // std::cout << ":"; + // std::cout << (tempPix - tempRaster->getWrap())->getInk(); + // std::cout << "."; + // std::cout << (tempPix - tempRaster->getWrap())->getPaint(); + // std::cout << "."; + // std::cout << (tempPix - tempRaster->getWrap())->getTone(); + // std::cout << ";"; + // std::cout << (keepPix - r->getWrap())->getInk(); + // std::cout << "."; + // std::cout << (keepPix - r->getWrap())->getPaint(); + // std::cout << "."; + // std::cout << (keepPix - r->getWrap())->getTone(); + + + // // does this pixel have a fill pixel neighbor that is new? + // if ( + // ((tempX > 0) && ((tempPix - 1)->getPaint() == paint) && (tempPix - 1)->isPurePaint() && !(((keepPix - 1)->getPaint() == paint) && (keepPix - 1)->isPurePaint()) ) // west + // || ((tempX < tempRaster->getLx()) && ((tempPix + 1)->getPaint() == paint) && (tempPix + 1)->isPurePaint() && !(((keepPix + 1)->getPaint() == paint) && (keepPix + 1)->isPurePaint()) ) // east + // || ((tempPix + tempRaster->getWrap())->getPaint() == paint && (tempPix + tempRaster->getWrap())->isPurePaint() && !((keepPix + r->getWrap())->getPaint() == paint && (keepPix + r->getWrap())->isPurePaint()) ) // north + // || ((tempPix - tempRaster->getWrap())->getPaint() == paint && (tempPix - tempRaster->getWrap())->isPurePaint() && !((keepPix - r->getWrap())->getPaint() == paint && (keepPix - r->getWrap())->isPurePaint()) ) // south + // ) {// yes, keep this pixel + // if (closeGaps + // && ( + // ((tempX > 0) && (tempPix - 1)->getPaint() == 0 && (tempPix - 1)->isPurePaint()) // west + // || ((tempX < tempRaster->getLx()) && ((tempPix + 1)->getPaint() == 0) && (tempPix + 1)->isPurePaint()) // east + // || ((tempPix + tempRaster->getWrap())->getPaint() == 0 && (tempPix + tempRaster->getWrap())->isPurePaint()) // north + // || ((tempPix - tempRaster->getWrap())->getPaint() == 0 && (tempPix - tempRaster->getWrap())->isPurePaint()) // south + // ) + // ){ //keep as ink line + // keepPix->setInk(closeStyleIndex); + // keepPix->setPaint(paint); + // keepPix->setTone(0); + // } else { //keep as paint + // //keepPix->setInk(paint); + // keepPix->setPaint(paint); + // keepPix->setTone(255); + // } + // } + // } else { + // // Ignore unwanted gap close pixels. + // // Should not reach this code as those pixels should not be + // // generated prior to this code without fillGaps or closeGaps set to + // // true. + // } + } else { + // + // Handle all other pixels + // + keepPix->setInk(tempPix->getInk()); keepPix->setPaint(tempPix->getPaint()); - // This next line takes care of autopaint lines - if (tempPix->getInk() != styleIndex) { - if (closeGaps && tempPix->getInk() == fakeStyleIndex) { - keepPix->setInk(closeStyleIndex); - keepPix->setTone(tempPix->getTone()); - } else if (tempPix->getInk() != fakeStyleIndex) { - keepPix->setInk(tempPix->getInk()); - } + keepPix->setTone(tempPix->getTone()); } + // This next line takes care of autopaint lines + //if (tempPix->getInk() != styleIndex) { //commented out by Tom + // //if (closeGaps && (tempPix->getInk() == fakeStyleIndex)) { + // if (tempPix->getInk() == fakeStyleIndex) { + // std::cout << "\n****** A pixel with ink 4095 was found ******\n"; + // if (closeGaps) { + // keepPix->setInk(closeStyleIndex); + // // the following two lines could set up a partial ink, partial paint pixel + // // keepPix->setPaint(closeStyleIndex); + // // keepPix->setTone(tempPix->getTone()); //commented out by Tom + // keepPix->setTone(0); + // } else { + // keepPix->setPaint(paint); + // keepPix->setTone(255); + // } + // } else { + // keepPix->setPaint(tempPix->getPaint()); + // keepPix->setTone(tempPix->getTone()); + // } + //} else { // handle tempPix->getInk() == styleIndex + //TPoint nearestPix = nearestInkNotDiagonal(tempRaster, TPoint(tempX, tempY)); + //std::cout << "\nfor pix y: "; + //std::cout << tempY; + //std::cout << " x: "; + //std::cout << tempX; + //std::cout << " nearest pix y: "; + //std::cout << nearestPix.y; + //std::cout << " x: "; + //std::cout << nearestPix.x; + // Is this pixel next to a pixel painted with current fill color? + // then keep + //keepPix->setInk(closeStyleIndex); + //keepPix->setTone(0); + // else, ignore + //keepPix->setTone(255); + //} + //std::cout << " b"; + //std::cout << tempX; + //std::cout << ":"; + //std::cout << tempPix->getInk(); + //std::cout << "."; + //std::cout << tempPix->getPaint(); + //std::cout << "."; + //std::cout << tempPix->getTone(); + //std::cout << ":"; + //std::cout << keepPix->getInk(); + //std::cout << "."; + //std::cout << keepPix->getPaint(); + //std::cout << "."; + //std::cout << keepPix->getTone(); } } } @@ -739,6 +1367,8 @@ void fill(const TRaster32P &ras, const TRaster32P &ref, TRect bbbox = workRas->getBounds(); + std::cout << "\nGlobalScope.fill_1\n"; + if (!bbbox.contains(params.m_p)) return; TPaletteP plt = params.m_palette; @@ -1019,19 +1649,20 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - if (fillGaps && closeGaps) { - // Set the ink on gaps that were used to 4095 - TPixelCM32 *tempPix = refCMRaster->pixels(0); - tempPix += (y * refCMRaster->getLx()) + xa - 1; - int i = xa; - while (i <= xb) { - if (tempPix->getInk() == styleIndex) { - tempPix->setInk(fakeStyleIndex); - } - tempPix++; - i++; - } - } + // TomDoingArt - update this for issue 1151? + //if (fillGaps && closeGaps) { + // // Set the ink on gaps that were used to 4095 + // TPixelCM32 *tempPix = refCMRaster->pixels(0); + // tempPix += (y * refCMRaster->getLx()) + xa - 1; + // int i = xa; + // while (i <= xb) { + // if (tempPix->getInk() == styleIndex) { + // tempPix->setInk(fakeStyleIndex); + // } + // tempPix++; + // i++; + // } + //} while (!seeds.empty()) { FillSeed fs = seeds.top(); @@ -1083,19 +1714,21 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, clickedPosColor, fillDepth); // insert segment to be filled insertSegment(segments[y], std::pair(xc, xd)); - if (fillGaps && closeGaps) { - // Set the ink on gaps that were used to 4095 - TPixelCM32 *tempPix = refCMRaster->pixels(0); - tempPix += (y * refCMRaster->getLx()) + xa - 1; - int i = xa; - while (i <= xb) { - if (tempPix->getInk() == styleIndex) { - tempPix->setInk(fakeStyleIndex); - } - tempPix++; - i++; - } - } + + // TomDoingArt - update this for issue 1151? + //if (fillGaps && closeGaps) { + // // Set the ink on gaps that were used to 4095 + // TPixelCM32 *tempPix = refCMRaster->pixels(0); + // tempPix += (y * refCMRaster->getLx()) + xa - 1; + // int i = xa; + // while (i <= xb) { + // if (tempPix->getInk() == styleIndex) { + // tempPix->setInk(fakeStyleIndex); + // } + // tempPix++; + // i++; + // } + //} // create new fillSeed to invert direction, if needed if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy)); From e3354ee47508d7d79071f9a5db2baf855e06312c Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Thu, 14 Sep 2023 21:19:19 -0400 Subject: [PATCH 2/8] Ready for alpha testing Candidate fixes ready for alpha testing. --- toonz/sources/common/tvectorimage/tstroke.cpp | 6 + toonz/sources/include/toonz/fill.h | 2 + toonz/sources/include/toonz/strokegenerator.h | 3 + toonz/sources/tnztools/filltool.cpp | 226 +++++++++------ toonz/sources/toonzlib/fill.cpp | 273 +++++------------- toonz/sources/toonzlib/fillutil.cpp | 112 ++++++- toonz/sources/toonzlib/strokegenerator.cpp | 10 + 7 files changed, 340 insertions(+), 292 deletions(-) diff --git a/toonz/sources/common/tvectorimage/tstroke.cpp b/toonz/sources/common/tvectorimage/tstroke.cpp index 586b1c9e..d0f2e8d6 100644 --- a/toonz/sources/common/tvectorimage/tstroke.cpp +++ b/toonz/sources/common/tvectorimage/tstroke.cpp @@ -3717,6 +3717,12 @@ TThickCubic *TCubicStroke::generateCubic3D(const T3DPointD pointsArrayBegin[], TCubicStroke, cioe' uno stroke cubico. Da questo trova lo stroke quadratico. */ +//! Returns a stroke from a vector of TThickPoints +/*! + Transforms an array of TThickPoints into an array of T3DPointDs + which is used for a TCubicStroke, i.e. a cubic stroke. + From this he finds the stroke quadratic. +*/ TStroke *TStroke::interpolate(const vector &points, double error, bool findCorners) { vector pointsArray3D; diff --git a/toonz/sources/include/toonz/fill.h b/toonz/sources/include/toonz/fill.h index 7ed8f17b..bcc5c620 100644 --- a/toonz/sources/include/toonz/fill.h +++ b/toonz/sources/include/toonz/fill.h @@ -73,6 +73,8 @@ class TTileSaverFullColor; //============================================================================= +DVAPI void outputPixels(const std::string _str, const TRasterCM32P& r); + // returns true if the savebox is changed typically, if you fill the bg) DVAPI bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TTileSaverCM32 *saver = 0, bool fillGaps = false, diff --git a/toonz/sources/include/toonz/strokegenerator.h b/toonz/sources/include/toonz/strokegenerator.h index bc96dc7d..9c303f9b 100644 --- a/toonz/sources/include/toonz/strokegenerator.h +++ b/toonz/sources/include/toonz/strokegenerator.h @@ -22,6 +22,9 @@ class TStroke; Genera degli stroke sulla base di un vettore di punti, questo vettore e' fatto di punti che vengono inseriti. Consente di visualizzare dei frammenti fatti dai punti che acquisisce. + Generate strokes based on a vector of points, + this vector is made of points that are inserted. + Allows you to view fragments made from the points it acquires. */ class DVAPI StrokeGenerator { //! Vettore di TThickPoint diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index ee80618a..412fd2b5 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -65,6 +65,8 @@ using namespace ToolUtils; #define POLYLINEFILL L"Polyline" #define FREEPICKFILL L"Freepick" +#define IGNORECOLORSTYLE 4093 + TEnv::IntVar MinFillDepth("InknpaintMinFillDepth", 1); TEnv::IntVar MaxFillDepth("InknpaintMaxFillDepth", 10); TEnv::StringVar FillType("InknpaintFillType", "Normal"); @@ -987,49 +989,96 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, int closeStyleIndex, bool fillOnlySavebox) { TRectD selArea = stroke ? stroke->getBBox() : area; + //std::cout << "\nfillAreaWithUndo.strokeBBox y1:"; + //std::cout << selArea.y1; + //std::cout << "::y0:"; + //std::cout << selArea.y0; + //std::cout << ",x1:"; + //std::cout << selArea.x1; + //std::cout << ",x0:"; + //std::cout << selArea.x0; + if (TToonzImageP ti = img) { // allargo di 1 la savebox, perche cosi' il rectfill di tutta l'immagine fa // una sola fillata + // Widen the savebox by 1, because this is how the rectfill of the whole image does + // a single fill TRect enlargedSavebox = fillOnlySavebox ? ti->getSavebox().enlarge(1) * TRect(TPoint(0, 0), ti->getSize()) : TRect(TPoint(0, 0), ti->getSize()); TRect rasterFillArea = ToonzImageUtils::convertWorldToRaster(selArea, ti) * enlargedSavebox; + //std::cout << " rasterFillArea:y1="; + //std::cout << rasterFillArea.y1; + //std::cout << ",y0="; + //std::cout << rasterFillArea.y0; + //std::cout << "; x1="; + //std::cout << rasterFillArea.x1; + //std::cout << ",x0="; + //std::cout << rasterFillArea.x0; + if (rasterFillArea.isEmpty()) return; TRasterCM32P ras = ti->getRaster(); /*-- tileSetでFill範囲のRectをUndoに格納しておく --*/ + /* Store the Rect of the Fill range in Undo with tileSet */ TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize()); tileSet->add(ras, rasterFillArea); + std::cout << "\nfillAreaWithUndo ras:"; + std::cout << ras->getSize(); + outputPixels("ras", ras); + TRasterCM32P tempRaster; int styleIndex = 4094; + + TToonzImageP tempTi = ti->clone(); + tempRaster = tempTi->getRaster(); + + if (fillGaps) { - TToonzImageP tempTi = ti->clone(); - tempRaster = tempTi->getRaster(); + //std::cout << "\nfillAreaWithUndo before applyAutoclose, tempRaster size:"; + //std::cout << tempRaster->getSize(); + //std::cout << ", AutocloseDistance:"; + //std::cout << AutocloseDistance; + //std::cout << ", AutocloseAngle:"; + //std::cout << AutocloseAngle; + applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle, AutocloseOpacity, 4094, convert(rasterFillArea), stroke); - } else { - tempRaster = ras; + + std::cout << "\nfillAreaWithUndo after applyAutoclose, tempRaster size:"; + std::cout << tempRaster->getSize(); + outputPixels("tempRaster", tempRaster); } AreaFiller filler(tempRaster); + if (!stroke) { + std::cout << "\nfillAreaWithUndo now calling AreaFiller.rectFill()"; bool ret = filler.rectFill(rasterFillArea, cs, onlyUnfilled, colorType != LINES, colorType != AREAS); if (!ret) { delete tileSet; return; } - } else + std::cout << "\nfillAreaWithUndo after calling AreaFiller.rectFill()"; + std::cout << tempRaster->getSize(); + outputPixels("tempRaster", tempRaster); + + } else { + std::cout << "\nfillAreaWithUndo now calling AreaFiller.strokeFill()"; filler.strokeFill(stroke, cs, onlyUnfilled, colorType != LINES, colorType != AREAS, rasterFillArea); + std::cout << "\nfillAreaWithUndo after calling AreaFiller.strokeFill()"; + std::cout << tempRaster->getSize(); + outputPixels("tempRaster", tempRaster); + } - if (fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); - std::cout << "\nfilltool.cpp:fillAreaWithUndo"; + std::cout << "\nFinal Check Started filltool.cpp:fillAreaWithUndo if fillGaps is TRUE"; std::cout << "\n---- y:"; std::cout << tempRaster->getLy(); std::cout << " x:"; @@ -1038,111 +1087,100 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, std::cout << cs; std::cout << "----"; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - std::cout << "\n row:"; + std::cout << "\n y:"; std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - std::cout << " a"; - std::cout << tempX; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); - std::cout << ":"; - std::cout << keepPix->getInk(); - std::cout << "."; - std::cout << keepPix->getPaint(); - std::cout << "."; - std::cout << keepPix->getTone(); - - if (tempPix->getInk() == 4095 || - tempPix->getInk() == styleIndex) { - if (fillGaps || closeGaps) { + //if (tempPix->getInk() == 4095 || + // tempPix->getInk() == styleIndex) { + if (tempPix->getInk() == 4095) { + //if (fillGaps || closeGaps) { // does this pixel have a fill pixel neighbor? - if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && - (tempPix - 1)->isPurePaint()) // west - || ((tempX < tempRaster->getLx()) && - ((tempPix + 1)->getPaint() == cs) && - (tempPix + 1)->isPurePaint()) // east - || - ((tempPix + tempRaster->getWrap())->getPaint() == cs && - (tempPix + tempRaster->getWrap())->isPurePaint()) // north - || - ((tempPix - tempRaster->getWrap())->getPaint() == cs && - (tempPix - tempRaster->getWrap())->isPurePaint()) // south + if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && + (tempPix - 1)->isPurePaint()) // west + || ((tempX < tempRaster->getLx()) && + ((tempPix + 1)->getPaint() == cs) && + (tempPix + 1)->isPurePaint()) // east + || + ((tempPix + tempRaster->getWrap())->getPaint() == cs && + (tempPix + tempRaster->getWrap())->isPurePaint()) // north + || + ((tempPix - tempRaster->getWrap())->getPaint() == cs && + (tempPix - tempRaster->getWrap())->isPurePaint()) // south ) { // yes, keep this pixel - if (closeGaps && - (((tempX > 0) && (tempPix - 1)->getPaint() == 0 && - (tempPix - 1)->isPurePaint()) // west - || ((tempX < tempRaster->getLx()) && - ((tempPix + 1)->getPaint() == 0) && - (tempPix + 1)->isPurePaint()) // east - || ((tempPix + tempRaster->getWrap())->getPaint() == 0 && - (tempPix + tempRaster->getWrap()) - ->isPurePaint()) // north - || ((tempPix - tempRaster->getWrap())->getPaint() == 0 && - (tempPix - tempRaster->getWrap()) - ->isPurePaint()) // south - )) { // keep as ink line - std::cout << " i:"; - std::cout << tempY; - std::cout << ":"; - std::cout << tempX; - keepPix->setInk(closeStyleIndex); - keepPix->setPaint(cs); - keepPix->setTone(0); - } else { // keep as paint - // keepPix->setInk(paint); - std::cout << " p:"; - std::cout << tempY; - std::cout << ":"; - std::cout << tempX; - keepPix->setPaint(cs); - keepPix->setTone(255); - } + if (closeGaps) { + // keep as ink line + std::cout << " i:"; + std::cout << tempY; + std::cout << ":"; + std::cout << tempX; + keepPix->setInk(closeStyleIndex); + keepPix->setPaint(cs); + keepPix->setTone(0); + } + else { + // keep as paint + // keepPix->setInk(paint); + std::cout << " p:"; + std::cout << tempY; + std::cout << ":"; + std::cout << tempX; + keepPix->setPaint(cs); + keepPix->setTone(255); } } else { - // Ignore unwanted gap close pixels. - // Should not reach this code because those pixels should not be - // generated prior to this code without fillGaps or closeGaps set - // to true. + //unwanted close gap pixel } + } else if (tempPix->getPaint() == IGNORECOLORSTYLE || tempPix->getInk() == IGNORECOLORSTYLE) { + // IGNORECOLORSTYLE is a color style index value above the valid style index values. + // Pixels are set to this value in fillutil::restoreColors() + // It indicates pixels that should be discarded by this final check routine. + // This allows original pixel values to persist. + //std::cout << ", IGNORECOLORSTYLE at:"; + //std::cout << tempY; + //std::cout << ":"; + //std::cout << tempX; } else { // Handle all other pixels - keepPix->setInk(tempPix->getInk()); - keepPix->setPaint(tempPix->getPaint()); - keepPix->setTone(tempPix->getTone()); - } - - std::cout << " b"; - std::cout << tempX; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); - std::cout << ":"; - std::cout << keepPix->getInk(); - std::cout << "."; - std::cout << keepPix->getPaint(); - std::cout << "."; - std::cout << keepPix->getTone(); - + // ToDo - add a check for stray single pixels + // New paint pixels on a border without a paint neighbor should be removed. + // Stray pixels can appear on the opposite side of ink lines from the filled side. + // ToDo - add a check to persist only pixels of the current colorstyle. + // Only new pixels of the current colorstyle should be preserved. + // This resolves the accidental replacement of pixels with 0 colorstyle pixels. + // Is this needed? + if (tempPix->getPaint() == cs){ + keepPix->setInk(tempPix->getInk()); + keepPix->setPaint(tempPix->getPaint()); + keepPix->setTone(tempPix->getTone()); + } } } } + std::cout << "\nFinal Check Complete fillAreaWithUndo ras at end of filltool.cpp:fillAreaWithUndo if fillGaps"; + std::cout << fillGaps; + std::cout << ras->getSize(); + outputPixels("ras", ras); TPalette *plt = ti->getPalette(); + std::cout << "\nautopaintLines:"; + std::cout << autopaintLines; + std::cout << ", plt:"; + std::cout << plt; + std::cout << ", plt && !hasAutoInks(plt):"; + std::cout << (plt && !hasAutoInks(plt)); + // !autopaintLines will temporary disable autopaint line feature if ((plt && !hasAutoInks(plt)) || !autopaintLines) plt = 0; + std::cout << ", after test plt:"; + std::cout << plt; + if (plt) { + std::cout << "\nautopainting lines"; TRect rect = rasterFillArea; TRect bounds = ras->getBounds(); if (bounds.overlaps(rect)) { @@ -1951,6 +1989,7 @@ void AreaFillTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { void AreaFillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e, bool fillGaps, bool closeGaps, int closeStyleIndex) { + std::cout << "\nAreaFillTool::leftButtonUp()"; if (!m_isLeftButtonPressed) return; m_isLeftButtonPressed = false; @@ -2088,7 +2127,14 @@ void AreaFillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e, m_enabled = m_active = false; if (!isValid || m_track.isEmpty()) return; double pixelSize2 = m_parent->getPixelSize() * m_parent->getPixelSize(); + + if (m_type == FREEPICK){ + //strip off the first n points to allow the stroke to begin away from the initial click point where the color style will be selected. + TPointD firstPoint = m_track.getFirstPoint(); + } + // add the first point as also the last point, to form a complete loop. m_track.add(TThickPoint(m_firstPos, m_thick), pixelSize2); + m_track.filterPoints(); double error = (m_isPath ? 20.0 : 30.0 / 11) * sqrt(pixelSize2); TStroke *stroke = m_track.makeStroke(error); diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 220d8fbb..6aa7af79 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -71,9 +71,15 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, limit = line + r->getBounds().x1; oldtone = pix->getTone(); tone = oldtone; - std::cout << "calcFillRow xa:"; + std::cout << "calcFillRow, prevailing:"; + std::cout << prevailing; + std::cout << ", p.x:"; + std::cout << p.x; + std::cout << ", limit:"; + std::cout << r->getBounds().x1; + std::cout << ", xa:"; std::cout << xa; - std::cout << " xb:"; + std::cout << ", xb:"; std::cout << xb; for (; pix <= limit; pix++) { std::cout << " x:"; @@ -567,12 +573,50 @@ TRasterCM32P convertRaster2CM(const TRasterP &inputRaster) { return rout; } +//----------------------------------------------------------------------------- + +void outputPixels(const std::string _str, const TRasterCM32P &r) { + //r->lock(); + //TPixelCM32* tempPix = r->pixels(0); + //std::cout << "\noutputPixels for:"; + //std::cout << _str; + //std::cout << ", bbox is y : "; + //std::cout << r->getLy(); + //std::cout << ",x:"; + //std::cout << r->getLx(); + //std::cout << "----"; + //tempPix = tempPix + ((r->getLy()-1) * r->getLx()); + //for (int tempY = r->getLy()-1; tempY >= 0; tempY--) { + // if (tempY < r->getLy() - 1) { + // tempPix = tempPix - 2 * r->getLx(); + // } + // std::cout << "\ny:"; + // std::cout << tempY; + // for (int tempX = 0; tempX < r->getLx(); + // tempX++, tempPix++) { + // std::cout << "|x:"; + // std::cout << tempX; + // std::cout << ":"; + // std::cout << tempPix->getInk(); + // std::cout << "."; + // std::cout << tempPix->getPaint(); + // std::cout << "."; + // std::cout << tempPix->getTone(); + // } + //} + //r->unlock(); + //std::cout << "\n"; + return; +} + +//----------------------------------------------------------------------------- + /*-- The return value is whether the saveBox has been updated or not. --*/ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TTileSaverCM32 *saver, bool fillGaps, bool closeGaps, int closeStyleIndex, double autoCloseDistance, TXsheet *xsheet, int frameIndex) { - std::cout << "\nGlobalScope.fill_2"; + std::cout << " GlobalScope.fill_2"; auto fullColorThreshMatte = [](int matte, int fillDepth) -> int { return (matte <= fillDepth) ? matte : 255; }; @@ -609,11 +653,25 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, /*-- getBounds returns the entire image --*/ TRect bbbox = tempRaster->getBounds(); + std::cout << " bbbox:"; + std::cout << bbbox; + std::cout << " p:"; + std::cout << p; + /*- Return if clicked outside the screen -*/ if (!bbbox.contains(p)) return false; /*- If the same color has already been painted, return -*/ int paintAtClickedPos = (tempRaster->pixels(p.y) + p.x)->getPaint(); - if (paintAtClickedPos == paint) return false; + + std::cout << " paintAtClickedPos:"; + std::cout << paintAtClickedPos; + std::cout << ", paint:"; + std::cout << paint; + + if (paintAtClickedPos == paint) { + std::cout << " paintAtClickedPos==paint "; + return false; + } /*- If the "paint only transparent areas" option is enabled and the area is * already colored, return * -*/ @@ -721,6 +779,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, std::cout << " paint_2=:"; std::cout << paint; + std::cout << " "; bool fillIt = !xsheet ? calcFillRow(tempRaster, p, xa, xb, paint, params.m_palette, @@ -729,12 +788,18 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, fillDepth); std::cout << " paint_3=:"; std::cout << paint; + std::cout << " "; if (fillIt) fillRow(tempRaster, p, xa, xb, paint, params.m_palette, saver); if (xsheet) segments[y].push_back(std::pair(xa, xb)); seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); + std::cout << "\nfill.fill().outputPixels() tempRaster about to populate first seed, fillGaps is:"; + std::cout << fillGaps; + outputPixels("tempRaster",tempRaster); // issue 1151 + + // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 1 of 2 if (fillGaps || closeGaps) { std::cout << "\nY:"; @@ -1117,10 +1182,15 @@ std::cout << "\nFill-Seeds"; } } + std::cout << "\nfill.fill().outputPixels() before final, fillGaps is:"; + std::cout << fillGaps; + outputPixels("tempRaster", tempRaster); // issue 1151 + + if (fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = r->pixels(); - std::cout << "\nfill_final_check----y:"; + std::cout << "\nfill.cpp:fill final check started----y:"; std::cout << tempRaster->getLy(); std::cout << ",x:"; std::cout << tempRaster->getLx(); @@ -1130,35 +1200,8 @@ std::cout << "\nFill-Seeds"; //std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - //std::cout << " a"; - //std::cout << tempX; - //std::cout << ":"; - //std::cout << tempPix->getInk(); - //std::cout << "."; - //std::cout << tempPix->getPaint(); - //std::cout << "."; - //std::cout << tempPix->getTone(); - //std::cout << ":"; - //std::cout << keepPix->getInk(); - //std::cout << "."; - //std::cout << keepPix->getPaint(); - //std::cout << "."; - //std::cout << keepPix->getTone(); - // if (tempPix->getInk() != styleIndex && - // tempPix->getInk() != fakeStyleIndex) { - // std::cout << "\ntempY:"; - // std::cout << tempY; - // std::cout << "\ttempX:"; - // std::cout << tempX; - // std::cout << "\ttemPix.getInk():"; - // std::cout << tempPix->getInk(); - // std::cout << "\ttemPix.getPaint():"; - // std::cout << tempPix->getPaint(); - // keepPix->setPaint(tempPix->getPaint()); - //} // Handle pixels of gap close lines, 4094, 4095 - if (tempPix->getInk() == fakeStyleIndex || tempPix->getInk() == styleIndex) { if (tempPix->getInk() == fakeStyleIndex) { @@ -1174,122 +1217,7 @@ std::cout << "\nFill-Seeds"; }else{ // an unused close gap pixel, so ignore } - // if (fillGaps || closeGaps) { - // - // std::cout << "\nNorth "; //north - // std::cout << tempY+1; - // std::cout << " "; - // std::cout << tempX; - // std::cout << ":"; - // std::cout << (tempPix + tempRaster->getWrap())->getInk(); - // std::cout << "."; - // std::cout << (tempPix + tempRaster->getWrap())->getPaint(); - // std::cout << "."; - // std::cout << (tempPix + tempRaster->getWrap())->getTone(); - // std::cout << ";"; - // std::cout << (keepPix + r->getWrap())->getInk(); - // std::cout << "."; - // std::cout << (keepPix + r->getWrap())->getPaint(); - // std::cout << "."; - // std::cout << (keepPix + r->getWrap())->getTone(); - - // std::cout << "\nWest:Center:East "; //west, center, east - // std::cout << tempY; - // std::cout << " "; - // // west - // std::cout << tempX-1; - // std::cout << ":"; - // std::cout << (tempPix - 1)->getInk(); - // std::cout << "."; - // std::cout << (tempPix - 1)->getPaint(); - // std::cout << "."; - // std::cout << (tempPix - 1)->getTone(); - // std::cout << ";"; - // std::cout << (keepPix - 1)->getInk(); - // std::cout << "."; - // std::cout << (keepPix - 1)->getPaint(); - // std::cout << "."; - // std::cout << (keepPix - 1)->getTone(); - // // center - // std::cout << " "; - // std::cout << tempX; - // std::cout << ":"; - // std::cout << tempPix->getInk(); - // std::cout << "."; - // std::cout << tempPix->getPaint(); - // std::cout << "."; - // std::cout << tempPix->getTone(); - // std::cout << ";"; - // std::cout << keepPix->getInk(); - // std::cout << "."; - // std::cout << keepPix->getPaint(); - // std::cout << "."; - // std::cout << keepPix->getTone(); - // // east - // std::cout << " "; - // std::cout << tempX+1; - // std::cout << ":"; - // std::cout << (tempPix + 1)->getInk(); - // std::cout << "."; - // std::cout << (tempPix + 1)->getPaint(); - // std::cout << "."; - // std::cout << (tempPix + 1)->getTone(); - // std::cout << ";"; - // std::cout << (keepPix + 1)->getInk(); - // std::cout << "."; - // std::cout << (keepPix + 1)->getPaint(); - // std::cout << "."; - // std::cout << (keepPix + 1)->getTone(); - // // south - // std::cout << "\nSouth "; - // std::cout << tempY-1; - // std::cout << " "; - // std::cout << tempX; - // std::cout << ":"; - // std::cout << (tempPix - tempRaster->getWrap())->getInk(); - // std::cout << "."; - // std::cout << (tempPix - tempRaster->getWrap())->getPaint(); - // std::cout << "."; - // std::cout << (tempPix - tempRaster->getWrap())->getTone(); - // std::cout << ";"; - // std::cout << (keepPix - r->getWrap())->getInk(); - // std::cout << "."; - // std::cout << (keepPix - r->getWrap())->getPaint(); - // std::cout << "."; - // std::cout << (keepPix - r->getWrap())->getTone(); - - - // // does this pixel have a fill pixel neighbor that is new? - // if ( - // ((tempX > 0) && ((tempPix - 1)->getPaint() == paint) && (tempPix - 1)->isPurePaint() && !(((keepPix - 1)->getPaint() == paint) && (keepPix - 1)->isPurePaint()) ) // west - // || ((tempX < tempRaster->getLx()) && ((tempPix + 1)->getPaint() == paint) && (tempPix + 1)->isPurePaint() && !(((keepPix + 1)->getPaint() == paint) && (keepPix + 1)->isPurePaint()) ) // east - // || ((tempPix + tempRaster->getWrap())->getPaint() == paint && (tempPix + tempRaster->getWrap())->isPurePaint() && !((keepPix + r->getWrap())->getPaint() == paint && (keepPix + r->getWrap())->isPurePaint()) ) // north - // || ((tempPix - tempRaster->getWrap())->getPaint() == paint && (tempPix - tempRaster->getWrap())->isPurePaint() && !((keepPix - r->getWrap())->getPaint() == paint && (keepPix - r->getWrap())->isPurePaint()) ) // south - // ) {// yes, keep this pixel - // if (closeGaps - // && ( - // ((tempX > 0) && (tempPix - 1)->getPaint() == 0 && (tempPix - 1)->isPurePaint()) // west - // || ((tempX < tempRaster->getLx()) && ((tempPix + 1)->getPaint() == 0) && (tempPix + 1)->isPurePaint()) // east - // || ((tempPix + tempRaster->getWrap())->getPaint() == 0 && (tempPix + tempRaster->getWrap())->isPurePaint()) // north - // || ((tempPix - tempRaster->getWrap())->getPaint() == 0 && (tempPix - tempRaster->getWrap())->isPurePaint()) // south - // ) - // ){ //keep as ink line - // keepPix->setInk(closeStyleIndex); - // keepPix->setPaint(paint); - // keepPix->setTone(0); - // } else { //keep as paint - // //keepPix->setInk(paint); - // keepPix->setPaint(paint); - // keepPix->setTone(255); - // } - // } - // } else { - // // Ignore unwanted gap close pixels. - // // Should not reach this code as those pixels should not be - // // generated prior to this code without fillGaps or closeGaps set to - // // true. - // } } else { // // Handle all other pixels @@ -1298,58 +1226,9 @@ std::cout << "\nFill-Seeds"; keepPix->setPaint(tempPix->getPaint()); keepPix->setTone(tempPix->getTone()); } - // This next line takes care of autopaint lines - //if (tempPix->getInk() != styleIndex) { //commented out by Tom - // //if (closeGaps && (tempPix->getInk() == fakeStyleIndex)) { - // if (tempPix->getInk() == fakeStyleIndex) { - // std::cout << "\n****** A pixel with ink 4095 was found ******\n"; - // if (closeGaps) { - // keepPix->setInk(closeStyleIndex); - // // the following two lines could set up a partial ink, partial paint pixel - // // keepPix->setPaint(closeStyleIndex); - // // keepPix->setTone(tempPix->getTone()); //commented out by Tom - // keepPix->setTone(0); - // } else { - // keepPix->setPaint(paint); - // keepPix->setTone(255); - // } - // } else { - // keepPix->setPaint(tempPix->getPaint()); - // keepPix->setTone(tempPix->getTone()); - // } - //} else { // handle tempPix->getInk() == styleIndex - //TPoint nearestPix = nearestInkNotDiagonal(tempRaster, TPoint(tempX, tempY)); - //std::cout << "\nfor pix y: "; - //std::cout << tempY; - //std::cout << " x: "; - //std::cout << tempX; - //std::cout << " nearest pix y: "; - //std::cout << nearestPix.y; - //std::cout << " x: "; - //std::cout << nearestPix.x; - // Is this pixel next to a pixel painted with current fill color? - // then keep - //keepPix->setInk(closeStyleIndex); - //keepPix->setTone(0); - // else, ignore - //keepPix->setTone(255); - //} - //std::cout << " b"; - //std::cout << tempX; - //std::cout << ":"; - //std::cout << tempPix->getInk(); - //std::cout << "."; - //std::cout << tempPix->getPaint(); - //std::cout << "."; - //std::cout << tempPix->getTone(); - //std::cout << ":"; - //std::cout << keepPix->getInk(); - //std::cout << "."; - //std::cout << keepPix->getPaint(); - //std::cout << "."; - //std::cout << keepPix->getTone(); } } + std::cout << "\nfill.cpp:fill final check finished----"; } return saveBoxChanged; } diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index a8952989..f7840b52 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -13,6 +13,8 @@ #include +#define IGNORECOLORSTYLE 4093 + using namespace SkeletonLut; //----------------------------------------------------------------------------- @@ -29,10 +31,17 @@ void computeSeeds(const TRasterCM32P &r, TStroke *stroke, for (int i = 0; i < length; i++) { TPoint p = convert(stroke->getPointAtLength(i)); if (p == oldP || !bbox.contains(p)) continue; + //std::cout << "\ncomputeSeeds y:"; + //std::cout << p.y; + //std::cout << " x:"; + //std::cout << p.x; + //std::cout << " paint:"; + //std::cout << (r->pixels(p.y) + p.x)->getPaint(); seeds.push_back( std::pair(p, (r->pixels(p.y) + p.x)->getPaint())); oldP = p; } + std::cout << "\n"; } //----------------------------------------------------------------------------- @@ -65,6 +74,15 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, bbox *= ras->getBounds(); ras->lock(); + std::cout << "\nfillutil.fillArea(), bbox"; + std::cout << " y1:"; + std::cout << bbox.y1; + std::cout << " y0:"; + std::cout << bbox.y0; + std::cout << " x1:"; + std::cout << bbox.x1; + std::cout << " x0:"; + std::cout << bbox.x0; for (int i = bbox.y0; i <= bbox.y1; i++) { TPixelCM32 *line = ras->pixels(i); std::vector intersections; @@ -76,6 +94,12 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, int from = std::max(tfloor(intersections[j]), bbox.x0); int to = std::min(tceil(intersections[j + 1]), bbox.x1); TPixelCM32 *pix = line + from; + std::cout << "\ny:"; + std::cout << i; + std::cout << " from:"; + std::cout << from; + std::cout << " to:"; + std::cout << to; for (int k = from; k < to; k++, pix++) { if (fillPaints && (!onlyUnfilled || pix->getPaint() == 0)) pix->setPaint(colorId); @@ -92,11 +116,21 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, void restoreColors(const TRasterCM32P &r, const std::vector> &seeds) { FillParameters params; - // in order to make the paint to protlude behind the line + // in order to make the paint to protrude behind the line params.m_prevailing = false; for (UINT i = 0; i < seeds.size(); i++) { params.m_p = seeds[i].first; - params.m_styleId = seeds[i].second; + //params.m_styleId = seeds[i].second; + //params.m_styleId = 0; + params.m_styleId = IGNORECOLORSTYLE; //an unused color style value used to control a later final check + std::cout << "\nrestoreColors:"; + std::cout << i; + std::cout << " y:"; + std::cout << params.m_p.y; + std::cout << " x:"; + std::cout << params.m_p.x; + std::cout << " styleId:"; + std::cout << params.m_styleId; fill(r, params); } } @@ -158,6 +192,9 @@ AreaFiller::~AreaFiller() { m_ras->unlock(); } // inchiostri di tipo "autoink" // che confinano con le aree appena fillate con il rect. rbefore e' il rect del // raster prima del rectfill. +// This function is called after rect fill of the areas, and colors the +// "autoink" type inks bordering the areas just filled with the rect. +// rbefore is the rect of the raster before rectfill. void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, TPalette *plt, int fillIndex) { assert(plt); @@ -165,16 +202,59 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, assert(r->getSize() == rbefore->getSize()); int i, j; + std::cout << "\nfillautoInks(), fillIndex:"; + std::cout << fillIndex; + for (i = 0; i < r->getLy(); i++) { TPixelCM32 *pix = r->pixels(i); TPixelCM32 *pixb = rbefore->pixels(i); + std::cout << "\ny:"; + std::cout << i; for (j = 0; j < r->getLx(); j++, pix++, pixb++) { int paint = pix->getPaint(); int tone = pix->getTone(); int ink = pix->getInk(); - if (paint != pixb->getPaint() && paint == fillIndex && ink != paint && - plt->getStyle(ink)->getFlags() != 0) - inkFill(rin, TPoint(j, i) + rect.getP00(), paint, 0, NULL, &rect); + //std::cout << "|pix x:"; + //std::cout << j; + //std::cout << ", pix.paint:"; + //std::cout << paint; + //std::cout << ", pixb.paint:"; + //std::cout << pixb->getPaint(); + //std::cout << ", tone:"; + //std::cout << tone; + //std::cout << ", ink:"; + //std::cout << ink; + //std::cout << ", flag:"; + //std::cout << plt->getStyle(ink)->getFlags(); + + /* new + * Pseudocode: + * Start the inkFill procedure at the current pixel if: + * The ink colorstyle has autopaint enabled + * The ink colorstyle is not already the same as the fill colorstyle + * The paint colorstyle of a neighboring pixel: + * is the same as the fill colorstyle + * has changed from its prior version + */ + + if (plt->getStyle(ink)->getFlags() != 0 + && ink != fillIndex + && ( + ((pix + r->getWrap())->getPaint() == fillIndex //north + && (pix + r->getWrap())->getPaint() != (pixb + rbefore->getWrap())->getPaint()) + || + ((pix - r->getWrap())->getPaint() == fillIndex //south + && (pix - r->getWrap())->getPaint() != (pixb - rbefore->getWrap())->getPaint()) + || + ((pix + 1)->getPaint() == fillIndex //east + && (pix + 1)->getPaint() != (pixb + 1)->getPaint()) + || + ((pix - 1)->getPaint() == fillIndex //west + && (pix - 1)->getPaint() != (pixb - 1)->getPaint()) + ) + ){ + inkFill(rin, TPoint(j, i) + rect.getP00(), fillIndex, 0, NULL, &rect); + } } } } @@ -189,6 +269,16 @@ bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled, // Then uses the fill command to fill in the edges with their original color // This makes sure only the enclosed areas not on the edge get filled. /*- In case of FillInk only -*/ + + std::cout << "\nAreaFiller::rectFill(), color:"; + std::cout << color; + std::cout << ", onlyUnfilled:"; + std::cout << onlyUnfilled; + std::cout << ", fillPaints:"; + std::cout << fillPaints; + std::cout << ", fillInks:"; + std::cout << fillInks; + if (!fillPaints) { assert(fillInks); assert(m_ras->getBounds().contains(rect)); @@ -323,14 +413,26 @@ void AreaFiller::strokeFill(TStroke *stroke, int colorId, bool onlyUnfilled, TVectorImage app; app.addStroke(stroke); + app.findRegions(); + + std::cout << "\nAreaFiller::strokeFill().fillArea()"; + for (UINT i = 0; i < app.getRegionCount(); i++) fillArea(m_ras, app.getRegion(i), colorId, onlyUnfilled, fillPaints, fillInks); + + std::cout << "\nAreaFiller::strokeFill(), after fillArea()"; + outputPixels("tempRaster", m_ras); // issue 1151 + app.removeStroke(0); stroke->transform(TTranslation(convert(-m_ras->getCenter()))); restoreColors(m_ras, seeds); + + std::cout << "\nAreaFiller::strokeFill(), after restoreColors()"; + outputPixels("tempRaster", m_ras); // issue 1151 + m_ras->unlock(); } diff --git a/toonz/sources/toonzlib/strokegenerator.cpp b/toonz/sources/toonzlib/strokegenerator.cpp index 28a5c447..aef307fa 100644 --- a/toonz/sources/toonzlib/strokegenerator.cpp +++ b/toonz/sources/toonzlib/strokegenerator.cpp @@ -57,12 +57,15 @@ void StrokeGenerator::filterPoints() { // filtra m_points iniziali: generalmente elevate variazioni di thickness // si hanno tra m_points[0] (al massimo m_points[1]) e i successivi) + // filter initial m_points: usually large thickness variations + // you have between m_points[0] (at most m_points[1]) and the following ones) int size1 = m_points.size(); int kMin = 0; int kMax = std::min( 4, size1 - 2); // confronta 5 m_points iniziali con i successivi corrispondenti + // compare initial 5 m_points with subsequent matched ones int k = kMax; for (k = kMax; k >= kMin; --k) { TThickPoint currPoint = m_points[k]; @@ -72,10 +75,12 @@ void StrokeGenerator::filterPoints() { if (deltaThick > 0.6 * dist) // deltaThick <= dist (condizione // approssimata di non-autocontenimento per // TTQ) + // deltaThick <= dist (approximate non-self-contained condition for TTQ) { vector::iterator it1 = m_points.begin(); vector::iterator it2 = it1 + k + 1; m_points.erase(it1, it2); // cancella da m_points[0] a m_points[k] + // delete from m_points[0] to m_points[k] assert((int)m_points.size() == size1 - k - 1); break; } @@ -83,11 +88,15 @@ void StrokeGenerator::filterPoints() { // filtra m_points finali: generalmente elevate variazioni di thickness // si hanno tra m_points[size - 1] (al massimo m_points[size - 2]) e i // predecessori) + // filter final m_points: usually large thickness variations + // have between m_points[size - 1] (at most m_points[size - 2]) and i + // predecessors) int size2 = m_points.size(); kMax = size2 - 1; kMin = std::max( kMax - 4, 1); // confronta 5 m_points finali con i predecessori corrispondenti + // compare final 5 m_points with matching ancestors k = kMin; for (k = kMin; k <= kMax; ++k) { TThickPoint currPoint = m_points[k]; @@ -100,6 +109,7 @@ void StrokeGenerator::filterPoints() { { int kTmp = k; while (k <= kMax) // cancella da m_points[k] a m_points[size2 - 1] + // delete from m_points[k] to m_points[size2 - 1] { m_points.pop_back(); ++k; From 5a6d5a481cc589567b7478f0bf088c90ce0eb334 Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Fri, 15 Sep 2023 09:58:20 -0400 Subject: [PATCH 3/8] Removed or commented out cout statements Removed or commented out the cout statements which were used while researching the code. --- toonz/sources/tnztools/filltool.cpp | 117 ++------ toonz/sources/toonzlib/fill.cpp | 419 +++------------------------- toonz/sources/toonzlib/fillutil.cpp | 66 +---- 3 files changed, 72 insertions(+), 530 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 412fd2b5..ffc4deec 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -989,15 +989,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, int closeStyleIndex, bool fillOnlySavebox) { TRectD selArea = stroke ? stroke->getBBox() : area; - //std::cout << "\nfillAreaWithUndo.strokeBBox y1:"; - //std::cout << selArea.y1; - //std::cout << "::y0:"; - //std::cout << selArea.y0; - //std::cout << ",x1:"; - //std::cout << selArea.x1; - //std::cout << ",x0:"; - //std::cout << selArea.x0; - if (TToonzImageP ti = img) { // allargo di 1 la savebox, perche cosi' il rectfill di tutta l'immagine fa // una sola fillata @@ -1009,14 +1000,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, : TRect(TPoint(0, 0), ti->getSize()); TRect rasterFillArea = ToonzImageUtils::convertWorldToRaster(selArea, ti) * enlargedSavebox; - //std::cout << " rasterFillArea:y1="; - //std::cout << rasterFillArea.y1; - //std::cout << ",y0="; - //std::cout << rasterFillArea.y0; - //std::cout << "; x1="; - //std::cout << rasterFillArea.x1; - //std::cout << ",x0="; - //std::cout << rasterFillArea.x0; if (rasterFillArea.isEmpty()) return; @@ -1026,9 +1009,9 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize()); tileSet->add(ras, rasterFillArea); - std::cout << "\nfillAreaWithUndo ras:"; - std::cout << ras->getSize(); - outputPixels("ras", ras); + //std::cout << "\nfillAreaWithUndo ras:"; + //std::cout << ras->getSize(); + //outputPixels("ras", ras); TRasterCM32P tempRaster; int styleIndex = 4094; @@ -1038,65 +1021,54 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, if (fillGaps) { - //std::cout << "\nfillAreaWithUndo before applyAutoclose, tempRaster size:"; - //std::cout << tempRaster->getSize(); - //std::cout << ", AutocloseDistance:"; - //std::cout << AutocloseDistance; - //std::cout << ", AutocloseAngle:"; - //std::cout << AutocloseAngle; applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle, AutocloseOpacity, 4094, convert(rasterFillArea), stroke); - std::cout << "\nfillAreaWithUndo after applyAutoclose, tempRaster size:"; - std::cout << tempRaster->getSize(); - outputPixels("tempRaster", tempRaster); + //std::cout << "\nfillAreaWithUndo after applyAutoclose, tempRaster size:"; + //std::cout << tempRaster->getSize(); + //outputPixels("tempRaster", tempRaster); } AreaFiller filler(tempRaster); if (!stroke) { - std::cout << "\nfillAreaWithUndo now calling AreaFiller.rectFill()"; bool ret = filler.rectFill(rasterFillArea, cs, onlyUnfilled, colorType != LINES, colorType != AREAS); if (!ret) { delete tileSet; return; } - std::cout << "\nfillAreaWithUndo after calling AreaFiller.rectFill()"; - std::cout << tempRaster->getSize(); - outputPixels("tempRaster", tempRaster); + //std::cout << "\nfillAreaWithUndo after calling AreaFiller.rectFill()"; + //std::cout << tempRaster->getSize(); + //outputPixels("tempRaster", tempRaster); } else { - std::cout << "\nfillAreaWithUndo now calling AreaFiller.strokeFill()"; filler.strokeFill(stroke, cs, onlyUnfilled, colorType != LINES, colorType != AREAS, rasterFillArea); - std::cout << "\nfillAreaWithUndo after calling AreaFiller.strokeFill()"; - std::cout << tempRaster->getSize(); - outputPixels("tempRaster", tempRaster); + //std::cout << "\nfillAreaWithUndo after calling AreaFiller.strokeFill()"; + //std::cout << tempRaster->getSize(); + //outputPixels("tempRaster", tempRaster); } TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); - std::cout << "\nFinal Check Started filltool.cpp:fillAreaWithUndo if fillGaps is TRUE"; - std::cout << "\n---- y:"; - std::cout << tempRaster->getLy(); - std::cout << " x:"; - std::cout << tempRaster->getLx(); - std::cout << " paint:"; - std::cout << cs; - std::cout << "----"; + //std::cout << "\nFinal Check Started filltool.cpp:fillAreaWithUndo if fillGaps is TRUE"; + //std::cout << "\n---- y:"; + //std::cout << tempRaster->getLy(); + //std::cout << " x:"; + //std::cout << tempRaster->getLx(); + //std::cout << " paint:"; + //std::cout << cs; + //std::cout << "----"; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - std::cout << "\n y:"; - std::cout << tempY; + //std::cout << "\n y:"; + //std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - //if (tempPix->getInk() == 4095 || - // tempPix->getInk() == styleIndex) { if (tempPix->getInk() == 4095) { - //if (fillGaps || closeGaps) { - // does this pixel have a fill pixel neighbor? + // does this pixel have a fill pixel neighbor? if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && (tempPix - 1)->isPurePaint()) // west || ((tempX < tempRaster->getLx()) && @@ -1111,10 +1083,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, ) { // yes, keep this pixel if (closeGaps) { // keep as ink line - std::cout << " i:"; - std::cout << tempY; - std::cout << ":"; - std::cout << tempX; keepPix->setInk(closeStyleIndex); keepPix->setPaint(cs); keepPix->setTone(0); @@ -1122,10 +1090,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, else { // keep as paint // keepPix->setInk(paint); - std::cout << " p:"; - std::cout << tempY; - std::cout << ":"; - std::cout << tempX; keepPix->setPaint(cs); keepPix->setTone(255); } @@ -1133,23 +1097,12 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, //unwanted close gap pixel } } else if (tempPix->getPaint() == IGNORECOLORSTYLE || tempPix->getInk() == IGNORECOLORSTYLE) { - // IGNORECOLORSTYLE is a color style index value above the valid style index values. + // IGNORECOLORSTYLE is a color style index value used to identify pixels to not persist. // Pixels are set to this value in fillutil::restoreColors() // It indicates pixels that should be discarded by this final check routine. // This allows original pixel values to persist. - //std::cout << ", IGNORECOLORSTYLE at:"; - //std::cout << tempY; - //std::cout << ":"; - //std::cout << tempX; } else { // Handle all other pixels - // ToDo - add a check for stray single pixels - // New paint pixels on a border without a paint neighbor should be removed. - // Stray pixels can appear on the opposite side of ink lines from the filled side. - // ToDo - add a check to persist only pixels of the current colorstyle. - // Only new pixels of the current colorstyle should be preserved. - // This resolves the accidental replacement of pixels with 0 colorstyle pixels. - // Is this needed? if (tempPix->getPaint() == cs){ keepPix->setInk(tempPix->getInk()); keepPix->setPaint(tempPix->getPaint()); @@ -1159,28 +1112,17 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, } } - std::cout << "\nFinal Check Complete fillAreaWithUndo ras at end of filltool.cpp:fillAreaWithUndo if fillGaps"; - std::cout << fillGaps; - std::cout << ras->getSize(); - outputPixels("ras", ras); + //std::cout << "\nFinal Check Complete fillAreaWithUndo ras at end of filltool.cpp:fillAreaWithUndo if fillGaps"; + //std::cout << fillGaps; + //std::cout << ras->getSize(); + //outputPixels("ras", ras); TPalette *plt = ti->getPalette(); - std::cout << "\nautopaintLines:"; - std::cout << autopaintLines; - std::cout << ", plt:"; - std::cout << plt; - std::cout << ", plt && !hasAutoInks(plt):"; - std::cout << (plt && !hasAutoInks(plt)); - // !autopaintLines will temporary disable autopaint line feature if ((plt && !hasAutoInks(plt)) || !autopaintLines) plt = 0; - std::cout << ", after test plt:"; - std::cout << plt; - if (plt) { - std::cout << "\nautopainting lines"; TRect rect = rasterFillArea; TRect bounds = ras->getBounds(); if (bounds.overlaps(rect)) { @@ -1311,7 +1253,7 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms, if (tileSaver.getTileSet()->getTileCount() != 0) { static int count = 0; - TSystem::outputDebug("FILL" + std::to_string(count++) + "\n"); + //TSystem::outputDebug("FILL" + std::to_string(count++) + "\n"); if (offs != TPoint()) for (int i = 0; i < tileSet->getTileCount(); i++) { TTileSet::Tile *t = tileSet->editTile(i); @@ -1989,7 +1931,6 @@ void AreaFillTool::mouseMove(const TPointD &pos, const TMouseEvent &e) { void AreaFillTool::leftButtonUp(const TPointD &pos, const TMouseEvent &e, bool fillGaps, bool closeGaps, int closeStyleIndex) { - std::cout << "\nAreaFillTool::leftButtonUp()"; if (!m_isLeftButtonPressed) return; m_isLeftButtonPressed = false; diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 6aa7af79..126e4dee 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -71,69 +71,21 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, limit = line + r->getBounds().x1; oldtone = pix->getTone(); tone = oldtone; - std::cout << "calcFillRow, prevailing:"; - std::cout << prevailing; - std::cout << ", p.x:"; - std::cout << p.x; - std::cout << ", limit:"; - std::cout << r->getBounds().x1; - std::cout << ", xa:"; - std::cout << xa; - std::cout << ", xb:"; - std::cout << xb; for (; pix <= limit; pix++) { - std::cout << " x:"; - std::cout << p.x + pix - pix0; if (pix->getPaint() == paint) { - std::cout << " r_eq_paint:"; - std::cout << paint; - std::cout << "_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); //break; } if (emptyOnly && pix->getPaint() != 0) { - std::cout << " r_(emptyOnly&&pix->getPaint()!=0)_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); //break; } tone = pix->getTone(); if (tone == 0) { - std::cout << " r_(tone==0)_x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } // prevent fill area from protruding behind the colored line if (tone > oldtone) { - std::cout << " r_tone>oldtone_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); // not-yet-colored line case if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint()) - std::cout << " prevailing_or_notPurePaint_or_inkNotEqPaint_x:"; - std::cout << p.x + pix - pix0; break; while (pix != pix0) { // iterate back in order to leave the pixel with the lowest tone @@ -148,18 +100,8 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, TPixelCM32 *upPix = pix - r->getWrap(); TPixelCM32 *downPix = pix + r->getWrap(); if (upPix->getTone() > pix->getTone() && - downPix->getTone() > pix->getTone()) - std::cout << " l_getTone()>oldtone_continue"; - continue; + downPix->getTone() > pix->getTone()) continue; } - std::cout << " r_getTone()>oldtone_x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } } @@ -174,14 +116,6 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, for (; pix <= limit; pix++) { //if (pix->getPaint() == paint) break; // commented out for issue 1151 if (pix->getTone() != 0) { - std::cout << " r_(tone!=0)_x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } } @@ -197,54 +131,19 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, tone = oldtone; for (pix--; pix >= limit; pix--) { if (pix->getPaint() == paint) { - std::cout << " l_eq_paint:"; - std::cout << paint; - std::cout << "_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } if (emptyOnly && pix->getPaint() != 0) { - std::cout << " l_getPaint!=0_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } tone = pix->getTone(); if (tone == 0) { - std::cout << " l_(tone==0)_x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } // prevent fill area from protruding behind the colored line if (tone > oldtone) { - std::cout << " l_tone>oldtone_x:"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); // not-yet-colored line case if (prevailing && !pix->isPurePaint() && pix->getInk() != pix->getPaint()){ - std::cout << " prevailing_notPurePaint_or_pix_ink!=pix_paint"; break; } while (pix != pix0) { @@ -261,18 +160,9 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, TPixelCM32 *downPix = pix + r->getWrap(); if (upPix->getTone() > pix->getTone() && downPix->getTone() > pix->getTone()) { - std::cout << " l_getTone()>oldtone_continue"; continue; } } - std::cout << " l_getTone()>oldtone_x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } } @@ -287,14 +177,6 @@ bool calcFillRow(const TRasterCM32P &r, const TPoint &p, int &xa, int &xb, for (; pix >= limit; pix--) { //if (pix->getPaint() == paint) break; // commented out for issue 1151 if (pix->getTone() != 0) { - std::cout << " l_(tone!=0) x"; - std::cout << p.x + pix - pix0; - std::cout << ":"; - std::cout << pix->getInk(); - std::cout << "."; - std::cout << pix->getPaint(); - std::cout << "."; - std::cout << pix->getTone(); break; } } @@ -312,7 +194,6 @@ void findSegment(const TRaster32P &r, const TPoint &p, int &xa, int &xb, int matte, oldmatte; TPixel32 *pix, *pix0, *limit, *tmp_limit; - std::cout << "\nanonymous-namespace.findSegment "; /* vai a destra */ TPixel32 *line = r->pixels(p.y); @@ -357,11 +238,6 @@ void findSegment(const TRaster32P &r, const TPoint &p, int &xa, int &xb, } } xa = p.x + pix - pix0 + 1; - - std::cout << " xa:"; - std::cout << xa; - std::cout << " xb:"; - std::cout << xb; } //----------------------------------------------------------------------------- @@ -467,8 +343,6 @@ inline int threshTone(const TPixelCM32 &pix, int fillDepth) { void fillRow(const TRasterCM32P &r, const TPoint &p, int xa, int xb, int paint, TPalette *palette, TTileSaverCM32 *saver) { - std::cout << " paint_4:"; - std::cout << paint; /* vai a destra */ TPixelCM32 *line = r->pixels(p.y); TPixelCM32 *pix = line + p.x; @@ -576,36 +450,36 @@ TRasterCM32P convertRaster2CM(const TRasterP &inputRaster) { //----------------------------------------------------------------------------- void outputPixels(const std::string _str, const TRasterCM32P &r) { - //r->lock(); - //TPixelCM32* tempPix = r->pixels(0); - //std::cout << "\noutputPixels for:"; - //std::cout << _str; - //std::cout << ", bbox is y : "; - //std::cout << r->getLy(); - //std::cout << ",x:"; - //std::cout << r->getLx(); - //std::cout << "----"; - //tempPix = tempPix + ((r->getLy()-1) * r->getLx()); - //for (int tempY = r->getLy()-1; tempY >= 0; tempY--) { - // if (tempY < r->getLy() - 1) { - // tempPix = tempPix - 2 * r->getLx(); - // } - // std::cout << "\ny:"; - // std::cout << tempY; - // for (int tempX = 0; tempX < r->getLx(); - // tempX++, tempPix++) { - // std::cout << "|x:"; - // std::cout << tempX; - // std::cout << ":"; - // std::cout << tempPix->getInk(); - // std::cout << "."; - // std::cout << tempPix->getPaint(); - // std::cout << "."; - // std::cout << tempPix->getTone(); - // } - //} - //r->unlock(); - //std::cout << "\n"; + r->lock(); + TPixelCM32* tempPix = r->pixels(0); + std::cout << "\noutputPixels for:"; + std::cout << _str; + std::cout << ", bbox is y : "; + std::cout << r->getLy(); + std::cout << ",x:"; + std::cout << r->getLx(); + std::cout << "----"; + tempPix = tempPix + ((r->getLy()-1) * r->getLx()); + for (int tempY = r->getLy()-1; tempY >= 0; tempY--) { + if (tempY < r->getLy() - 1) { + tempPix = tempPix - 2 * r->getLx(); + } + std::cout << "\ny:"; + std::cout << tempY; + for (int tempX = 0; tempX < r->getLx(); + tempX++, tempPix++) { + std::cout << "|x:"; + std::cout << tempX; + std::cout << ":"; + std::cout << tempPix->getInk(); + std::cout << "."; + std::cout << tempPix->getPaint(); + std::cout << "."; + std::cout << tempPix->getTone(); + } + } + r->unlock(); + std::cout << "\n"; return; } @@ -616,7 +490,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TTileSaverCM32 *saver, bool fillGaps, bool closeGaps, int closeStyleIndex, double autoCloseDistance, TXsheet *xsheet, int frameIndex) { - std::cout << " GlobalScope.fill_2"; auto fullColorThreshMatte = [](int matte, int fillDepth) -> int { return (matte <= fillDepth) ? matte : 255; }; @@ -629,8 +502,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, TPoint p = params.m_p; int x = p.x, y = p.y; int paint = params.m_styleId; - std::cout << " paint_1=:"; - std::cout << paint; int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth; TRasterCM32P tempRaster; @@ -653,23 +524,12 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, /*-- getBounds returns the entire image --*/ TRect bbbox = tempRaster->getBounds(); - std::cout << " bbbox:"; - std::cout << bbbox; - std::cout << " p:"; - std::cout << p; - /*- Return if clicked outside the screen -*/ if (!bbbox.contains(p)) return false; /*- If the same color has already been painted, return -*/ int paintAtClickedPos = (tempRaster->pixels(p.y) + p.x)->getPaint(); - std::cout << " paintAtClickedPos:"; - std::cout << paintAtClickedPos; - std::cout << ", paint:"; - std::cout << paint; - if (paintAtClickedPos == paint) { - std::cout << " paintAtClickedPos==paint "; return false; } /*- If the "paint only transparent areas" option is enabled and the area is @@ -773,66 +633,30 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, std::stack seeds; - std::cout << "\ny:"; - std::cout << y; - std::cout << " "; - - std::cout << " paint_2=:"; - std::cout << paint; - std::cout << " "; - bool fillIt = !xsheet ? calcFillRow(tempRaster, p, xa, xb, paint, params.m_palette, params.m_prevailing, params.m_emptyOnly) : calcRefFillRow(refRaster, p, xa, xb, color, clickedPosColor, fillDepth); - std::cout << " paint_3=:"; - std::cout << paint; - std::cout << " "; if (fillIt) fillRow(tempRaster, p, xa, xb, paint, params.m_palette, saver); if (xsheet) segments[y].push_back(std::pair(xa, xb)); seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - std::cout << "\nfill.fill().outputPixels() tempRaster about to populate first seed, fillGaps is:"; - std::cout << fillGaps; - outputPixels("tempRaster",tempRaster); // issue 1151 + //std::cout << "\nfill.fill().outputPixels() tempRaster about to populate first seed, fillGaps is:"; + //std::cout << fillGaps; + //outputPixels("tempRaster",tempRaster); // issue 1151 // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 1 of 2 if (fillGaps || closeGaps) { - std::cout << "\nY:"; - std::cout << y; - std::cout << " xa:"; - std::cout << xa; - std::cout << " xb:"; - std::cout << xb; TPixelCM32 *tempPix = tempRaster->pixels(0); tempPix += (y * tempRaster->getLx()) + xa - 1; int i = xa; - // std::cout << "\n1:"; - // std::cout << y; - // std::cout << ":i:"; - // std::cout << i; - // std::cout << ":xb:"; - // std::cout << xb; while (i <= xb) { - std::cout << " a1:"; - std::cout << i; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); - - // if (tempPix->getInk() == styleIndex) { - // tempPix->setInk(fakeStyleIndex); - // //std::cout << " *4095* "; - //} if (tempPix->getPaint() == paint) { // check for neighboring gap pixels and finalize them @@ -893,22 +717,11 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } } } - - std::cout << " b1:"; - std::cout << i; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); tempPix++; i++; } } -std::cout << "\nFill-Seeds"; - while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); @@ -949,9 +762,6 @@ std::cout << "\nFill-Seeds"; floodCheck(clickedPosColor, refpix, oldrefpix, fillDepth); } if (canPaint) { - std::cout << "\ny:"; - std::cout << y; - std::cout << " "; bool fillIt = !xsheet ? calcFillRow(tempRaster, TPoint(x, y), xc, xd, paint, params.m_palette, params.m_prevailing) @@ -961,179 +771,35 @@ std::cout << "\nFill-Seeds"; fillRow(tempRaster, TPoint(x, y), xc, xd, paint, params.m_palette, saver); if (xsheet) insertSegment(segments[y], std::pair(xc, xd)); - - // Set the ink on gaps that were used to 4095 - // - //{ - // TPixelCM32 *tempPix = tempRaster->pixels(0); - // tempPix += (y * tempRaster->getLx()) + xa - 1; - // int i = xa; - // //std::cout << "\n2:"; - // //std::cout << y; - // //std::cout << ":i:"; - // //std::cout << i; - // //std::cout << ":xb:"; - // //std::cout << xb; - - // while (i <= xb) { - // //std::cout << " a2:"; - // //std::cout << i; - // //std::cout << ":"; - // //std::cout << tempPix->getInk(); - // //std::cout << "."; - // //std::cout << tempPix->getPaint(); - // //std::cout << "."; - // //std::cout << tempPix->getTone(); - - // if (tempPix->getInk() == styleIndex) { - // tempPix->setInk(fakeStyleIndex); - // //std::cout << " *4095* "; - // } - // //// check the neighboring pixels for gap close ink - // //// west - // //if (i == xa) { - // // if ((tempPix - 1)->getInk() == styleIndex) { - // // (tempPix - 1)->setInk(fakeStyleIndex); - // // //std::cout << " *4095 w* "; - // // } - // //} - // //// east - // //if (i == xb) { - // // if ((tempPix + 1)->getInk() == styleIndex) { - // // (tempPix + 1)->setInk(fakeStyleIndex); - // // //std::cout << " *4095 e* "; - // // } - // //} - // //// north - // //if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { - // // (tempPix + tempRaster->getWrap())->setInk(fakeStyleIndex); - // // //std::cout << " *4095 n* "; - // //} - // //// south - // //if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { - // // (tempPix - tempRaster->getWrap())->setInk(fakeStyleIndex); - // // //std::cout << " *4095 s* "; - // //} - // //std::cout << " b2:"; - // //std::cout << i; - // //std::cout << ":"; - // //std::cout << tempPix->getInk(); - // //std::cout << "."; - // //std::cout << tempPix->getPaint(); - // //std::cout << "."; - // //std::cout << tempPix->getTone(); - - // tempPix++; - // i++; - // } - //} // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 2 of 2 if (fillGaps || closeGaps) { - std::cout << "\nY:"; - std::cout << y; - std::cout << " xa:"; - std::cout << xa; - std::cout << " xb:"; - std::cout << xb; TPixelCM32 *tempPix = tempRaster->pixels(0); tempPix += (y * tempRaster->getLx()) + xa - 1; int i = xa; - // std::cout << "\n1:"; - // std::cout << y; - // std::cout << ":i:"; - // std::cout << i; - // std::cout << ":xb:"; - // std::cout << xb; while (i <= xb) { - std::cout << " a2:"; - std::cout << i; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); - - // if (tempPix->getInk() == styleIndex) { - // tempPix->setInk(fakeStyleIndex); - // //std::cout << " *4095* "; - //} if (tempPix->getPaint() == paint) { // check for neighboring gap pixels and finalize them // west if ((tempPix - 1)->getInk() == styleIndex) { (tempPix - 1)->setInk(fakeStyleIndex); - //if (closeGaps) { - // // keep as ink pixel - // (tempPix - 1)->setInk(closeStyleIndex); - // (tempPix - 1)->setPaint(paint); - // (tempPix - 1)->setTone(0); - //} else { - // // keep as paint pixel - // (tempPix - 1)->setInk(0); - // (tempPix - 1)->setPaint(paint); - // (tempPix - 1)->setTone(255); - //} } // east if ((tempPix + 1)->getInk() == styleIndex) { (tempPix + 1)->setInk(fakeStyleIndex); - //if (closeGaps) { - // // keep as ink pixel - // (tempPix + 1)->setInk(closeStyleIndex); - // (tempPix + 1)->setPaint(paint); - // (tempPix + 1)->setTone(0); - //} else { - // // keep as paint pixel - // (tempPix + 1)->setInk(0); - // (tempPix + 1)->setPaint(paint); - // (tempPix + 1)->setTone(255); - //} } // north if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { (tempPix + tempRaster->getWrap())->setInk(fakeStyleIndex); - //if (closeGaps) { - // // keep as ink pixel - // (tempPix + tempRaster->getWrap())->setInk(closeStyleIndex); - // (tempPix + tempRaster->getWrap())->setPaint(paint); - // (tempPix + tempRaster->getWrap())->setTone(0); - //} else { - // // keep as paint pixel - // (tempPix + tempRaster->getWrap())->setInk(0); - // (tempPix + tempRaster->getWrap())->setPaint(paint); - // (tempPix + tempRaster->getWrap())->setTone(255); - //} } // south if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { (tempPix - tempRaster->getWrap())->setInk(fakeStyleIndex); - //if (closeGaps) { - // // keep as ink pixel - // (tempPix - tempRaster->getWrap())->setInk(closeStyleIndex); - // (tempPix - tempRaster->getWrap())->setPaint(paint); - // (tempPix - tempRaster->getWrap())->setTone(0); - //} else { - // // keep as paint pixel - // (tempPix - tempRaster->getWrap())->setInk(0); - // (tempPix - tempRaster->getWrap())->setPaint(paint); - // (tempPix - tempRaster->getWrap())->setTone(255); - //} } } - - std::cout << " b2:"; - std::cout << i; - std::cout << ":"; - std::cout << tempPix->getInk(); - std::cout << "."; - std::cout << tempPix->getPaint(); - std::cout << "."; - std::cout << tempPix->getTone(); tempPix++; i++; } @@ -1182,22 +848,15 @@ std::cout << "\nFill-Seeds"; } } - std::cout << "\nfill.fill().outputPixels() before final, fillGaps is:"; - std::cout << fillGaps; - outputPixels("tempRaster", tempRaster); // issue 1151 + //std::cout << "\nfill.fill().outputPixels() before final, fillGaps is:"; + //std::cout << fillGaps; + //outputPixels("tempRaster", tempRaster); // issue 1151 if (fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = r->pixels(); - std::cout << "\nfill.cpp:fill final check started----y:"; - std::cout << tempRaster->getLy(); - std::cout << ",x:"; - std::cout << tempRaster->getLx(); - std::cout << "----"; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - //std::cout << "\n"; - //std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { @@ -1228,7 +887,7 @@ std::cout << "\nFill-Seeds"; } } } - std::cout << "\nfill.cpp:fill final check finished----"; + //std::cout << "\nfill.cpp:fill final check finished----"; } return saveBoxChanged; } @@ -1246,8 +905,6 @@ void fill(const TRaster32P &ras, const TRaster32P &ref, TRect bbbox = workRas->getBounds(); - std::cout << "\nGlobalScope.fill_1\n"; - if (!bbbox.contains(params.m_p)) return; TPaletteP plt = params.m_palette; diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index f7840b52..4cfc4ab5 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -31,17 +31,10 @@ void computeSeeds(const TRasterCM32P &r, TStroke *stroke, for (int i = 0; i < length; i++) { TPoint p = convert(stroke->getPointAtLength(i)); if (p == oldP || !bbox.contains(p)) continue; - //std::cout << "\ncomputeSeeds y:"; - //std::cout << p.y; - //std::cout << " x:"; - //std::cout << p.x; - //std::cout << " paint:"; - //std::cout << (r->pixels(p.y) + p.x)->getPaint(); seeds.push_back( std::pair(p, (r->pixels(p.y) + p.x)->getPaint())); oldP = p; } - std::cout << "\n"; } //----------------------------------------------------------------------------- @@ -74,15 +67,6 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, bbox *= ras->getBounds(); ras->lock(); - std::cout << "\nfillutil.fillArea(), bbox"; - std::cout << " y1:"; - std::cout << bbox.y1; - std::cout << " y0:"; - std::cout << bbox.y0; - std::cout << " x1:"; - std::cout << bbox.x1; - std::cout << " x0:"; - std::cout << bbox.x0; for (int i = bbox.y0; i <= bbox.y1; i++) { TPixelCM32 *line = ras->pixels(i); std::vector intersections; @@ -94,12 +78,6 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, int from = std::max(tfloor(intersections[j]), bbox.x0); int to = std::min(tceil(intersections[j + 1]), bbox.x1); TPixelCM32 *pix = line + from; - std::cout << "\ny:"; - std::cout << i; - std::cout << " from:"; - std::cout << from; - std::cout << " to:"; - std::cout << to; for (int k = from; k < to; k++, pix++) { if (fillPaints && (!onlyUnfilled || pix->getPaint() == 0)) pix->setPaint(colorId); @@ -123,14 +101,6 @@ void restoreColors(const TRasterCM32P &r, //params.m_styleId = seeds[i].second; //params.m_styleId = 0; params.m_styleId = IGNORECOLORSTYLE; //an unused color style value used to control a later final check - std::cout << "\nrestoreColors:"; - std::cout << i; - std::cout << " y:"; - std::cout << params.m_p.y; - std::cout << " x:"; - std::cout << params.m_p.x; - std::cout << " styleId:"; - std::cout << params.m_styleId; fill(r, params); } } @@ -201,31 +171,14 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, TRasterCM32P r = rin->extract(rect); assert(r->getSize() == rbefore->getSize()); int i, j; - - std::cout << "\nfillautoInks(), fillIndex:"; - std::cout << fillIndex; for (i = 0; i < r->getLy(); i++) { TPixelCM32 *pix = r->pixels(i); TPixelCM32 *pixb = rbefore->pixels(i); - std::cout << "\ny:"; - std::cout << i; for (j = 0; j < r->getLx(); j++, pix++, pixb++) { int paint = pix->getPaint(); int tone = pix->getTone(); int ink = pix->getInk(); - //std::cout << "|pix x:"; - //std::cout << j; - //std::cout << ", pix.paint:"; - //std::cout << paint; - //std::cout << ", pixb.paint:"; - //std::cout << pixb->getPaint(); - //std::cout << ", tone:"; - //std::cout << tone; - //std::cout << ", ink:"; - //std::cout << ink; - //std::cout << ", flag:"; - //std::cout << plt->getStyle(ink)->getFlags(); /* new * Pseudocode: @@ -270,15 +223,6 @@ bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled, // This makes sure only the enclosed areas not on the edge get filled. /*- In case of FillInk only -*/ - std::cout << "\nAreaFiller::rectFill(), color:"; - std::cout << color; - std::cout << ", onlyUnfilled:"; - std::cout << onlyUnfilled; - std::cout << ", fillPaints:"; - std::cout << fillPaints; - std::cout << ", fillInks:"; - std::cout << fillInks; - if (!fillPaints) { assert(fillInks); assert(m_ras->getBounds().contains(rect)); @@ -416,22 +360,22 @@ void AreaFiller::strokeFill(TStroke *stroke, int colorId, bool onlyUnfilled, app.findRegions(); - std::cout << "\nAreaFiller::strokeFill().fillArea()"; + //std::cout << "\nAreaFiller::strokeFill().fillArea()"; for (UINT i = 0; i < app.getRegionCount(); i++) fillArea(m_ras, app.getRegion(i), colorId, onlyUnfilled, fillPaints, fillInks); - std::cout << "\nAreaFiller::strokeFill(), after fillArea()"; - outputPixels("tempRaster", m_ras); // issue 1151 + //std::cout << "\nAreaFiller::strokeFill(), after fillArea()"; + //outputPixels("tempRaster", m_ras); // issue 1151 app.removeStroke(0); stroke->transform(TTranslation(convert(-m_ras->getCenter()))); restoreColors(m_ras, seeds); - std::cout << "\nAreaFiller::strokeFill(), after restoreColors()"; - outputPixels("tempRaster", m_ras); // issue 1151 + //std::cout << "\nAreaFiller::strokeFill(), after restoreColors()"; + //outputPixels("tempRaster", m_ras); // issue 1151 m_ras->unlock(); } From 4b0833ef8c906819bd595aff6014e4ec712b303b Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Sat, 16 Sep 2023 22:03:19 -0400 Subject: [PATCH 4/8] Fix for filling a Raster level with refer visible ticked Fill on a Raster level with refer visible ticked would have artifacts from unused gap fill lines. This commit fixes the issue for Raster levels. Still to do: a fix for SmartRaster levels with refer visible ticked. --- toonz/sources/tnztools/filltool.cpp | 2 +- toonz/sources/toonzlib/fill.cpp | 79 +++++++++++++++++------------ toonz/sources/toonzlib/fillutil.cpp | 43 +++++++--------- 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index ffc4deec..f253ce6b 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -1253,7 +1253,7 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms, if (tileSaver.getTileSet()->getTileCount() != 0) { static int count = 0; - //TSystem::outputDebug("FILL" + std::to_string(count++) + "\n"); + TSystem::outputDebug("FILL" + std::to_string(count++) + "\n"); if (offs != TPoint()) for (int i = 0; i < tileSet->getTileCount(); i++) { TTileSet::Tile *t = tileSet->editTile(i); diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 126e4dee..80b9395d 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -1185,21 +1185,6 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - // TomDoingArt - update this for issue 1151? - //if (fillGaps && closeGaps) { - // // Set the ink on gaps that were used to 4095 - // TPixelCM32 *tempPix = refCMRaster->pixels(0); - // tempPix += (y * refCMRaster->getLx()) + xa - 1; - // int i = xa; - // while (i <= xb) { - // if (tempPix->getInk() == styleIndex) { - // tempPix->setInk(fakeStyleIndex); - // } - // tempPix++; - // i++; - // } - //} - while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); @@ -1250,21 +1235,6 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, clickedPosColor, fillDepth); // insert segment to be filled insertSegment(segments[y], std::pair(xc, xd)); - - // TomDoingArt - update this for issue 1151? - //if (fillGaps && closeGaps) { - // // Set the ink on gaps that were used to 4095 - // TPixelCM32 *tempPix = refCMRaster->pixels(0); - // tempPix += (y * refCMRaster->getLx()) + xa - 1; - // int i = xa; - // while (i <= xb) { - // if (tempPix->getInk() == styleIndex) { - // tempPix->setInk(fakeStyleIndex); - // } - // tempPix++; - // i++; - // } - //} // create new fillSeed to invert direction, if needed if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy)); @@ -1327,14 +1297,57 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, } } - if (fillGaps && closeGaps) { + //std::cout << "\nfill::fullColorFill() step before final, fillGaps is:"; + //std::cout << fillGaps; + //outputPixels("refCMRaster", refCMRaster); // issue 1151 + +// final check for close gap pixels + if (fillGaps) { TPixelCM32 *tempPix = refCMRaster->pixels(); TPixel32 *keepPix = ras->pixels(); + int fillNeighbors; for (int tempY = 0; tempY < refCMRaster->getLy(); tempY++) { for (int tempX = 0; tempX < refCMRaster->getLx(); tempX++, tempPix++, keepPix++) { - if (tempPix->getInk() == fakeStyleIndex) { - *keepPix = gapColor; + // if (tempPix->getInk() == fakeStyleIndex) { + if (tempPix->getInk() == styleIndex) { + // how many fill pixel neighbors for the current pixel? + fillNeighbors = 0; + if ((tempX > 0) && *(keepPix - 1) == color) fillNeighbors++; // west + if ((tempX < refCMRaster->getLx()) && *(keepPix + 1) == color) + fillNeighbors++; // east + if (*(keepPix + ras->getWrap()) == color) fillNeighbors++; // north + if (*(keepPix - ras->getWrap()) == color) fillNeighbors++; // south + if (fillNeighbors < 1) { + // no neighboring fill pixels, this is an unused gap close pixel + } else if (fillNeighbors > 3) { + // too many neighboring fill pixels to be a gap close pixel + // , convert it to a fill pixel + *keepPix = color; + } else { + // does it have at least one unpainted pixel neighbor? + if (((tempX > 0) && (tempPix - 1)->getInk() == 0 && + (*(keepPix - 1) == clickedPosColor)) // west + || ((tempX < refCMRaster->getLx()) && + (tempPix + 1)->getInk() == 0 && + *(keepPix + 1) == clickedPosColor) // east + || ((tempPix + refCMRaster->getWrap())->getInk() == 0 && + *(keepPix + ras->getWrap()) == clickedPosColor) // north + || ((tempPix - refCMRaster->getWrap())->getInk() == 0 && + *(keepPix - ras->getWrap()) == clickedPosColor) // south + ) { + // yes, persist it as a gap close pixel + if (closeGaps) { + *keepPix = gapColor; + } else { + *keepPix = color; + } + } else { + // it is not acting as a border pixel so convert it to a fill + // pixel + *keepPix = color; + } + } } } } diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index 4cfc4ab5..fcf80494 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -181,31 +181,26 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, int ink = pix->getInk(); /* new - * Pseudocode: - * Start the inkFill procedure at the current pixel if: - * The ink colorstyle has autopaint enabled - * The ink colorstyle is not already the same as the fill colorstyle - * The paint colorstyle of a neighboring pixel: - * is the same as the fill colorstyle - * has changed from its prior version - */ + * Pseudocode: + * Start the inkFill procedure at the current pixel if: + * The ink colorstyle has autopaint enabled + * The ink colorstyle is not already the same as the fill colorstyle + * The paint colorstyle of a neighboring pixel: + * is the same as the fill colorstyle + * has changed from its prior version + */ - if (plt->getStyle(ink)->getFlags() != 0 - && ink != fillIndex - && ( - ((pix + r->getWrap())->getPaint() == fillIndex //north - && (pix + r->getWrap())->getPaint() != (pixb + rbefore->getWrap())->getPaint()) - || - ((pix - r->getWrap())->getPaint() == fillIndex //south - && (pix - r->getWrap())->getPaint() != (pixb - rbefore->getWrap())->getPaint()) - || - ((pix + 1)->getPaint() == fillIndex //east - && (pix + 1)->getPaint() != (pixb + 1)->getPaint()) - || - ((pix - 1)->getPaint() == fillIndex //west - && (pix - 1)->getPaint() != (pixb - 1)->getPaint()) - ) - ){ + if (plt->getStyle(ink)->getFlags() != 0 && ink != fillIndex && + (((pix + r->getWrap())->getPaint() == fillIndex // north + && (pix + r->getWrap())->getPaint() != + (pixb + rbefore->getWrap())->getPaint()) || + ((pix - r->getWrap())->getPaint() == fillIndex // south + && (pix - r->getWrap())->getPaint() != + (pixb - rbefore->getWrap())->getPaint()) || + ((pix + 1)->getPaint() == fillIndex // east + && (pix + 1)->getPaint() != (pixb + 1)->getPaint()) || + ((pix - 1)->getPaint() == fillIndex // west + && (pix - 1)->getPaint() != (pixb - 1)->getPaint()))) { inkFill(rin, TPoint(j, i) + rect.getP00(), fillIndex, 0, NULL, &rect); } } From 9139ed9909288515a73bcfc4a76a8dad0da9ed0a Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:50:46 -0400 Subject: [PATCH 5/8] Corrections to gap fills and bounds testing Made corrections to gap fills and added bounds testing for the fill final checks. --- toonz/sources/tnztools/filltool.cpp | 22 ++- toonz/sources/toonzlib/fill.cpp | 269 +++++++++++++--------------- toonz/sources/toonzlib/fillutil.cpp | 34 ++-- 3 files changed, 151 insertions(+), 174 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index f253ce6b..01d78540 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -66,6 +66,7 @@ using namespace ToolUtils; #define FREEPICKFILL L"Freepick" #define IGNORECOLORSTYLE 4093 +#define FAKESTYLEINDEX 4095 TEnv::IntVar MinFillDepth("InknpaintMinFillDepth", 1); TEnv::IntVar MaxFillDepth("InknpaintMaxFillDepth", 10); @@ -605,6 +606,8 @@ public: filler.strokeFill(m_s, m_paintId, m_onlyUnfilled, m_colorType != LINES, m_colorType != AREAS, m_fillArea); + TSystem::outputDebug("filltool.redo() final check, m_fillGaps is:" + std::to_string(m_fillGaps) + "\n"); + // final check if (m_fillGaps) { TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); @@ -614,13 +617,13 @@ public: keepPix->setPaint(tempPix->getPaint()); if (tempPix->getInk() != styleIndex) { if (m_colorType == AREAS && m_closeGaps && - tempPix->getInk() == 4095) { + tempPix->getInk() == FAKESTYLEINDEX) { keepPix->setInk(m_closeStyleIndex); keepPix->setTone(tempPix->getTone()); - } else if (m_colorType != AREAS && tempPix->getInk() == 4095) { + } else if (m_colorType != AREAS && tempPix->getInk() == FAKESTYLEINDEX) { keepPix->setInk(m_paintId); keepPix->setTone(tempPix->getTone()); - } else if (tempPix->getInk() != 4095) { + } else if (tempPix->getInk() != FAKESTYLEINDEX) { keepPix->setInk(tempPix->getInk()); } } @@ -1053,21 +1056,16 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); - //std::cout << "\nFinal Check Started filltool.cpp:fillAreaWithUndo if fillGaps is TRUE"; - //std::cout << "\n---- y:"; - //std::cout << tempRaster->getLy(); - //std::cout << " x:"; - //std::cout << tempRaster->getLx(); - //std::cout << " paint:"; - //std::cout << cs; - //std::cout << "----"; + + TSystem::outputDebug("filltool.fillAreaWithUndo() final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); + for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { //std::cout << "\n y:"; //std::cout << tempY; for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - if (tempPix->getInk() == 4095) { + if (tempPix->getInk() == FAKESTYLEINDEX) { // does this pixel have a fill pixel neighbor? if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && (tempPix - 1)->isPurePaint()) // west diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 80b9395d..0ce7c485 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -20,6 +20,8 @@ #include +#include "tsystem.h" + extern TEnv::DoubleVar AutocloseDistance; extern TEnv::DoubleVar AutocloseAngle; extern TEnv::IntVar AutocloseInk; @@ -521,6 +523,9 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, tempRaster = r; } + TSystem::outputDebug("fill.cpp::fill() tempRaster just after TAutocloser(), fillGaps:" + std::to_string(fillGaps) + "\n"); + //outputPixels("tempRaster", tempRaster); // issue 1151 + /*-- getBounds returns the entire image --*/ TRect bbbox = tempRaster->getBounds(); @@ -644,84 +649,10 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - //std::cout << "\nfill.fill().outputPixels() tempRaster about to populate first seed, fillGaps is:"; + //std::cout << "\nfill.fill().outputPixels() tempRaster about to process close gaps for first seed, fillGaps is:"; //std::cout << fillGaps; //outputPixels("tempRaster",tempRaster); // issue 1151 - - // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 1 of 2 - if (fillGaps || closeGaps) { - - TPixelCM32 *tempPix = tempRaster->pixels(0); - tempPix += (y * tempRaster->getLx()) + xa - 1; - int i = xa; - - while (i <= xb) { - - if (tempPix->getPaint() == paint) { - // check for neighboring gap pixels and finalize them - // west - if ((tempPix - 1)->getInk() == styleIndex) { - if (closeGaps) { - // keep as ink pixel - (tempPix - 1)->setInk(closeStyleIndex); - (tempPix - 1)->setPaint(paint); - (tempPix - 1)->setTone(0); - } else { - // keep as paint pixel - (tempPix - 1)->setInk(0); - (tempPix - 1)->setPaint(paint); - (tempPix - 1)->setTone(255); - } - } - // east - if ((tempPix + 1)->getInk() == styleIndex) { - if (closeGaps) { - // keep as ink pixel - (tempPix + 1)->setInk(closeStyleIndex); - (tempPix + 1)->setPaint(paint); - (tempPix + 1)->setTone(0); - } else { - // keep as paint pixel - (tempPix + 1)->setInk(0); - (tempPix + 1)->setPaint(paint); - (tempPix + 1)->setTone(255); - } - } - // north - if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { - if (closeGaps) { - // keep as ink pixel - (tempPix + tempRaster->getWrap())->setInk(closeStyleIndex); - (tempPix + tempRaster->getWrap())->setPaint(paint); - (tempPix + tempRaster->getWrap())->setTone(0); - } else { - // keep as paint pixel - (tempPix + tempRaster->getWrap())->setInk(0); - (tempPix + tempRaster->getWrap())->setPaint(paint); - (tempPix + tempRaster->getWrap())->setTone(255); - } - } - // south - if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { - if (closeGaps) { - // keep as ink pixel - (tempPix - tempRaster->getWrap())->setInk(closeStyleIndex); - (tempPix - tempRaster->getWrap())->setPaint(paint); - (tempPix - tempRaster->getWrap())->setTone(0); - } else { - // keep as paint pixel - (tempPix - tempRaster->getWrap())->setInk(0); - (tempPix - tempRaster->getWrap())->setPaint(paint); - (tempPix - tempRaster->getWrap())->setTone(255); - } - } - } - tempPix++; - i++; - } - } - while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); @@ -772,40 +703,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, saver); if (xsheet) insertSegment(segments[y], std::pair(xc, xd)); - // Start: Set the ink on gaps that were used to their final value, NOTE: This is duplicate code, 2 of 2 - if (fillGaps || closeGaps) { - - TPixelCM32 *tempPix = tempRaster->pixels(0); - tempPix += (y * tempRaster->getLx()) + xa - 1; - int i = xa; - - while (i <= xb) { - - if (tempPix->getPaint() == paint) { - // check for neighboring gap pixels and finalize them - // west - if ((tempPix - 1)->getInk() == styleIndex) { - (tempPix - 1)->setInk(fakeStyleIndex); - } - // east - if ((tempPix + 1)->getInk() == styleIndex) { - (tempPix + 1)->setInk(fakeStyleIndex); - } - // north - if ((tempPix + tempRaster->getWrap())->getInk() == styleIndex) { - (tempPix + tempRaster->getWrap())->setInk(fakeStyleIndex); - } - // south - if ((tempPix - tempRaster->getWrap())->getInk() == styleIndex) { - (tempPix - tempRaster->getWrap())->setInk(fakeStyleIndex); - } - } - tempPix++; - i++; - } - }// End: Set the ink on gaps that were used to their final value - - if (xc < xa) seeds.push(FillSeed(xc, xa - 1, y, -dy)); if (xd > xb) seeds.push(FillSeed(xb + 1, xd, y, -dy)); if (oldxd >= xc - 1) @@ -848,47 +745,124 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } } - //std::cout << "\nfill.fill().outputPixels() before final, fillGaps is:"; - //std::cout << fillGaps; + TSystem::outputDebug("fill.cpp::fill() before final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); //outputPixels("tempRaster", tempRaster); // issue 1151 - if (fillGaps) { - TPixelCM32 *tempPix = tempRaster->pixels(); - TPixelCM32 *keepPix = r->pixels(); + TPixelCM32 *tempPix, *tempPixRestart; + tempPixRestart = tempPix = tempRaster->pixels(); + TPixelCM32 *keepPix, *keepPixRestart; + keepPixRestart = keepPix = r->pixels(); + int fillNeighbors = 0; + // validate close gap pixels for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - - // Handle pixels of gap close lines, 4094, 4095 if (tempPix->getInk() == fakeStyleIndex || tempPix->getInk() == styleIndex) { - if (tempPix->getInk() == fakeStyleIndex) { - if(closeGaps){ //keep as ink pixel - keepPix->setInk(closeStyleIndex); - keepPix->setPaint(paint); - keepPix->setTone(0); - } else { //keep as paint pixel - keepPix->setInk(0); - keepPix->setPaint(paint); - keepPix->setTone(255); - } - }else{ - // an unused close gap pixel, so ignore + // how many new fill pixel neighbors for the current pixel? + fillNeighbors = 0; + if (tempX > 0 && (tempPix - 1)->getTone() > 0 && + (tempPix - 1)->getInk() < 4093 && + (tempPix - 1)->getPaint() == paint && + (keepPix - 1)->getPaint() != paint) + fillNeighbors++; // west + if (tempX < tempRaster->getLx() - 1 && (tempPix + 1)->getTone() > 0 && + (tempPix + 1)->getInk() < 4093 && + (tempPix + 1)->getPaint() == paint && + (keepPix + 1)->getPaint() != paint) + fillNeighbors++; // east + if (tempY < tempRaster->getLy() - 1 && + (tempPix + tempRaster->getWrap())->getTone() > 0 && + (tempPix + tempRaster->getWrap())->getInk() < 4093 && + (tempPix + tempRaster->getWrap())->getPaint() == paint && + (keepPix + r->getWrap())->getPaint() != paint) + fillNeighbors++; // north + if (tempY > 0 && (tempPix - tempRaster->getWrap())->getTone() > 0 && + (tempPix - tempRaster->getWrap())->getInk() < 4093 && + (tempPix - tempRaster->getWrap())->getPaint() == paint && + (keepPix - r->getWrap())->getPaint() != paint) + fillNeighbors++; // south + if (fillNeighbors < 1) { + // no neighboring new fill pixels, this is an unused gap close pixel + // pull in original values from keepPix for pixel neighbor checks + tempPix->setInk(keepPix->getInk()); + tempPix->setPaint(keepPix->getPaint()); + tempPix->setTone(keepPix->getTone()); + continue; + } + if (fillNeighbors > 3) { + // too many neighboring new fill pixels to be a gap close pixel + // convert it to a fill pixel + tempPix->setInk(0); + tempPix->setPaint(paint); + tempPix->setTone(255); + continue; + } + // does it have at least one paintable but unpainted pixel neighbor? + if ((tempX > 0 && (tempPix - 1)->getInk() < fakeStyleIndex && + (tempPix - 1)->getTone() > 0 && + ((tempPix - 1)->getPaint() == 0 || + (tempPix - 1)->getPaint() == paintAtClickedPos)) // west + || (tempX < tempRaster->getLx() - 1 && + (tempPix + 1)->getInk() < fakeStyleIndex && + (tempPix + 1)->getTone() > 0 && + ((tempPix + 1)->getPaint() == 0 || + (tempPix + 1)->getPaint() == paintAtClickedPos)) // east + || + (tempY < tempRaster->getLy() - 1 && + (tempPix + tempRaster->getWrap())->getInk() < fakeStyleIndex && + (tempPix + tempRaster->getWrap())->getTone() > 0 && + ((tempPix + tempRaster->getWrap())->getPaint() == 0 || + (tempPix + tempRaster->getWrap())->getPaint() == + paintAtClickedPos)) // north + || + (tempY > 0 && + (tempPix - tempRaster->getWrap())->getInk() < fakeStyleIndex && + (tempPix - tempRaster->getWrap())->getTone() > 0 && + ((tempPix - tempRaster->getWrap())->getPaint() == 0 || + (tempPix - tempRaster->getWrap())->getPaint() == + paintAtClickedPos)) // south + ) { + // has a paintable but unpainted neighbor, is this a close and fill + // pixel? + if (closeGaps) { // yes, keep as ink + tempPix->setInk(closeStyleIndex); + tempPix->setPaint(paint); + tempPix->setTone(0); + continue; } - - } else { - // - // Handle all other pixels - // - keepPix->setInk(tempPix->getInk()); - keepPix->setPaint(tempPix->getPaint()); - keepPix->setTone(tempPix->getTone()); + // no, a fill gaps pixel, keep as paint + tempPix->setInk(0); + tempPix->setPaint(paint); + tempPix->setTone(255); + continue; + } + // no, it is not acting as a border pixel so treat it as a fill pixel + tempPix->setInk(0); + tempPix->setPaint(paint); + tempPix->setTone(255); + continue; } } } - //std::cout << "\nfill.cpp:fill final check finished----"; + // persistence pass + tempPix = tempPixRestart; + keepPix = keepPixRestart; + + for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { + for (int tempX = 0; tempX < tempRaster->getLx(); + tempX++, tempPix++, keepPix++) { + keepPix->setInk(tempPix->getInk()); + keepPix->setPaint(tempPix->getPaint()); + keepPix->setTone(tempPix->getTone()); + } + } } + + TSystem::outputDebug("fill.cpp:fill final check finished----\n"); + //outputPixels("r", r); // issue 1151 + return saveBoxChanged; } @@ -1297,8 +1271,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, } } - //std::cout << "\nfill::fullColorFill() step before final, fillGaps is:"; - //std::cout << fillGaps; + TSystem::outputDebug("fill::fullColorFill() final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); //outputPixels("refCMRaster", refCMRaster); // issue 1151 // final check for close gap pixels @@ -1314,10 +1287,12 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, // how many fill pixel neighbors for the current pixel? fillNeighbors = 0; if ((tempX > 0) && *(keepPix - 1) == color) fillNeighbors++; // west - if ((tempX < refCMRaster->getLx()) && *(keepPix + 1) == color) - fillNeighbors++; // east - if (*(keepPix + ras->getWrap()) == color) fillNeighbors++; // north - if (*(keepPix - ras->getWrap()) == color) fillNeighbors++; // south + if (tempX < ras->getLx() - 1 && *(keepPix + 1) == color) + fillNeighbors++; // east + if (tempY < ras->getLy() - 1 && *(keepPix + ras->getWrap()) == color) + fillNeighbors++; // north + if (tempY > 0 && *(keepPix - ras->getWrap()) == color) + fillNeighbors++; // south if (fillNeighbors < 1) { // no neighboring fill pixels, this is an unused gap close pixel } else if (fillNeighbors > 3) { @@ -1328,12 +1303,14 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, // does it have at least one unpainted pixel neighbor? if (((tempX > 0) && (tempPix - 1)->getInk() == 0 && (*(keepPix - 1) == clickedPosColor)) // west - || ((tempX < refCMRaster->getLx()) && + || (tempX < refCMRaster->getLx() - 1 && (tempPix + 1)->getInk() == 0 && *(keepPix + 1) == clickedPosColor) // east - || ((tempPix + refCMRaster->getWrap())->getInk() == 0 && + || (tempY < refCMRaster->getLy() - 1 && + (tempPix + refCMRaster->getWrap())->getInk() == 0 && *(keepPix + ras->getWrap()) == clickedPosColor) // north - || ((tempPix - refCMRaster->getWrap())->getInk() == 0 && + || (tempY > 0 && + (tempPix - refCMRaster->getWrap())->getInk() == 0 && *(keepPix - ras->getWrap()) == clickedPosColor) // south ) { // yes, persist it as a gap close pixel diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index fcf80494..400f1574 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -158,12 +158,8 @@ AreaFiller::AreaFiller(const TRasterCM32P &ras) AreaFiller::~AreaFiller() { m_ras->unlock(); } //----------------------------------------------------------------------------- -// questa funzione viene chiamata dopo il fill rect delle aree, e colora gli -// inchiostri di tipo "autoink" -// che confinano con le aree appena fillate con il rect. rbefore e' il rect del -// raster prima del rectfill. // This function is called after rect fill of the areas, and colors the -// "autoink" type inks bordering the areas just filled with the rect. +// "autoink" type inks bordering the areas just filled with the rect. // rbefore is the rect of the raster before rectfill. void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, TPalette *plt, int fillIndex) { @@ -171,7 +167,7 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, TRasterCM32P r = rin->extract(rect); assert(r->getSize() == rbefore->getSize()); int i, j; - + for (i = 0; i < r->getLy(); i++) { TPixelCM32 *pix = r->pixels(i); TPixelCM32 *pixb = rbefore->pixels(i); @@ -191,16 +187,22 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, */ if (plt->getStyle(ink)->getFlags() != 0 && ink != fillIndex && - (((pix + r->getWrap())->getPaint() == fillIndex // north - && (pix + r->getWrap())->getPaint() != - (pixb + rbefore->getWrap())->getPaint()) || - ((pix - r->getWrap())->getPaint() == fillIndex // south - && (pix - r->getWrap())->getPaint() != - (pixb - rbefore->getWrap())->getPaint()) || - ((pix + 1)->getPaint() == fillIndex // east - && (pix + 1)->getPaint() != (pixb + 1)->getPaint()) || - ((pix - 1)->getPaint() == fillIndex // west - && (pix - 1)->getPaint() != (pixb - 1)->getPaint()))) { + ( + // north + (i < r->getLy() - 1 && + (pix + r->getWrap())->getPaint() == fillIndex && + (pix + r->getWrap())->getPaint() != + (pixb + rbefore->getWrap())->getPaint()) + // south + || (i > 0 && (pix - r->getWrap())->getPaint() == fillIndex && + (pix - r->getWrap())->getPaint() != + (pixb - rbefore->getWrap())->getPaint()) + // east + || (j < r->getLx() - 1 && (pix + 1)->getPaint() == fillIndex && + (pix + 1)->getPaint() != (pixb + 1)->getPaint()) + // west + || (j > 0 && (pix - 1)->getPaint() == fillIndex && + (pix - 1)->getPaint() != (pixb - 1)->getPaint()))) { inkFill(rin, TPoint(j, i) + rect.getP00(), fillIndex, 0, NULL, &rect); } } From 881c6f9166b0797811d2eb06fe322d02dd276620 Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:44:30 -0400 Subject: [PATCH 6/8] Updated to treat a gap close line as a single unit Updated the logic handling gap close lines to treat it as a line instead of separately handling each pixel. More still to be done on Undo/Redo logic. Update the show() logic to display a label for Distance on the Normal Fill tool while on a Raster level in Fill Gap mode. --- toonz/sources/include/toonz/fill.h | 6 + toonz/sources/tnztools/filltool.cpp | 159 ++++++++------- toonz/sources/tnztools/tooloptions.cpp | 2 +- toonz/sources/toonzlib/fill.cpp | 166 ++++++---------- toonz/sources/toonzlib/fillutil.cpp | 259 +++++++++++++++++++++++-- 5 files changed, 388 insertions(+), 204 deletions(-) diff --git a/toonz/sources/include/toonz/fill.h b/toonz/sources/include/toonz/fill.h index bcc5c620..cd1cc3e3 100644 --- a/toonz/sources/include/toonz/fill.h +++ b/toonz/sources/include/toonz/fill.h @@ -105,6 +105,12 @@ void DVAPI fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, bool closeGaps = false, int closeStyleIndex = -1, double autoCloseDistance = -1.0); +void DVAPI finishGapLines(TRasterCM32P &rin, TRect &rect, + const TRasterCM32P &rbefore, + const TRasterCM32P &combined, TPalette *plt, + int clickedColorStyle, int fillIndex, + int closeColorStyle, bool closeGaps); + //============================================================================= //! The class AreaFiller allows to fill a raster area, delimited by rect or //! spline. diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 01d78540..4ea16ff3 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -65,8 +65,9 @@ using namespace ToolUtils; #define POLYLINEFILL L"Polyline" #define FREEPICKFILL L"Freepick" +#define GAP_CLOSE_USED 4095 +#define GAP_CLOSE_TEMP 4094 #define IGNORECOLORSTYLE 4093 -#define FAKESTYLEINDEX 4095 TEnv::IntVar MinFillDepth("InknpaintMinFillDepth", 1); TEnv::IntVar MaxFillDepth("InknpaintMaxFillDepth", 10); @@ -155,6 +156,8 @@ bool applyAutoclose(const TToonzImageP &ti, int distance, int angle, ras = raux; if (!ras) return false; + //outputPixels("ras in applyAutoClose", ras); + TAutocloser ac(ras, distance, angle, newInkIndex, opacity); std::vector segments; @@ -467,14 +470,9 @@ class RasterFillUndo final : public TRasterUndo { public: /*RasterFillUndo(TTileSetCM32 *tileSet, TPoint fillPoint, - int paintId, int - fillDepth, - std::wstring - fillType, bool isSegment, - bool selective, bool - isShiftFill, - TXshSimpleLevel* sl, - const TFrameId& fid)*/ + int paintId, int fillDepth, std::wstring fillType, + bool isSegment, bool selective, bool isShiftFill, + TXshSimpleLevel* sl, const TFrameId& fid)*/ RasterFillUndo(TTileSetCM32 *tileSet, const FillParameters ¶ms, TXshSimpleLevel *sl, const TFrameId &fid, bool saveboxOnly, bool fillGaps, bool closeGaps, int closeStyleIndex, @@ -587,13 +585,13 @@ public: TRasterCM32P ras = image->getRaster(); TRasterCM32P tempRaster; - int styleIndex = 4094; + int styleIndex = GAP_CLOSE_TEMP; if (m_fillGaps) { TToonzImageP tempTi = image->clone(); tempRaster = tempTi->getRaster(); TRectD doubleFillArea = convert(m_fillArea); applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle, - AutocloseOpacity, 4094, doubleFillArea, m_s); + AutocloseOpacity, GAP_CLOSE_TEMP, doubleFillArea, m_s); } else { tempRaster = ras; } @@ -606,26 +604,60 @@ public: filler.strokeFill(m_s, m_paintId, m_onlyUnfilled, m_colorType != LINES, m_colorType != AREAS, m_fillArea); - TSystem::outputDebug("filltool.redo() final check, m_fillGaps is:" + std::to_string(m_fillGaps) + "\n"); + TSystem::outputDebug("filltool.redo() final check, m_fillGaps is:" + std::to_string(m_fillGaps)); // final check + + // ToDo - call finishGapLines instead of this code + //void finishGapLines(TRasterCM32P & rin, TRect & rect, const TRasterCM32P & rbefore, + // const TRasterCM32P & combined, TPalette * plt, + // int clickedColorStyle, int fillIndex, int closeColorStyle, + // bool closeGaps) { + + if (m_fillGaps) { + + TRect rect = m_fillArea; + finishGapLines( + tempRaster, + rect, + ras, + tempRaster, + m_palette, + 0, + m_paintId, + m_closeStyleIndex, + m_closeGaps); + TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); + //for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { + // for (int tempX = 0; tempX < tempRaster->getLx(); + // tempX++, tempPix++, keepPix++) { + // keepPix->setPaint(tempPix->getPaint()); + // if (tempPix->getInk() != styleIndex) { + // if (m_colorType == AREAS && m_closeGaps && + // tempPix->getInk() == GAP_CLOSE_USED) { + // keepPix->setInk(m_closeStyleIndex); + // keepPix->setTone(tempPix->getTone()); + // } else if (m_colorType != AREAS && tempPix->getInk() == GAP_CLOSE_USED) { + // keepPix->setInk(m_paintId); + // keepPix->setTone(tempPix->getTone()); + // } else if (tempPix->getInk() != GAP_CLOSE_USED) { + // keepPix->setInk(tempPix->getInk()); + // } + // } + // } + //} for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { keepPix->setPaint(tempPix->getPaint()); - if (tempPix->getInk() != styleIndex) { - if (m_colorType == AREAS && m_closeGaps && - tempPix->getInk() == FAKESTYLEINDEX) { - keepPix->setInk(m_closeStyleIndex); - keepPix->setTone(tempPix->getTone()); - } else if (m_colorType != AREAS && tempPix->getInk() == FAKESTYLEINDEX) { - keepPix->setInk(m_paintId); - keepPix->setTone(tempPix->getTone()); - } else if (tempPix->getInk() != FAKESTYLEINDEX) { - keepPix->setInk(tempPix->getInk()); - } + if (tempPix->getInk() >= IGNORECOLORSTYLE || tempPix->getPaint() >= IGNORECOLORSTYLE) { + continue; + } else { + keepPix->setInk(tempPix->getInk()); + keepPix->setPaint(tempPix->getPaint()); + keepPix->setTone(tempPix->getTone()); } } } @@ -993,8 +1025,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, TRectD selArea = stroke ? stroke->getBBox() : area; if (TToonzImageP ti = img) { - // allargo di 1 la savebox, perche cosi' il rectfill di tutta l'immagine fa - // una sola fillata // Widen the savebox by 1, because this is how the rectfill of the whole image does // a single fill TRect enlargedSavebox = @@ -1007,7 +1037,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, if (rasterFillArea.isEmpty()) return; TRasterCM32P ras = ti->getRaster(); - /*-- tileSetでFill範囲のRectをUndoに格納しておく --*/ /* Store the Rect of the Fill range in Undo with tileSet */ TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize()); tileSet->add(ras, rasterFillArea); @@ -1017,16 +1046,17 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, //outputPixels("ras", ras); TRasterCM32P tempRaster; - int styleIndex = 4094; + int styleIndex = GAP_CLOSE_TEMP; TToonzImageP tempTi = ti->clone(); tempRaster = tempTi->getRaster(); + //outputPixels("tempRaster before auto close", tempRaster); if (fillGaps) { applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle, - AutocloseOpacity, 4094, convert(rasterFillArea), stroke); + AutocloseOpacity, GAP_CLOSE_TEMP, convert(rasterFillArea), stroke); //std::cout << "\nfillAreaWithUndo after applyAutoclose, tempRaster size:"; //std::cout << tempRaster->getSize(); @@ -1054,65 +1084,32 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, //outputPixels("tempRaster", tempRaster); } - TPixelCM32 *tempPix = tempRaster->pixels(); - TPixelCM32 *keepPix = ras->pixels(); + TPixelCM32 *tempPix = tempRaster->pixels(); + TPixelCM32 *keepPix = ras->pixels(); - TSystem::outputDebug("filltool.fillAreaWithUndo() final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); + TSystem::outputDebug( + "filltool.fillAreaWithUndo() final check, fillGaps is:" + + std::to_string(fillGaps) + "\n"); - for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - //std::cout << "\n y:"; - //std::cout << tempY; - for (int tempX = 0; tempX < tempRaster->getLx(); - tempX++, tempPix++, keepPix++) { + finishGapLines(tempRaster, rasterFillArea, ras, ras, ti->getPalette(), 0, + cs, closeStyleIndex, closeGaps); - if (tempPix->getInk() == FAKESTYLEINDEX) { - // does this pixel have a fill pixel neighbor? - if (((tempX > 0) && ((tempPix - 1)->getPaint() == cs) && - (tempPix - 1)->isPurePaint()) // west - || ((tempX < tempRaster->getLx()) && - ((tempPix + 1)->getPaint() == cs) && - (tempPix + 1)->isPurePaint()) // east - || - ((tempPix + tempRaster->getWrap())->getPaint() == cs && - (tempPix + tempRaster->getWrap())->isPurePaint()) // north - || - ((tempPix - tempRaster->getWrap())->getPaint() == cs && - (tempPix - tempRaster->getWrap())->isPurePaint()) // south - ) { // yes, keep this pixel - if (closeGaps) { - // keep as ink line - keepPix->setInk(closeStyleIndex); - keepPix->setPaint(cs); - keepPix->setTone(0); - } - else { - // keep as paint - // keepPix->setInk(paint); - keepPix->setPaint(cs); - keepPix->setTone(255); - } - } else { - //unwanted close gap pixel - } - } else if (tempPix->getPaint() == IGNORECOLORSTYLE || tempPix->getInk() == IGNORECOLORSTYLE) { - // IGNORECOLORSTYLE is a color style index value used to identify pixels to not persist. - // Pixels are set to this value in fillutil::restoreColors() - // It indicates pixels that should be discarded by this final check routine. - // This allows original pixel values to persist. - } else { - // Handle all other pixels - if (tempPix->getPaint() == cs){ - keepPix->setInk(tempPix->getInk()); - keepPix->setPaint(tempPix->getPaint()); - keepPix->setTone(tempPix->getTone()); - } - } + for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { + for (int tempX = 0; tempX < tempRaster->getLx(); + tempX++, tempPix++, keepPix++) { + if (tempPix->getInk() >= IGNORECOLORSTYLE || + tempPix->getPaint() >= IGNORECOLORSTYLE) { + continue; + } else { + // Handle all other pixels + keepPix->setInk(tempPix->getInk()); + keepPix->setPaint(tempPix->getPaint()); + keepPix->setTone(tempPix->getTone()); } } + } - //std::cout << "\nFinal Check Complete fillAreaWithUndo ras at end of filltool.cpp:fillAreaWithUndo if fillGaps"; - //std::cout << fillGaps; - //std::cout << ras->getSize(); + TSystem::outputDebug("filltool.fillAreaWithUndo() final check complete.\n"); //outputPixels("ras", ras); TPalette *plt = ti->getPalette(); diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 9d551625..f9fa7e87 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -1801,7 +1801,7 @@ void FullColorFillToolOptionsBox::onGapSettingChanged(int index) { m_styleIndex->hide(); m_styleIndexLabel->hide(); m_rasterGapSlider->show(); - m_gapSliderLabel->hide(); + m_gapSliderLabel->show(); } else if (index == 2) { m_styleIndex->show(); m_styleIndexLabel->show(); diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 0ce7c485..99c50329 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -27,6 +27,10 @@ extern TEnv::DoubleVar AutocloseAngle; extern TEnv::IntVar AutocloseInk; extern TEnv::IntVar AutocloseOpacity; +#define IGNORECOLORSTYLE 4093 +#define GAP_CLOSE_TEMP 4094 +#define GAP_CLOSE_USED 4095 + //----------------------------------------------------------------------------- namespace { // Utility Function //----------------------------------------------------------------------------- @@ -506,9 +510,9 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, int paint = params.m_styleId; int fillDepth = params.m_shiftFill ? params.m_maxFillDepth : params.m_minFillDepth; - TRasterCM32P tempRaster; - int styleIndex = 4094; - int fakeStyleIndex = 4095; + TRasterCM32P tempRaster, cr, refCMRaster; + int styleIndex = GAP_CLOSE_TEMP; + int fakeStyleIndex = GAP_CLOSE_USED; if (autoCloseDistance < 0.0) autoCloseDistance = AutocloseDistance; bool gapsClosed = false, refGapsClosed = false; @@ -523,7 +527,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, tempRaster = r; } - TSystem::outputDebug("fill.cpp::fill() tempRaster just after TAutocloser(), fillGaps:" + std::to_string(fillGaps) + "\n"); + //TSystem::outputDebug("fill.cpp::fill() tempRaster just after TAutocloser(), fillGaps:" + std::to_string(fillGaps) + "\n"); //outputPixels("tempRaster", tempRaster); // issue 1151 /*-- getBounds returns the entire image --*/ @@ -574,8 +578,11 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } if (fillGaps) { - TRasterCM32P cr = convertRaster2CM(refRaster); - TRasterCM32P refCMRaster = cr->clone(); + cr = convertRaster2CM(refRaster); + refCMRaster = cr->clone(); + + //outputPixels("refCMRaster", refCMRaster); + //outputPixels("cr", cr); refGapsClosed = TAutocloser(refCMRaster, autoCloseDistance, AutocloseAngle, styleIndex, AutocloseOpacity) @@ -584,6 +591,7 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, if (!gapsClosed) tempRaster = r->clone(); // Transfer the gap segments to the refRaster + TSystem::outputDebug("fill.cpp::fill() Transfer the gap segments to the refRaster, refGapsClosed:" + std::to_string(refGapsClosed) +", gapsClosed:" + std::to_string(gapsClosed)); TPixelCM32 *tempPix = tempRaster->pixels(0); TPixelCM32 *refCMPix = refCMRaster->pixels(0); TPixel32 *refPix = refRaster->pixels(0); @@ -592,7 +600,8 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, refCMX++, refCMPix++, refPix++, tempPix++) { if (refCMPix->getInk() != styleIndex) continue; *refPix = color; - if (closeGaps) { + if (fillGaps) { + TSystem::outputDebug("y:" + std::to_string(refCMY) + "," + "x:" + std::to_string(refCMX) + "," + std::to_string(refCMPix->getInk()) + ":" + std::to_string(refCMPix->getPaint()) + ":" + std::to_string(refCMPix->getTone()) + "\n"); tempPix->setInk(refCMPix->getInk()); tempPix->setTone(refCMPix->getTone()); } @@ -602,7 +611,10 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } } - if (fillGaps && !gapsClosed && !refGapsClosed) fillGaps = false; + if (fillGaps && !gapsClosed && !refGapsClosed) { + fillGaps = false; + TSystem::outputDebug("fill.cpp::fill(), refGapsClosed:" + std::to_string(refGapsClosed) + ", gapsClosed:" + std::to_string(gapsClosed) + ", set fillGaps to:" + std::to_string(fillGaps)); + } assert(fillDepth >= 0 && fillDepth < 16); @@ -745,114 +757,23 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } } - TSystem::outputDebug("fill.cpp::fill() before final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); - //outputPixels("tempRaster", tempRaster); // issue 1151 - if (fillGaps) { + TSystem::outputDebug("fill.cpp::fill() final check, fillGaps is:" + std::to_string(fillGaps)); + //outputPixels("tempRaster", tempRaster); // issue 1151 + finishGapLines(tempRaster, bbbox, r, refCMRaster, params.m_palette, paintAtClickedPos, paint, closeStyleIndex, closeGaps); TPixelCM32 *tempPix, *tempPixRestart; tempPixRestart = tempPix = tempRaster->pixels(); TPixelCM32 *keepPix, *keepPixRestart; keepPixRestart = keepPix = r->pixels(); - int fillNeighbors = 0; - // validate close gap pixels - for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - for (int tempX = 0; tempX < tempRaster->getLx(); - tempX++, tempPix++, keepPix++) { - if (tempPix->getInk() == fakeStyleIndex || - tempPix->getInk() == styleIndex) { - // how many new fill pixel neighbors for the current pixel? - fillNeighbors = 0; - if (tempX > 0 && (tempPix - 1)->getTone() > 0 && - (tempPix - 1)->getInk() < 4093 && - (tempPix - 1)->getPaint() == paint && - (keepPix - 1)->getPaint() != paint) - fillNeighbors++; // west - if (tempX < tempRaster->getLx() - 1 && (tempPix + 1)->getTone() > 0 && - (tempPix + 1)->getInk() < 4093 && - (tempPix + 1)->getPaint() == paint && - (keepPix + 1)->getPaint() != paint) - fillNeighbors++; // east - if (tempY < tempRaster->getLy() - 1 && - (tempPix + tempRaster->getWrap())->getTone() > 0 && - (tempPix + tempRaster->getWrap())->getInk() < 4093 && - (tempPix + tempRaster->getWrap())->getPaint() == paint && - (keepPix + r->getWrap())->getPaint() != paint) - fillNeighbors++; // north - if (tempY > 0 && (tempPix - tempRaster->getWrap())->getTone() > 0 && - (tempPix - tempRaster->getWrap())->getInk() < 4093 && - (tempPix - tempRaster->getWrap())->getPaint() == paint && - (keepPix - r->getWrap())->getPaint() != paint) - fillNeighbors++; // south - if (fillNeighbors < 1) { - // no neighboring new fill pixels, this is an unused gap close pixel - // pull in original values from keepPix for pixel neighbor checks - tempPix->setInk(keepPix->getInk()); - tempPix->setPaint(keepPix->getPaint()); - tempPix->setTone(keepPix->getTone()); - continue; - } - if (fillNeighbors > 3) { - // too many neighboring new fill pixels to be a gap close pixel - // convert it to a fill pixel - tempPix->setInk(0); - tempPix->setPaint(paint); - tempPix->setTone(255); - continue; - } - // does it have at least one paintable but unpainted pixel neighbor? - if ((tempX > 0 && (tempPix - 1)->getInk() < fakeStyleIndex && - (tempPix - 1)->getTone() > 0 && - ((tempPix - 1)->getPaint() == 0 || - (tempPix - 1)->getPaint() == paintAtClickedPos)) // west - || (tempX < tempRaster->getLx() - 1 && - (tempPix + 1)->getInk() < fakeStyleIndex && - (tempPix + 1)->getTone() > 0 && - ((tempPix + 1)->getPaint() == 0 || - (tempPix + 1)->getPaint() == paintAtClickedPos)) // east - || - (tempY < tempRaster->getLy() - 1 && - (tempPix + tempRaster->getWrap())->getInk() < fakeStyleIndex && - (tempPix + tempRaster->getWrap())->getTone() > 0 && - ((tempPix + tempRaster->getWrap())->getPaint() == 0 || - (tempPix + tempRaster->getWrap())->getPaint() == - paintAtClickedPos)) // north - || - (tempY > 0 && - (tempPix - tempRaster->getWrap())->getInk() < fakeStyleIndex && - (tempPix - tempRaster->getWrap())->getTone() > 0 && - ((tempPix - tempRaster->getWrap())->getPaint() == 0 || - (tempPix - tempRaster->getWrap())->getPaint() == - paintAtClickedPos)) // south - ) { - // has a paintable but unpainted neighbor, is this a close and fill - // pixel? - if (closeGaps) { // yes, keep as ink - tempPix->setInk(closeStyleIndex); - tempPix->setPaint(paint); - tempPix->setTone(0); - continue; - } - // no, a fill gaps pixel, keep as paint - tempPix->setInk(0); - tempPix->setPaint(paint); - tempPix->setTone(255); - continue; - } - // no, it is not acting as a border pixel so treat it as a fill pixel - tempPix->setInk(0); - tempPix->setPaint(paint); - tempPix->setTone(255); - continue; - } - } - } - // persistence pass - tempPix = tempPixRestart; - keepPix = keepPixRestart; + int fillNeighbors = 0; + int paintableNeighbors = 0; for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { + if (tempPix->getInk() >= IGNORECOLORSTYLE || tempPix->getPaint() >= IGNORECOLORSTYLE) { + continue; + } keepPix->setInk(tempPix->getInk()); keepPix->setPaint(tempPix->getPaint()); keepPix->setTone(tempPix->getTone()); @@ -1089,8 +1010,8 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, TRaster32P refRas(bbbox.getSize()); TPixel32 gapColor = plt->getStyle(closeStyleIndex)->getMainColor(); - int styleIndex = 4094; - int fakeStyleIndex = 4095; + int styleIndex = GAP_CLOSE_TEMP; + int fakeStyleIndex = GAP_CLOSE_USED; if (xsheet) { ToonzScene *scene = xsheet->getScene(); @@ -1115,9 +1036,10 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, } TRasterCM32P refCMRaster; + TRasterCM32P cr; if (fillGaps) { - TRasterCM32P cr = convertRaster2CM(refRas); + cr = convertRaster2CM(refRas); refCMRaster = cr->clone(); fillGaps = TAutocloser(refCMRaster, autoCloseDistance, AutocloseAngle, styleIndex, AutocloseOpacity) @@ -1271,11 +1193,32 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, } } - TSystem::outputDebug("fill::fullColorFill() final check, fillGaps is:" + std::to_string(fillGaps) + "\n"); + TSystem::outputDebug("fill::fullColorFill() final check, fillGaps is:" + std::to_string(fillGaps)); //outputPixels("refCMRaster", refCMRaster); // issue 1151 // final check for close gap pixels if (fillGaps) { + + // ToDo - Can this be adpated to call finishGapClosePixels instead of the logic below? + // This logic doesn't use the palette color styles it uses RGB pixel values + //void finishGapLines(TRasterCM32P& rin, TRect& rect, const TRasterCM32P& rbefore, + // const TRasterCM32P& combined, TPalette* plt, + // int clickedColorStyle, int fillIndex, int closeColorStyle, + // bool closeGaps) { + + //finishGapLines( + // refCMRaster, + // bbbox, + // cr, + // refCMRaster, + // params.m_palette, + // clickedPosColor, + // fillIndex, + // closeStyleIndex, + // closeGaps + //); + + TPixelCM32 *tempPix = refCMRaster->pixels(); TPixel32 *keepPix = ras->pixels(); int fillNeighbors; @@ -1295,6 +1238,7 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, fillNeighbors++; // south if (fillNeighbors < 1) { // no neighboring fill pixels, this is an unused gap close pixel + continue; } else if (fillNeighbors > 3) { // too many neighboring fill pixels to be a gap close pixel // , convert it to a fill pixel diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index 400f1574..11b3847f 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -12,8 +12,11 @@ #include "tpixelutils.h" #include +#include #define IGNORECOLORSTYLE 4093 +#define GAP_CLOSE_TEMP 4094 +#define GAP_CLOSE_USED 4095 using namespace SkeletonLut; @@ -81,8 +84,7 @@ void fillArea(const TRasterCM32P &ras, TRegion *r, int colorId, for (int k = from; k < to; k++, pix++) { if (fillPaints && (!onlyUnfilled || pix->getPaint() == 0)) pix->setPaint(colorId); - if (fillInks && pix->getInk() != 4094) pix->setInk(colorId); - if (pix->getInk() == 4094) pix->setInk(4095); + if (fillInks && pix->getInk() != GAP_CLOSE_TEMP) pix->setInk(colorId); } } } @@ -100,7 +102,7 @@ void restoreColors(const TRasterCM32P &r, params.m_p = seeds[i].first; //params.m_styleId = seeds[i].second; //params.m_styleId = 0; - params.m_styleId = IGNORECOLORSTYLE; //an unused color style value used to control a later final check + params.m_styleId = IGNORECOLORSTYLE; //set to ignore in final check fill(r, params); } } @@ -141,6 +143,242 @@ bool areRectPixelsTransparent(TPixel32 *pixels, TRect rect, int wrap) { } // namespace //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined, + const TPoint &pin, int clickedColorStyle, int fillColorStyle, + int closeColorStyle, int searchRay, TRect *insideRect, + bool closeGaps) { + r->lock(); + + TRasterCM32P myCombined; + if (!combined.getPointer() || combined->isEmpty()) { + myCombined = r; + } else { + myCombined = combined; + } + + TPixelCM32 *pixels = (TPixelCM32 *)r->getRawData(); + TPixelCM32 *combinedPixels = (TPixelCM32 *)myCombined->getRawData(); + ; + TPoint p = pin; + int filledNeighbor = 0; + int unfilledNeighbor = 0; + int inkStyle = 0; + int paintStyle = 0; + int toneValue = 0; + + TSystem::outputDebug( + "fillutil.finishGapLine(), closeGaps:" + std::to_string(closeGaps) + + ", clickedColorStyle:" + std::to_string(clickedColorStyle) + + ", fillColorStyle:" + std::to_string(fillColorStyle) + + ", closeColorStyle:" + std::to_string(closeColorStyle)); + TSystem::outputDebug("point is p.y:" + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x)); + + TSystem::outputDebug("r->getBounds()), ly:" + std::to_string(r->getBounds().getLy()) + ", lx:" + std::to_string(r->getBounds().getLx())); + TSystem::outputDebug("insideRect, ly:" + std::to_string(insideRect->getLy()) + ", lx : " + std::to_string(insideRect->getLx())); + + + TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); + TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x); + + // outputPixels("r", r); + + std::stack gapLinePixels; + std::stack seeds; + seeds.push(p); + + while (!seeds.empty()) { + p = seeds.top(); + seeds.pop(); + + if (!r->getBounds().contains(p)) { + TSystem::outputDebug("fillutil.finishGapLine(), out of bounds at p.y:" + + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x)); + continue; + } + if (insideRect && !insideRect->contains(p)) { + TSystem::outputDebug("fillutil.finishGapLine(), insideRect && !insideRect->contains(p) at p.y:" + + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x)); + continue; + } + + TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); + TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x); + + TSystem::outputDebug("--------------------- checking pixel at: p.y:" + + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x) + + ", ink:" + std::to_string(pix->getInk()) + + ", paint:" + std::to_string(pix->getPaint()) + + ", tone:" + std::to_string(pix->getTone()) + + ", pixc " + + ", ink:" + std::to_string(pixc->getInk()) + + ", paint:" + std::to_string(pixc->getPaint()) + + ", tone:" + std::to_string(pixc->getTone())); + + + // handle gap close pixel + if (pix->getInk() == GAP_CLOSE_USED) continue; + if (pix->getInk() == GAP_CLOSE_TEMP) { + TSystem::outputDebug("Gap Close pixel at p.y:" + + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x)); + + pix->setInk(GAP_CLOSE_USED); + // push to the gapLinePixels collection for later processing as a line + gapLinePixels.push(p); + + // push neighboring pixels into the seeds queue + seeds.push(TPoint(p.x - 1, p.y - 1)); // sw + seeds.push(TPoint(p.x - 1, p.y)); // west + seeds.push(TPoint(p.x - 1, p.y + 1)); // nw + seeds.push(TPoint(p.x, p.y - 1)); // south + seeds.push(TPoint(p.x, p.y + 1)); // north + seeds.push(TPoint(p.x + 1, p.y - 1)); // se + seeds.push(TPoint(p.x + 1, p.y)); // east + seeds.push(TPoint(p.x + 1, p.y + 1)); // ne + continue; + } + // a neighboring filled pixel + if (pix->getTone() > 0 && pix->getPaint() == fillColorStyle) { + filledNeighbor++; + TSystem::outputDebug(" Filled neighbor at p.y:" + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x) + " "); + continue; + } + // a neighboring fillable but unfilled pixel + if ((pix->getTone() == 255 && ((pix->getPaint() == clickedColorStyle) || + (pix->getPaint() == 0) || (pix->getPaint() == IGNORECOLORSTYLE))) && + (pixc->getTone() == 255 && ((pixc->getPaint() == clickedColorStyle) || + (pixc->getPaint() == 0)))) { + unfilledNeighbor++; + TSystem::outputDebug(" Unfilled neighbor at p.y:" + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x) + " "); + continue; + } + } + + TSystem::outputDebug("fillutil.finishGapLine(), filledNeighbor:" + + std::to_string(filledNeighbor) + ", unfilledNeighbor:" + + std::to_string(unfilledNeighbor)); + + // determine the final disposition of the gap line + if (filledNeighbor > 0) { + if (unfilledNeighbor > 0) { + TSystem::outputDebug( + "fillutil.finishGapLine(), a needed line so let's finish it."); + if (closeGaps) { + TSystem::outputDebug("fillutil.finishGapLine(), finish as ink."); + inkStyle = closeColorStyle; + paintStyle = fillColorStyle; + toneValue = 0; + } else { + TSystem::outputDebug("fillutil.finishGapLine(), finish as paint."); + inkStyle = 0; + paintStyle = fillColorStyle; + toneValue = 255; + } + } else { + // surrounded by filled pixels, not a needed line, fill with fill color + TSystem::outputDebug( + "fillutil.finishGapLine(), No unfilled pixel neighbors, so fill with " + "fill color."); + inkStyle = 0; + paintStyle = fillColorStyle; + toneValue = 255; + } + } else { + // not a needed line, restore original pixels + // set to IGNORECOLORSTYLE to resolve in final check + TSystem::outputDebug( + "fillutil.finishGapLine(), not a needed line, set ink to a value to " + "ignore later."); + inkStyle = IGNORECOLORSTYLE; + paintStyle = 0; + toneValue = 0; + } + + // process the stored gap close line pixels + while (!gapLinePixels.empty()) { + p = gapLinePixels.top(); + gapLinePixels.pop(); + + // do I need these checks since these points are already valid? + if (!r->getBounds().contains(p)) continue; + if (insideRect && !insideRect->contains(p)) continue; + + TSystem::outputDebug("finishing point p.y:" + std::to_string(p.y) + + ", p.x:" + std::to_string(p.x)); + + TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); + + pix->setInk(inkStyle); + pix->setPaint(paintStyle); + pix->setTone(toneValue); + } + + r->unlock(); +} + +//----------------------------------------------------------------------------- +// This function finishes candidate gap lines that were created +// during a fill process. +// combined is the levels combined as is done for the "use visible" tool option +void finishGapLines(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, + const TRasterCM32P &combined, TPalette *plt, + int clickedColorStyle, int fillIndex, int closeColorStyle, + bool closeGaps) { + assert(plt); + TRasterCM32P r = rin->extract(rect); + assert(r->getSize() == rbefore->getSize()); + assert(r->getSize() == combined->getSize()); + int i, j; + + for (i = 0; i < r->getLy(); i++) { + TPixelCM32 *pix = r->pixels(i); + TPixelCM32 *pixb = rbefore->pixels(i); + for (j = 0; j < r->getLx(); j++, pix++, pixb++) { + int paint = pix->getPaint(); + int tone = pix->getTone(); + int ink = pix->getInk(); + + /* Pseudocode: + * Start the finish line procedure at the current pixel if: + * The ink colorstyle is TEMP_GAP_CLOSE + * The paint colorstyle of at least one neighboring pixel: + * is the same as the fill colorstyle + * has changed from its prior version + */ + + if (ink == GAP_CLOSE_TEMP && + ( + // north + (i < rin->getLy() - 1 && + (pix + rin->getWrap())->getPaint() == fillIndex && + (pix + rin->getWrap())->getPaint() != + (pixb + rbefore->getWrap())->getPaint()) + // south + || (i > 0 && (pix - rin->getWrap())->getPaint() == fillIndex && + (pix - rin->getWrap())->getPaint() != + (pixb - rbefore->getWrap())->getPaint()) + // east + || (j < rin->getLx() - 1 && (pix + 1)->getPaint() == fillIndex && + (pix + 1)->getPaint() != (pixb + 1)->getPaint()) + // west + || (j > 0 && (pix - 1)->getPaint() == fillIndex && + (pix - 1)->getPaint() != (pixb - 1)->getPaint()))) { + finishGapLine(rin, combined, TPoint(j, i) + rect.getP00(), + clickedColorStyle, fillIndex, closeColorStyle, 0, &rect, + closeGaps); + } + } + } +} + //============================================================================= // AreaFiller @@ -214,7 +452,7 @@ void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled, bool fillPaints, bool fillInks) { // Synopsis: - // This gets the color of the pixes at the edge of the rect + // This gets the color of the pixels at the edge of the rect // Then fills in EVERYTHING with 'color' // Then uses the fill command to fill in the edges with their original color // This makes sure only the enclosed areas not on the edge get filled. @@ -226,8 +464,9 @@ bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled, for (int y = rect.y0; y <= rect.y1; y++) { TPixelCM32 *pix = m_ras->pixels(y) + rect.x0; for (int x = rect.x0; x <= rect.x1; x++, pix++) { - if (pix->getInk() == 4094) - pix->setInk(4095); + if (pix->getInk() == GAP_CLOSE_TEMP) + //pix->setInk(TEMP_GAP_CLOSE_WAS_USED); + continue; else pix->setInk(color); } @@ -280,18 +519,16 @@ bool AreaFiller::rectFill(const TRect &rect, int color, bool onlyUnfilled, for (x = r.x0; x <= r.x1; x++, pix++) { if (pix->getPaint() == 0) // BackgroundStyle pix->setPaint(color); - if (fillInks && (pix->getInk() != 4094 && pix->getInk() != 4095)) + if (fillInks && (pix->getInk() != GAP_CLOSE_TEMP && pix->getInk() != GAP_CLOSE_USED)) pix->setInk(color); - if (pix->getInk() == 4094) pix->setInk(4095); } } else for (y = r.y0; y <= r.y1; y++, pix += m_wrap - dx - 1) { for (x = r.x0; x <= r.x1; x++, pix++) { pix->setPaint(color); - if (fillInks && (pix->getInk() != 4094 && pix->getInk() != 4095)) + if (fillInks && (pix->getInk() != GAP_CLOSE_TEMP && pix->getInk() != GAP_CLOSE_USED)) pix->setInk(color); - if (pix->getInk() == 4094) pix->setInk(4095); } } @@ -455,7 +692,7 @@ void FullColorAreaFiller::rectFill(const TRect &rect, //============================================================================= // InkSegmenter -const int damInk = 4094; +const int damInk = 4094; //same value as the tempoary gap close lines? //----------------------------------------------------------------------------- From dc046e027cfc9dfb02f104644ab67b5dfcedbbf1 Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:32:18 -0400 Subject: [PATCH 7/8] Final for 1151 Fixed line fill code. Removed debugging statements. --- toonz/sources/tnztools/filltool.cpp | 55 ++----------------- toonz/sources/toonzlib/fill.cpp | 41 -------------- toonz/sources/toonzlib/fillutil.cpp | 83 ++--------------------------- 3 files changed, 8 insertions(+), 171 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 4ea16ff3..9682e63f 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -603,16 +603,6 @@ public: else filler.strokeFill(m_s, m_paintId, m_onlyUnfilled, m_colorType != LINES, m_colorType != AREAS, m_fillArea); - - TSystem::outputDebug("filltool.redo() final check, m_fillGaps is:" + std::to_string(m_fillGaps)); - // final check - - // ToDo - call finishGapLines instead of this code - //void finishGapLines(TRasterCM32P & rin, TRect & rect, const TRasterCM32P & rbefore, - // const TRasterCM32P & combined, TPalette * plt, - // int clickedColorStyle, int fillIndex, int closeColorStyle, - // bool closeGaps) { - if (m_fillGaps) { @@ -630,24 +620,6 @@ public: TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); - //for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { - // for (int tempX = 0; tempX < tempRaster->getLx(); - // tempX++, tempPix++, keepPix++) { - // keepPix->setPaint(tempPix->getPaint()); - // if (tempPix->getInk() != styleIndex) { - // if (m_colorType == AREAS && m_closeGaps && - // tempPix->getInk() == GAP_CLOSE_USED) { - // keepPix->setInk(m_closeStyleIndex); - // keepPix->setTone(tempPix->getTone()); - // } else if (m_colorType != AREAS && tempPix->getInk() == GAP_CLOSE_USED) { - // keepPix->setInk(m_paintId); - // keepPix->setTone(tempPix->getTone()); - // } else if (tempPix->getInk() != GAP_CLOSE_USED) { - // keepPix->setInk(tempPix->getInk()); - // } - // } - // } - //} for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { @@ -1041,26 +1013,17 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, TTileSetCM32 *tileSet = new TTileSetCM32(ras->getSize()); tileSet->add(ras, rasterFillArea); - //std::cout << "\nfillAreaWithUndo ras:"; - //std::cout << ras->getSize(); - //outputPixels("ras", ras); - TRasterCM32P tempRaster; int styleIndex = GAP_CLOSE_TEMP; TToonzImageP tempTi = ti->clone(); tempRaster = tempTi->getRaster(); - //outputPixels("tempRaster before auto close", tempRaster); - if (fillGaps) { applyAutoclose(tempTi, AutocloseDistance, AutocloseAngle, AutocloseOpacity, GAP_CLOSE_TEMP, convert(rasterFillArea), stroke); - //std::cout << "\nfillAreaWithUndo after applyAutoclose, tempRaster size:"; - //std::cout << tempRaster->getSize(); - //outputPixels("tempRaster", tempRaster); } AreaFiller filler(tempRaster); @@ -1072,24 +1035,15 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, delete tileSet; return; } - //std::cout << "\nfillAreaWithUndo after calling AreaFiller.rectFill()"; - //std::cout << tempRaster->getSize(); - //outputPixels("tempRaster", tempRaster); } else { filler.strokeFill(stroke, cs, onlyUnfilled, colorType != LINES, colorType != AREAS, rasterFillArea); - //std::cout << "\nfillAreaWithUndo after calling AreaFiller.strokeFill()"; - //std::cout << tempRaster->getSize(); - //outputPixels("tempRaster", tempRaster); } TPixelCM32 *tempPix = tempRaster->pixels(); TPixelCM32 *keepPix = ras->pixels(); - TSystem::outputDebug( - "filltool.fillAreaWithUndo() final check, fillGaps is:" + - std::to_string(fillGaps) + "\n"); finishGapLines(tempRaster, rasterFillArea, ras, ras, ti->getPalette(), 0, cs, closeStyleIndex, closeGaps); @@ -1109,9 +1063,6 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, } } - TSystem::outputDebug("filltool.fillAreaWithUndo() final check complete.\n"); - //outputPixels("ras", ras); - TPalette *plt = ti->getPalette(); // !autopaintLines will temporary disable autopaint line feature @@ -1248,7 +1199,7 @@ void doFill(const TImageP &img, const TPointD &pos, FillParameters ¶ms, if (tileSaver.getTileSet()->getTileCount() != 0) { static int count = 0; - TSystem::outputDebug("FILL" + std::to_string(count++) + "\n"); + TSystem::outputDebug("FILL" + std::to_string(count++)); if (offs != TPoint()) for (int i = 0; i < tileSet->getTileCount(); i++) { TTileSet::Tile *t = tileSet->editTile(i); @@ -2657,8 +2608,8 @@ void FillTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { invalidate(); return; } - TSystem::outputDebug("ok. pix=" + std::to_string(pix.getTone()) + "," + - std::to_string(pix.getPaint()) + "\n"); + //TSystem::outputDebug("ok. pix=" + std::to_string(pix.getTone()) + "," + + // std::to_string(pix.getPaint())); } else return; int closeStyleIndex = m_closeStyleIndex.getStyleIndex(); diff --git a/toonz/sources/toonzlib/fill.cpp b/toonz/sources/toonzlib/fill.cpp index 99c50329..bbdc2257 100644 --- a/toonz/sources/toonzlib/fill.cpp +++ b/toonz/sources/toonzlib/fill.cpp @@ -527,9 +527,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, tempRaster = r; } - //TSystem::outputDebug("fill.cpp::fill() tempRaster just after TAutocloser(), fillGaps:" + std::to_string(fillGaps) + "\n"); - //outputPixels("tempRaster", tempRaster); // issue 1151 - /*-- getBounds returns the entire image --*/ TRect bbbox = tempRaster->getBounds(); @@ -581,9 +578,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, cr = convertRaster2CM(refRaster); refCMRaster = cr->clone(); - //outputPixels("refCMRaster", refCMRaster); - //outputPixels("cr", cr); - refGapsClosed = TAutocloser(refCMRaster, autoCloseDistance, AutocloseAngle, styleIndex, AutocloseOpacity) .exec(); @@ -591,7 +585,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, if (!gapsClosed) tempRaster = r->clone(); // Transfer the gap segments to the refRaster - TSystem::outputDebug("fill.cpp::fill() Transfer the gap segments to the refRaster, refGapsClosed:" + std::to_string(refGapsClosed) +", gapsClosed:" + std::to_string(gapsClosed)); TPixelCM32 *tempPix = tempRaster->pixels(0); TPixelCM32 *refCMPix = refCMRaster->pixels(0); TPixel32 *refPix = refRaster->pixels(0); @@ -601,7 +594,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, if (refCMPix->getInk() != styleIndex) continue; *refPix = color; if (fillGaps) { - TSystem::outputDebug("y:" + std::to_string(refCMY) + "," + "x:" + std::to_string(refCMX) + "," + std::to_string(refCMPix->getInk()) + ":" + std::to_string(refCMPix->getPaint()) + ":" + std::to_string(refCMPix->getTone()) + "\n"); tempPix->setInk(refCMPix->getInk()); tempPix->setTone(refCMPix->getTone()); } @@ -613,7 +605,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, if (fillGaps && !gapsClosed && !refGapsClosed) { fillGaps = false; - TSystem::outputDebug("fill.cpp::fill(), refGapsClosed:" + std::to_string(refGapsClosed) + ", gapsClosed:" + std::to_string(gapsClosed) + ", set fillGaps to:" + std::to_string(fillGaps)); } assert(fillDepth >= 0 && fillDepth < 16); @@ -661,10 +652,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, seeds.push(FillSeed(xa, xb, y, 1)); seeds.push(FillSeed(xa, xb, y, -1)); - //std::cout << "\nfill.fill().outputPixels() tempRaster about to process close gaps for first seed, fillGaps is:"; - //std::cout << fillGaps; - //outputPixels("tempRaster",tempRaster); // issue 1151 - while (!seeds.empty()) { FillSeed fs = seeds.top(); seeds.pop(); @@ -758,8 +745,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } if (fillGaps) { - TSystem::outputDebug("fill.cpp::fill() final check, fillGaps is:" + std::to_string(fillGaps)); - //outputPixels("tempRaster", tempRaster); // issue 1151 finishGapLines(tempRaster, bbbox, r, refCMRaster, params.m_palette, paintAtClickedPos, paint, closeStyleIndex, closeGaps); TPixelCM32 *tempPix, *tempPixRestart; tempPixRestart = tempPix = tempRaster->pixels(); @@ -781,9 +766,6 @@ bool fill(const TRasterCM32P &r, const FillParameters ¶ms, } } - TSystem::outputDebug("fill.cpp:fill final check finished----\n"); - //outputPixels("r", r); // issue 1151 - return saveBoxChanged; } @@ -1193,31 +1175,8 @@ void fullColorFill(const TRaster32P &ras, const FillParameters ¶ms, } } - TSystem::outputDebug("fill::fullColorFill() final check, fillGaps is:" + std::to_string(fillGaps)); - //outputPixels("refCMRaster", refCMRaster); // issue 1151 - // final check for close gap pixels if (fillGaps) { - - // ToDo - Can this be adpated to call finishGapClosePixels instead of the logic below? - // This logic doesn't use the palette color styles it uses RGB pixel values - //void finishGapLines(TRasterCM32P& rin, TRect& rect, const TRasterCM32P& rbefore, - // const TRasterCM32P& combined, TPalette* plt, - // int clickedColorStyle, int fillIndex, int closeColorStyle, - // bool closeGaps) { - - //finishGapLines( - // refCMRaster, - // bbbox, - // cr, - // refCMRaster, - // params.m_palette, - // clickedPosColor, - // fillIndex, - // closeStyleIndex, - // closeGaps - //); - TPixelCM32 *tempPix = refCMRaster->pixels(); TPixel32 *keepPix = ras->pixels(); diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index 11b3847f..9bd77d29 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -100,9 +100,7 @@ void restoreColors(const TRasterCM32P &r, params.m_prevailing = false; for (UINT i = 0; i < seeds.size(); i++) { params.m_p = seeds[i].first; - //params.m_styleId = seeds[i].second; - //params.m_styleId = 0; - params.m_styleId = IGNORECOLORSTYLE; //set to ignore in final check + params.m_styleId = seeds[i].second; fill(r, params); } } @@ -168,23 +166,9 @@ void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined, int paintStyle = 0; int toneValue = 0; - TSystem::outputDebug( - "fillutil.finishGapLine(), closeGaps:" + std::to_string(closeGaps) + - ", clickedColorStyle:" + std::to_string(clickedColorStyle) + - ", fillColorStyle:" + std::to_string(fillColorStyle) + - ", closeColorStyle:" + std::to_string(closeColorStyle)); - TSystem::outputDebug("point is p.y:" + std::to_string(p.y) + - ", p.x:" + std::to_string(p.x)); - - TSystem::outputDebug("r->getBounds()), ly:" + std::to_string(r->getBounds().getLy()) + ", lx:" + std::to_string(r->getBounds().getLx())); - TSystem::outputDebug("insideRect, ly:" + std::to_string(insideRect->getLy()) + ", lx : " + std::to_string(insideRect->getLx())); - - TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x); - // outputPixels("r", r); - std::stack gapLinePixels; std::stack seeds; seeds.push(p); @@ -194,40 +178,18 @@ void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined, seeds.pop(); if (!r->getBounds().contains(p)) { - TSystem::outputDebug("fillutil.finishGapLine(), out of bounds at p.y:" + - std::to_string(p.y) + - ", p.x:" + std::to_string(p.x)); continue; } if (insideRect && !insideRect->contains(p)) { - TSystem::outputDebug("fillutil.finishGapLine(), insideRect && !insideRect->contains(p) at p.y:" + - std::to_string(p.y) + - ", p.x:" + std::to_string(p.x)); continue; } TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); TPixelCM32 *pixc = combinedPixels + (p.y * myCombined->getWrap() + p.x); - TSystem::outputDebug("--------------------- checking pixel at: p.y:" - + std::to_string(p.y) - + ", p.x:" + std::to_string(p.x) - + ", ink:" + std::to_string(pix->getInk()) - + ", paint:" + std::to_string(pix->getPaint()) - + ", tone:" + std::to_string(pix->getTone()) - + ", pixc " - + ", ink:" + std::to_string(pixc->getInk()) - + ", paint:" + std::to_string(pixc->getPaint()) - + ", tone:" + std::to_string(pixc->getTone())); - - // handle gap close pixel if (pix->getInk() == GAP_CLOSE_USED) continue; if (pix->getInk() == GAP_CLOSE_TEMP) { - TSystem::outputDebug("Gap Close pixel at p.y:" + - std::to_string(p.y) + - ", p.x:" + std::to_string(p.x)); - pix->setInk(GAP_CLOSE_USED); // push to the gapLinePixels collection for later processing as a line gapLinePixels.push(p); @@ -246,57 +208,37 @@ void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined, // a neighboring filled pixel if (pix->getTone() > 0 && pix->getPaint() == fillColorStyle) { filledNeighbor++; - TSystem::outputDebug(" Filled neighbor at p.y:" + std::to_string(p.y) + - ", p.x:" + std::to_string(p.x) + " "); continue; } // a neighboring fillable but unfilled pixel - if ((pix->getTone() == 255 && ((pix->getPaint() == clickedColorStyle) || - (pix->getPaint() == 0) || (pix->getPaint() == IGNORECOLORSTYLE))) && + if ((pix->getTone() == 255 && + ((pix->getPaint() == clickedColorStyle) || (pix->getPaint() == 0) || + (pix->getPaint() == IGNORECOLORSTYLE))) && (pixc->getTone() == 255 && ((pixc->getPaint() == clickedColorStyle) || - (pixc->getPaint() == 0)))) { + (pixc->getPaint() == 0)))) { unfilledNeighbor++; - TSystem::outputDebug(" Unfilled neighbor at p.y:" + std::to_string(p.y) + - ", p.x:" + std::to_string(p.x) + " "); continue; } } - TSystem::outputDebug("fillutil.finishGapLine(), filledNeighbor:" + - std::to_string(filledNeighbor) + ", unfilledNeighbor:" + - std::to_string(unfilledNeighbor)); - // determine the final disposition of the gap line if (filledNeighbor > 0) { if (unfilledNeighbor > 0) { - TSystem::outputDebug( - "fillutil.finishGapLine(), a needed line so let's finish it."); if (closeGaps) { - TSystem::outputDebug("fillutil.finishGapLine(), finish as ink."); inkStyle = closeColorStyle; paintStyle = fillColorStyle; toneValue = 0; } else { - TSystem::outputDebug("fillutil.finishGapLine(), finish as paint."); inkStyle = 0; paintStyle = fillColorStyle; toneValue = 255; } } else { - // surrounded by filled pixels, not a needed line, fill with fill color - TSystem::outputDebug( - "fillutil.finishGapLine(), No unfilled pixel neighbors, so fill with " - "fill color."); inkStyle = 0; paintStyle = fillColorStyle; toneValue = 255; } } else { - // not a needed line, restore original pixels - // set to IGNORECOLORSTYLE to resolve in final check - TSystem::outputDebug( - "fillutil.finishGapLine(), not a needed line, set ink to a value to " - "ignore later."); inkStyle = IGNORECOLORSTYLE; paintStyle = 0; toneValue = 0; @@ -307,13 +249,6 @@ void finishGapLine(const TRasterCM32P &r, const TRasterCM32P &combined, p = gapLinePixels.top(); gapLinePixels.pop(); - // do I need these checks since these points are already valid? - if (!r->getBounds().contains(p)) continue; - if (insideRect && !insideRect->contains(p)) continue; - - TSystem::outputDebug("finishing point p.y:" + std::to_string(p.y) + - ", p.x:" + std::to_string(p.x)); - TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x); pix->setInk(inkStyle); @@ -346,14 +281,6 @@ void finishGapLines(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore, int tone = pix->getTone(); int ink = pix->getInk(); - /* Pseudocode: - * Start the finish line procedure at the current pixel if: - * The ink colorstyle is TEMP_GAP_CLOSE - * The paint colorstyle of at least one neighboring pixel: - * is the same as the fill colorstyle - * has changed from its prior version - */ - if (ink == GAP_CLOSE_TEMP && ( // north From 313f5e0eb4c965a55e1691b69916c14ff8706bf8 Mon Sep 17 00:00:00 2001 From: Tom <44948041+TomDoingArt@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:00:11 -0400 Subject: [PATCH 8/8] Fix for restoreColors() restoreColors() needed a fix to not clear the paint of unclosed shapes. --- toonz/sources/tnztools/filltool.cpp | 12 +++++------- toonz/sources/toonzlib/fillutil.cpp | 5 +++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/toonz/sources/tnztools/filltool.cpp b/toonz/sources/tnztools/filltool.cpp index 9682e63f..05243503 100644 --- a/toonz/sources/tnztools/filltool.cpp +++ b/toonz/sources/tnztools/filltool.cpp @@ -1051,15 +1051,13 @@ void fillAreaWithUndo(const TImageP &img, const TRectD &area, TStroke *stroke, for (int tempY = 0; tempY < tempRaster->getLy(); tempY++) { for (int tempX = 0; tempX < tempRaster->getLx(); tempX++, tempPix++, keepPix++) { - if (tempPix->getInk() >= IGNORECOLORSTYLE || - tempPix->getPaint() >= IGNORECOLORSTYLE) { - continue; - } else { - // Handle all other pixels + if (tempPix->getInk() < IGNORECOLORSTYLE) { keepPix->setInk(tempPix->getInk()); - keepPix->setPaint(tempPix->getPaint()); - keepPix->setTone(tempPix->getTone()); } + if (tempPix->getPaint() < IGNORECOLORSTYLE) { + keepPix->setPaint(tempPix->getPaint()); + } + keepPix->setTone(tempPix->getTone()); } } diff --git a/toonz/sources/toonzlib/fillutil.cpp b/toonz/sources/toonzlib/fillutil.cpp index 9bd77d29..2010a6ed 100644 --- a/toonz/sources/toonzlib/fillutil.cpp +++ b/toonz/sources/toonzlib/fillutil.cpp @@ -99,8 +99,9 @@ void restoreColors(const TRasterCM32P &r, // in order to make the paint to protrude behind the line params.m_prevailing = false; for (UINT i = 0; i < seeds.size(); i++) { - params.m_p = seeds[i].first; - params.m_styleId = seeds[i].second; + params.m_p = seeds[i].first; + // params.m_styleId = seeds[i].second; + params.m_styleId = IGNORECOLORSTYLE; fill(r, params); } }