diff --git a/toonz/sources/common/trop/toperators.cpp b/toonz/sources/common/trop/toperators.cpp index 23c1053b..2d73c8d0 100644 --- a/toonz/sources/common/trop/toperators.cpp +++ b/toonz/sources/common/trop/toperators.cpp @@ -1547,7 +1547,7 @@ void TRop::depremultiply(const TRasterP &ras) { upPix = upRow; endPix = upPix + ras32->getLx(); while (upPix < endPix) { - depremult(*upPix); + if (upPix->m != 0) depremult(*upPix); ++upPix; } upRow += ras32->getWrap(); @@ -1563,7 +1563,7 @@ void TRop::depremultiply(const TRasterP &ras) { upPix = upRow; endPix = upPix + ras64->getLx(); while (upPix < endPix) { - depremult(*upPix); + if (upPix->m != 0) depremult(*upPix); ++upPix; } upRow += ras64->getWrap(); @@ -1578,6 +1578,68 @@ void TRop::depremultiply(const TRasterP &ras) { //----------------------------------------------------------------------------- +void TRop::expandColor(const TRaster32P &ras32, bool precise) { + struct locals { + static void copyRGB(TPixel32 *dst, TPixel32 *src) { + dst->r = src->r; + dst->g = src->g; + dst->b = src->b; + } + }; // locals + ras32->lock(); + TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); + TPixel32 *lastPix = + upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); + int currentRow = 0; + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras32->getLx(); + while (upPix < endPix) { + if (upPix->m == 0) { + // search 4-neighbor pixels + // left + if (upPix != upRow && (upPix - 1)->m != 0) + locals::copyRGB(upPix, upPix - 1); + // right + else if (upPix != endPix - 1 && (upPix + 1)->m != 0) + locals::copyRGB(upPix, upPix + 1); + // up + else if (currentRow != 0 && (upPix - ras32->getWrap())->m != 0) + locals::copyRGB(upPix, upPix - ras32->getWrap()); + // down + else if (currentRow != ras32->getLy() - 1 && + (upPix + ras32->getWrap())->m != 0) + locals::copyRGB(upPix, upPix + ras32->getWrap()); + // search 8-neighbor pixels + else if (precise) { + // upper left + if (currentRow != 0 && upPix != upRow && + (upPix - ras32->getWrap() - 1)->m != 0) + locals::copyRGB(upPix, upPix - ras32->getWrap() - 1); + // upper right + else if (currentRow != 0 && upPix != endPix - 1 && + (upPix - ras32->getWrap() + 1)->m != 0) + locals::copyRGB(upPix, upPix - ras32->getWrap() + 1); + // lower left + else if (currentRow != ras32->getLy() - 1 && upPix != upRow && + (upPix + ras32->getWrap() - 1)->m != 0) + locals::copyRGB(upPix, upPix + ras32->getWrap() - 1); + // lower right + else if (currentRow != ras32->getLy() - 1 && upPix != endPix - 1 && + (upPix + ras32->getWrap() + 1)->m != 0) + locals::copyRGB(upPix, upPix + ras32->getWrap() + 1); + } + } + ++upPix; + } + upRow += ras32->getWrap(); + currentRow++; + } + ras32->unlock(); +} + +//----------------------------------------------------------------------------- + void TRop::whiteTransp(const TRasterP &ras) { ras->lock(); TRaster32P ras32 = ras; diff --git a/toonz/sources/include/trop.h b/toonz/sources/include/trop.h index e9dc7a72..29851476 100644 --- a/toonz/sources/include/trop.h +++ b/toonz/sources/include/trop.h @@ -291,6 +291,14 @@ DVAPI void premultiply(const TRasterP &ras); //! Make a depremultiply of all raster pixels DVAPI void depremultiply(const TRasterP &ras); +// called from meshtexturizer in order to remove unwanted black contour +// appears at the border of the plastic-deformed texture. +// this function will "expand" color channels of the border pixels to +// neighbor full-transparent pixels. +// by doing this the linear interpolation at the border pixels will not +// decay color info and can get ideal antialiased result +DVAPI void expandColor(const TRaster32P &ras32, bool precise); + //! all white pixels are set to transparent DVAPI void whiteTransp(const TRasterP &ras); diff --git a/toonz/sources/tnzext/meshtexturizer.cpp b/toonz/sources/tnzext/meshtexturizer.cpp index 799bdedc..5a32c421 100644 --- a/toonz/sources/tnzext/meshtexturizer.cpp +++ b/toonz/sources/tnzext/meshtexturizer.cpp @@ -15,6 +15,8 @@ #include "tcg/tcg_list.h" #include "tcg/tcg_misc.h" +#include "trop.h" + #define COPIED_BORDER 1 // Amount of tile border from the original image #define TRANSP_BORDER 1 // Amount of transparent tile border #define NONPREM_BORDER \ @@ -127,6 +129,7 @@ GLuint MeshTexturizer::Imp::textureAlloc(const TRaster32P &ras, clearMatte(ras, ras->getLx() - border1, border1, ras->getLx() - border0, ras->getLy() - border1); } + }; // locals // Prepare the texture tile @@ -146,9 +149,11 @@ GLuint MeshTexturizer::Imp::textureAlloc(const TRaster32P &ras, tex->clear(); aux->extract(auxRect)->copy(ras->extract(rasRect)); - if (!premultiplied && NONPREM_BORDER > 0) - locals::clearMatte_border(aux, TRANSP_BORDER - NONPREM_BORDER, + if (!premultiplied && NONPREM_BORDER > 0) { + locals::clearMatte_border(tex, TRANSP_BORDER - NONPREM_BORDER, TRANSP_BORDER); + TRop::expandColor(tex, true); // precise is always true for now + } // Pass the raster into VRAM GLuint texId; diff --git a/toonz/sources/toonzlib/textureutils.cpp b/toonz/sources/toonzlib/textureutils.cpp index ca66ca5f..756742cb 100644 --- a/toonz/sources/toonzlib/textureutils.cpp +++ b/toonz/sources/toonzlib/textureutils.cpp @@ -100,7 +100,7 @@ TRasterImageP getTexture(const TXshSimpleLevel *sl, const TFrameId &fid, TRasterImageP ri(ImageManager::instance()->getImage( id, ImageManager::dontPutInCache, &extData)); - return ri; + return convert32(ri); } } // namespace