| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| namespace { |
| |
| const int BackgroundStyle = 0; |
| |
| |
| |
| TRect rasterizeStroke(TOfflineGL *&gl, const TRect &rasBounds, TStroke *stroke, |
| TPalette *palette, const TRectD &clip, bool doAntialias) { |
| TRectD bbox = clip * stroke->getBBox(); |
| TRect rect = convert(bbox).enlarge(1) * rasBounds; |
| |
| if (rect.getLx() <= 0 || rect.getLy() <= 0) return TRect(); |
| |
| gl = new TOfflineGL(rect.getSize()); |
| gl->makeCurrent(); |
| gl->clear(TPixel32::White); |
| |
| TPaletteP plt = palette->clone(); |
| int styleId = stroke->getStyle(); |
| TColorStyleP style = plt->getStyle(styleId); |
| assert(style); |
| style->setMainColor(TPixel32::Black); |
| |
| TTranslation affine(-convert(rect.getP00())); |
| TVectorRenderData rd(affine, gl->getBounds(), plt.getPointer(), 0, false, |
| doAntialias); |
| tglDraw(rd, stroke); |
| |
| glFinish(); |
| |
| return rect; |
| } |
| |
| |
| |
| TRect rasterizeStroke(TOfflineGL *&gl, TRect rasBounds, TStroke *stroke, |
| TRectD clip, bool filled = false) { |
| TDimension d = rasBounds.getSize(); |
| |
| TPointD offset(d.lx * 0.5, d.ly * 0.5); |
| TTranslation offsetMatrix(offset); |
| |
| TRectD strokeBBox = stroke->getBBox().enlarge(2); |
| if (!clip.isEmpty()) |
| strokeBBox = offsetMatrix * (strokeBBox * clip); |
| else |
| strokeBBox = offsetMatrix * strokeBBox; |
| |
| TRect rect = ToonzImageUtils::convertWorldToRaster(strokeBBox, 0) * rasBounds; |
| if (!rect.isEmpty()) { |
| gl = new TOfflineGL(rect.getSize()); |
| gl->makeCurrent(); |
| glClearColor(1, 1, 1, 1); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| TPalette *palette = new TPalette(); |
| TTranslation affine(-strokeBBox.getP00() + offset); |
| TVectorRenderData rd(affine, gl->getBounds(), palette, 0, false, true); |
| |
| int oldStyle = stroke->getStyle(); |
| stroke->setStyle(1); |
| |
| if (filled) { |
| TVectorImage vi; |
| vi.addStroke(new TStroke(*stroke)); |
| vi.findRegions(); |
| vi.selectFill(vi.getBBox().enlarge(2), 0, 1, false, true, false); |
| tglDraw(rd, &vi); |
| } else |
| tglDraw(rd, stroke); |
| |
| delete palette; |
| stroke->setStyle(oldStyle); |
| glFinish(); |
| } |
| return rect; |
| } |
| |
| |
| |
| TRect rasterizeRegion(TOfflineGL *&gl, TRect rasBounds, TRegion *region, |
| TRectD clip) { |
| TRectD regionBBox = region->getBBox(); |
| if (!clip.isEmpty()) regionBBox = regionBBox * clip; |
| |
| TRect rect = convert(regionBBox) * rasBounds; |
| if (!rect.isEmpty()) { |
| gl = new TOfflineGL(rect.getSize()); |
| gl->makeCurrent(); |
| gl->clear(TPixel32::White); |
| glPushAttrib(GL_ALL_ATTRIB_BITS); |
| glEnable(GL_ALPHA_TEST); |
| glAlphaFunc(GL_GREATER, 0); |
| |
| TPalette *palette = new TPalette(); |
| TTranslation affine(-convert(rect.getP00())); |
| TVectorRenderData rd(affine, gl->getBounds(), palette, 0, true, true); |
| |
| int oldStyle = region->getStyle(); |
| region->setStyle(1); |
| tglDraw(rd, region); |
| |
| glDisable(GL_ALPHA_TEST); |
| glPopAttrib(); |
| |
| region->setStyle(oldStyle); |
| glFinish(); |
| delete palette; |
| } |
| return rect; |
| } |
| |
| |
| |
| void fastAddPaintRegion(const TToonzImageP &ti, TRegion *region, int newPaintId, |
| int maxStyleId, TRectD clip = TRectD()) { |
| TRasterCM32P ras = ti->getRaster(); |
| TOfflineGL *gl; |
| TRect rect = rasterizeRegion(gl, ras->getBounds(), region, clip); |
| if (rect.isEmpty()) return; |
| |
| TRaster32P glRas = gl->getRaster(); |
| assert(TPixelCM32::getMaxTone() == 255); |
| ras->lock(); |
| glRas->lock(); |
| |
| for (int y = rect.y0; y <= rect.y1; y++) { |
| TPixel32 *inPix = glRas->pixels(y - rect.y0); |
| TPixelCM32 *outPix = ras->pixels(y) + rect.x0; |
| TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1; |
| for (; inPix < inEndPix; ++outPix, ++inPix) |
| if (inPix->r < 128) { |
| outPix->setPaint(newPaintId); |
| outPix->setTone(255); |
| } |
| } |
| |
| ras->unlock(); |
| glRas->unlock(); |
| |
| delete gl; |
| |
| TRegion *subregion; |
| UINT i = 0; |
| for (; i < region->getSubregionCount(); ++i) { |
| subregion = region->getSubregion(i); |
| fastAddPaintRegion(ti, subregion, |
| std::min(maxStyleId, subregion->getStyle()), maxStyleId); |
| } |
| } |
| } |
| |
| |
| |
| TRect ToonzImageUtils::convertWorldToRaster(const TRectD area, |
| const TToonzImageP ti) { |
| if (area.isEmpty()) return TRect(); |
| if (!ti || !ti->getRaster()) |
| return TRect(tfloor(area.x0), tfloor(area.y0), tfloor(area.x1) - 1, |
| tfloor(area.y1) - 1); |
| TRasterCM32P ras = ti->getRaster(); |
| TRectD rect(area + ras->getCenterD()); |
| return TRect(tfloor(rect.x0), tfloor(rect.y0), tceil(rect.x1) - 1, |
| tceil(rect.y1) - 1); |
| } |
| |
| |
| |
| TRectD ToonzImageUtils::convertRasterToWorld(const TRect area, |
| const TToonzImageP ti) { |
| if (area.isEmpty()) return TRectD(); |
| |
| TRectD rect(area.x0, area.y0, area.x1 + 1, area.y1 + 1); |
| if (ti && ti->getRaster()) rect = rect - ti->getRaster()->getCenterD(); |
| return rect; |
| } |
| |
| |
| |
| |
| |
| |
| |
| static TRect fastAddInkStroke(const TToonzImageP &ti, TStroke *stroke, |
| int inkId, bool selective, bool filled, |
| TRectD clip, bool doAntialiasing = true, |
| const set<int> &blendInks = set<int>()) { |
| TRasterCM32P ras = ti->getRaster(); |
| TOfflineGL *gl = 0; |
| |
| TRect rectRender = rasterizeStroke(gl, ras->getBounds(), stroke, |
| ti->getPalette(), clip, doAntialiasing); |
| if (!gl) return TRect(); |
| |
| TRaster32P glRas = gl->getRaster(); |
| TRasterCM32P outRas = ras->extract(rectRender); |
| assert(glRas->getSize() == outRas->getSize()); |
| |
| assert(TPixelCM32::getMaxTone() == 255); |
| outRas->lock(); |
| glRas->lock(); |
| bool isBlendInkUp = (blendInks.find(inkId) != blendInks.end()); |
| for (int y = 0; y < outRas->getLy(); ++y) { |
| TPixel32 *inPix = glRas->pixels(y); |
| TPixelCM32 *outPix = outRas->pixels(y); |
| for (int x = 0; x < outRas->getLx(); ++outPix, ++inPix, ++x) { |
| int upTone = inPix->r; |
| int dnTone = outPix->getTone(); |
| |
| if (doAntialiasing) { |
| |
| |
| bool isBlendInkDn = |
| (blendInks.find(outPix->getInk()) != blendInks.end()); |
| |
| if (isBlendInkUp && !isBlendInkDn && dnTone < 255) continue; |
| |
| if (isBlendInkDn && !isBlendInkUp && upTone < 255) { |
| *outPix = TPixelCM32(inkId, outPix->getPaint(), upTone); |
| continue; |
| } |
| |
| |
| |
| |
| |
| if ((upTone <= dnTone) && |
| ((outPix->getInk() == inkId) || (upTone != 255)) && |
| (!selective || !outPix->isPureInk())) |
| *outPix = TPixelCM32(inkId, outPix->getPaint(), upTone); |
| } else { |
| if (!selective || !outPix->isPureInk()) { |
| |
| if (upTone == 0) *outPix = TPixelCM32(inkId, outPix->getPaint(), 0); |
| } |
| } |
| } |
| } |
| outRas->unlock(); |
| glRas->unlock(); |
| delete gl; |
| |
| return rectRender; |
| } |
| |
| |
| TRect ToonzImageUtils::addInkStroke(const TToonzImageP &ti, TStroke *stroke, |
| int inkId, bool selective, bool filled, |
| TRectD clip, bool doAntialiasing) { |
| TStroke *s = new TStroke(*stroke); |
| TPoint tiCenter = ti->getRaster()->getCenter(); |
| s->transform(TTranslation(tiCenter.x, tiCenter.y)); |
| TRect rect = |
| fastAddInkStroke(ti, s, inkId, selective, filled, clip, doAntialiasing); |
| rect -= tiCenter; |
| return rect; |
| } |
| |
| |
| |
| TRect ToonzImageUtils::changeColorStroke( |
| const TToonzImageP &ti, const ChangeColorStrokeSettings &settings) { |
| if (!settings.changeInk && !settings.changePaint) return TRect(); |
| |
| TRasterCM32P ras = ti->getRaster(); |
| TOfflineGL *gl; |
| TRect rect = |
| rasterizeStroke(gl, ras->getBounds(), settings.stroke, settings.clip); |
| if (rect.isEmpty()) { |
| return rect; |
| } |
| TRaster32P glRas = gl->getRaster(); |
| ras->lock(); |
| glRas->lock(); |
| |
| for (int y = rect.y0; y <= rect.y1; ++y) { |
| TPixel32 *inPix = glRas->pixels(y - rect.y0); |
| TPixelCM32 *outPix = ras->pixels(y) + rect.x0; |
| TPixel32 *inEndPix = inPix + rect.x1 - rect.x0 + 1; |
| for (; inPix < inEndPix; ++outPix, ++inPix) { |
| if (inPix->r < 128 && settings.changeInk && !outPix->isPurePaint()) |
| outPix->setInk(settings.colorId); |
| if (inPix->r < 128 && settings.changePaint && |
| (settings.maskPaintId == -1 || |
| outPix->getPaint() == settings.maskPaintId)) |
| outPix->setPaint(settings.colorId); |
| } |
| } |
| delete gl; |
| ras->unlock(); |
| glRas->unlock(); |
| return rect; |
| } |
| |
| |
| |
| TRect ToonzImageUtils::eraseRect(const TToonzImageP &ti, const TRectD &area, |
| int maskId, bool onInk, bool onPaint) { |
| assert(onInk || onPaint); |
| TRasterCM32P ras = ti->getRaster(); |
| TRect rect = convertWorldToRaster(area, ti) * ras->getBounds(); |
| if (rect.isEmpty()) return rect; |
| ras->lock(); |
| |
| for (int y = rect.y0; y <= rect.y1; y++) { |
| TPixelCM32 *pix = ras->pixels(y) + rect.x0; |
| TPixelCM32 *endPix = ras->pixels(y) + rect.x1 + 1; |
| for (; pix < endPix; ++pix) { |
| if (onPaint && (maskId == -1 || maskId == pix->getPaint())) |
| pix->setPaint(BackgroundStyle); |
| |
| if (onInk && (maskId == -1 || maskId == pix->getInk())) |
| *pix = TPixelCM32(BackgroundStyle, pix->getPaint(), |
| TPixelCM32::getMaxTone()); |
| } |
| } |
| ras->unlock(); |
| return rect; |
| } |
| |
| |
| |
| std::vector<TRect> ToonzImageUtils::paste(const TToonzImageP &ti, |
| const TTileSetCM32 *tileSet) { |
| std::vector<TRect> rects; |
| TRasterCM32P raster = ti->getRaster(); |
| |
| for (int i = tileSet->getTileCount() - 1; i >= 0; i--) { |
| const TTileSetCM32::Tile *tile = tileSet->getTile(i); |
| TRasterCM32P rasCM32; |
| tile->getRaster(rasCM32); |
| assert(!!rasCM32); |
| raster->copy(rasCM32, tile->m_rasterBounds.getP00()); |
| rects.push_back(tile->m_rasterBounds); |
| } |
| return rects; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TToonzImageP ToonzImageUtils::vectorToToonzImage( |
| const TVectorImageP &vimage, const TAffine &aff, TPalette *palette, |
| const TPointD &outputPos, const TDimension &outputSize, |
| const std::vector<TRasterFxRenderDataP> *fxs, bool transformThickness) { |
| if (!vimage || !palette) return 0; |
| |
| |
| TVectorImageP vi = vimage->clone(); |
| vi->transform(aff, transformThickness); |
| |
| |
| TRasterCM32P raster(outputSize.lx, outputSize.ly); |
| raster->clear(); |
| TToonzImageP ti(raster, raster->getBounds()); |
| ti->setPalette(palette->clone()); |
| |
| |
| vi->transform(TTranslation(-outputPos)); |
| |
| int strokeCount = vi->getStrokeCount(); |
| std::vector<int> strokeIndex(strokeCount); |
| std::vector<TStroke *> strokes(strokeCount); |
| int maxStyleId = palette->getStyleCount() - 1; |
| |
| int i; |
| for (i = 0; i < strokeCount; ++i) { |
| strokeIndex[i] = i; |
| strokes[i] = vi->getStroke(i); |
| } |
| vi->notifyChangedStrokes(strokeIndex, strokes); |
| int regionCount = vi->getRegionCount(); |
| |
| |
| TRectD clip(TDimensionD(outputSize.lx, outputSize.ly)); |
| |
| set<int> colors; |
| if (fxs) { |
| for (i = 0; i < (int)fxs->size(); i++) { |
| SandorFxRenderData *sandorData = |
| dynamic_cast<SandorFxRenderData *>((*fxs)[i].getPointer()); |
| if (sandorData && sandorData->m_type == BlendTz) { |
| std::string indexes = |
| ::to_string(sandorData->m_blendParams.m_colorIndex); |
| std::vector<std::string> items; |
| parseIndexes(indexes, items); |
| PaletteFilterFxRenderData paletteFilterData; |
| insertIndexes(items, &paletteFilterData); |
| colors.insert(paletteFilterData.m_colors.begin(), |
| paletteFilterData.m_colors.end()); |
| } |
| } |
| } |
| |
| int k, l; |
| for (i = 0; i < strokeCount;) { |
| |
| for (k = 0; k < regionCount; ++k) |
| if (vi->areDifferentGroup(i, false, k, true) == -1) { |
| TRegion *region = vi->getRegion(k); |
| fastAddPaintRegion(ti, region, std::min(maxStyleId, region->getStyle()), |
| maxStyleId); |
| } |
| |
| |
| for (k = i; |
| k < strokeCount && vi->areDifferentGroup(i, false, k, false) == -1; |
| ++k) |
| ; |
| |
| |
| for (l = i; l < k; ++l) { |
| TStroke *stroke = vi->getStroke(l); |
| |
| bool visible = false; |
| int styleId = stroke->getStyle(); |
| TColorStyleP style = palette->getStyle(styleId); |
| assert(style); |
| int colorCount = style->getColorParamCount(); |
| if (colorCount == 0) |
| visible = true; |
| else { |
| visible = false; |
| for (int j = 0; j < style->getColorParamCount() && !visible; j++) { |
| TPixel32 color = style->getColorParamValue(j); |
| if (color.m != 0) visible = true; |
| } |
| } |
| if (visible) |
| fastAddInkStroke(ti, stroke, std::min(maxStyleId, stroke->getStyle()), |
| false, false, clip, true, colors); |
| } |
| i = k; |
| } |
| |
| return ti; |
| } |
| |
| |
| |
| TPalette *ToonzImageUtils::loadTzPalette(const TFilePath &pltFile) { |
| TImageP pltImg; |
| TImageReader loader(pltFile); |
| pltImg = loader.load(); |
| |
| TRasterImageP pltRasImg(pltImg); |
| if (!pltRasImg) return 0; |
| |
| TRaster32P rasPlt = pltRasImg->getRaster(); |
| if (!rasPlt) return 0; |
| |
| std::map<int, std::pair<std::string, std::string>> pltColorNames; |
| std::map<int, std::pair<std::string, std::string>>::iterator it; |
| loader.getTzpPaletteColorNames(pltColorNames); |
| |
| TPalette *palette = new TPalette(); |
| |
| const int offset = 0; |
| |
| assert(rasPlt->getLy() == 2); |
| rasPlt->lock(); |
| TPixel32 *pixelRow = rasPlt->pixels(0); |
| int x = 0; |
| int count = palette->getStyleCount(); |
| |
| for (; x < rasPlt->getLx(); ++x) { |
| TSolidColorStyle *style = new TSolidColorStyle(pixelRow[x]); |
| if ((it = pltColorNames.find(x)) != pltColorNames.end()) { |
| std::string styleName = it->second.second; |
| style->setName(::to_wstring(styleName)); |
| } |
| if (x < count) palette->setStyle(x, style); |
| |
| else |
| palette->addStyle(style); |
| } |
| |
| |
| |
| TPalette::Page *page = palette->getPage(0); |
| |
| |
| page->removeStyle(1); |
| |
| std::map<std::wstring, int> pages; |
| std::map<std::wstring, int>::iterator itpage; |
| |
| pixelRow = rasPlt->pixels(1); |
| for (x = 0; x < rasPlt->getLx(); ++x) { |
| if ((it = pltColorNames.find(x)) != pltColorNames.end()) { |
| std::wstring pageName; |
| pageName = ::to_wstring(it->second.first); |
| if (x == 0) { |
| page = palette->getPage(0); |
| page->setName(pageName); |
| pages[pageName] = 0; |
| } else if ((itpage = pages.find(pageName)) != pages.end()) |
| page = palette->getPage(itpage->second); |
| else { |
| page = palette->addPage(pageName); |
| pages[pageName] = page->getIndex(); |
| } |
| } else |
| page = palette->getPage(0); |
| |
| if (pixelRow[x].r == 255) page->addStyle(offset + x); |
| } |
| rasPlt->unlock(); |
| |
| return palette; |
| } |
| |
| |
| |
| void ToonzImageUtils::getUsedStyles(std::set<int> &styles, |
| const TToonzImageP &ti) { |
| TRasterCM32P ras = ti->getRaster(); |
| if (!ras) return; |
| int lx = ras->getLx(); |
| int ly = ras->getLy(); |
| ras->lock(); |
| for (int y = 0; y < ly; y++) { |
| TPixelCM32 *pix = ras->pixels(y); |
| TPixelCM32 *endPix = pix + lx; |
| while (pix < endPix) { |
| styles.insert(pix->getInk()); |
| styles.insert(pix->getPaint()); |
| ++pix; |
| } |
| } |
| ras->unlock(); |
| } |
| |
| void ToonzImageUtils::scrambleStyles(const TToonzImageP &ti, |
| std::map<int, int> styleTable) { |
| TRasterCM32P ras = ti->getRaster(); |
| if (!ras) return; |
| if (styleTable.empty()) return; |
| std::map<int, int>::iterator it; |
| std::vector<int> lut(4096, -1); |
| bool isIdentity = true; |
| for (it = styleTable.begin(); it != styleTable.end(); ++it) { |
| int j = it->first, k = it->second; |
| assert(j >= 0); |
| assert(j < 1000000); |
| if (j >= (int)lut.size()) lut.resize(j + 1, -1); |
| lut[j] = k; |
| if (j != k) isIdentity = false; |
| } |
| if (isIdentity) return; |
| |
| int m = lut.size(); |
| int lx = ras->getLx(); |
| int ly = ras->getLy(); |
| ras->lock(); |
| for (int y = 0; y < ly; y++) { |
| TPixelCM32 *pix = ras->pixels(y); |
| TPixelCM32 *endPix = pix + lx; |
| while (pix < endPix) { |
| int ink = pix->getInk(); |
| if (0 <= ink && ink < m && lut[ink] >= 0) ink = lut[ink]; |
| int paint = pix->getPaint(); |
| if (0 <= paint && paint < m && lut[paint] >= 0) paint = lut[paint]; |
| if (ink != pix->getInk() || paint != pix->getPaint()) { |
| *pix = TPixelCM32(ink, paint, pix->getTone()); |
| } |
| ++pix; |
| } |
| } |
| ras->unlock(); |
| } |
| |
| |
| |
| |
| |
| bool ToonzImageUtils::convertToTlv(const TFilePath &levelPathIn) { |
| try { |
| TFilePath levelPathOut = levelPathIn.getParentDir() + |
| TFilePath(levelPathIn.getWideName() + L".tlv"); |
| |
| TLevelReaderP lr(levelPathIn); |
| TLevelP level = lr->loadInfo(); |
| |
| TLevelWriterP lw(levelPathOut, 0); |
| |
| TPalette *plt = new TPalette(); |
| |
| TLevel::Iterator it = level->begin(); |
| TLevel::Iterator end = level->end(); |
| for (; it != level->end(); ++it) { |
| try { |
| TImageReaderP ir = lr->getFrameReader(it->first); |
| TRasterImageP img = ir->load(); |
| double dpix, dpiy; |
| img->getDpi(dpix, dpiy); |
| TRasterCM32P raster(convert(img->getBBox()).getSize()); |
| |
| TRop::convert(raster, img->getRaster()); |
| |
| TImageWriterP iw = lw->getFrameWriter(it->first); |
| TToonzImageP outimg(raster, raster->getBounds()); |
| outimg->setDpi(dpix, dpiy); |
| outimg->setPalette(plt); |
| iw->save(outimg); |
| |
| } catch (...) { |
| return false; |
| |
| |
| |
| } |
| } |
| |
| TFilePath pltPath = lw->getFilePath().withNoFrame().withType("tpl"); |
| if (TSystem::touchParentDir(pltPath)) { |
| if (TSystem::doesExistFileOrLevel(pltPath)) |
| TSystem::removeFileOrLevel(pltPath); |
| TOStream os(pltPath); |
| os << plt; |
| } |
| |
| lr = TLevelReaderP(); |
| lw = TLevelWriterP(); |
| |
| |
| return true; |
| } catch (...) { |
| return false; |
| } |
| } |
| |
| |
| |
| |
| |
| void ToonzImageUtils::eraseImage(const TToonzImageP &ti, |
| const TRaster32P &image, const TPoint &pos, |
| bool invert, bool eraseInk, bool erasePaint, |
| bool selective, int styleId) { |
| TRect rasBounds = ti->getRaster()->getBounds(); |
| TRect imageBounds = image->getBounds() + pos; |
| |
| if (invert) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TRect rect; |
| |
| if (rasBounds.y0 != imageBounds.y0) { |
| rect = TRect(imageBounds.x0, rasBounds.y0, rasBounds.x1, imageBounds.y0); |
| ToonzImageUtils::eraseRect( |
| ti, ToonzImageUtils::convertRasterToWorld(rect, ti), |
| selective ? styleId : -1, eraseInk, erasePaint); |
| } |
| |
| if (imageBounds.x1 != rasBounds.x1) { |
| rect = TRect(imageBounds.x1, imageBounds.y0, rasBounds.x1, rasBounds.y1); |
| ToonzImageUtils::eraseRect( |
| ti, ToonzImageUtils::convertRasterToWorld(rect, ti), |
| selective ? styleId : -1, eraseInk, erasePaint); |
| } |
| |
| if (imageBounds.y1 != rasBounds.y1) { |
| rect = TRect(rasBounds.x0, imageBounds.y1, imageBounds.x1, rasBounds.y1); |
| ToonzImageUtils::eraseRect( |
| ti, ToonzImageUtils::convertRasterToWorld(rect, ti), |
| selective ? styleId : -1, eraseInk, erasePaint); |
| } |
| |
| if (rasBounds.x0 != imageBounds.x0) { |
| rect = TRect(rasBounds.x0, rasBounds.y0, imageBounds.x0, imageBounds.y1); |
| ToonzImageUtils::eraseRect( |
| ti, ToonzImageUtils::convertRasterToWorld(rect, ti), |
| selective ? styleId : -1, eraseInk, erasePaint); |
| } |
| } |
| |
| TRasterCM32P workRas = ti->getRaster()->extract(imageBounds); |
| |
| int y; |
| for (y = 0; y < workRas->getLy(); y++) { |
| TPixelCM32 *outPix = workRas->pixels(y); |
| TPixelCM32 *outEndPix = outPix + workRas->getLx(); |
| TPixel32 *inPix = image->pixels(y); |
| for (; outPix != outEndPix; outPix++, inPix++) { |
| bool canEraseInk = |
| !selective || (selective && styleId == outPix->getInk()); |
| bool canErasePaint = |
| !selective || (selective && styleId == outPix->getPaint()); |
| |
| int paint, tone; |
| if (!invert) { |
| paint = inPix->m > 0 && erasePaint && canErasePaint |
| ? 0 |
| : outPix->getPaint(); |
| tone = inPix->m > 0 && eraseInk && canEraseInk |
| ? std::max(outPix->getTone(), (int)inPix->m) |
| : outPix->getTone(); |
| } else { |
| paint = inPix->m < 255 && erasePaint && canErasePaint |
| ? 0 |
| : outPix->getPaint(); |
| tone = inPix->m < 255 && eraseInk && canEraseInk |
| ? std::max(outPix->getTone(), 255 - (int)inPix->m) |
| : outPix->getTone(); |
| } |
| *outPix = TPixelCM32(outPix->getInk(), paint, tone); |
| } |
| } |
| } |
| |
| |
| |
| std::string ToonzImageUtils::premultiply(const TFilePath &levelPath) { |
| assert(0); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return ""; |
| } |
| |