void stroke_autofill_learn(const TVectorImageP &imgToLearn, TStroke *stroke) { if (!imgToLearn || !stroke || stroke->getControlPointCount() == 0) return; TVectorImage appImg; TStroke *appStroke = new TStroke(*stroke); appImg.addStroke(appStroke); appImg.findRegions(); double pbx, pby; double totalArea = 0; pbx = pby = 0; if (!regionsReference.isEmpty()) regionsReference.clear(); int i, j, index = 0; for (i = 0; i < (int)imgToLearn->getRegionCount(); i++) { TRegion *currentRegion = imgToLearn->getRegion(i); for (j = 0; j < (int)appImg.getRegionCount(); j++) { TRegion *region = appImg.getRegion(j); if (contains(region, currentRegion)) { scanRegion(currentRegion, index, regionsReference, region->getBBox()); index++; int k, subRegionCount = currentRegion->getSubregionCount(); for (k = 0; k < subRegionCount; k++) { TRegion *subRegion = currentRegion->getSubregion(k); if (contains(region, subRegion)) scanSubRegion(subRegion, index, regionsReference, region->getBBox()); } } } } QMap<int, Region>::Iterator it; for (it = regionsReference.begin(); it != regionsReference.end(); it++) { pbx += it.value().m_barycentre.x; pby += it.value().m_barycentre.y; totalArea += it.value().m_area; } if (totalArea > 0) referenceB = TPointD(pbx / totalArea, pby / totalArea); else referenceB = TPointD(0.0, 0.0); }
void rect_autofill_learn(const TVectorImageP &imgToLearn, const TRectD &rect) { if (rect.getLx() * rect.getLy() < MIN_SIZE) return; double pbx, pby; double totalArea = 0; pbx = pby = 0; if (!regionsReference.isEmpty()) regionsReference.clear(); int i, index = 0, regionCount = imgToLearn->getRegionCount(); for (i = 0; i < regionCount; i++) { TRegion *region = imgToLearn->getRegion(i); if (rect.contains(region->getBBox())) { scanRegion(region, index, regionsReference, rect); index++; } int j, subRegionCount = region->getSubregionCount(); for (j = 0; j < subRegionCount; j++) { TRegion *subRegion = region->getSubregion(j); if (rect.contains(subRegion->getBBox())) scanSubRegion(subRegion, index, regionsReference, rect); } } QMap<int, Region>::Iterator it; for (it = regionsReference.begin(); it != regionsReference.end(); it++) { pbx += it.value().m_barycentre.x; pby += it.value().m_barycentre.y; totalArea += it.value().m_area; } if (totalArea > 0) referenceB = TPointD(pbx / totalArea, pby / totalArea); else referenceB = TPointD(0.0, 0.0); }
//!Converts a TVectorImage into a TRasterImage. The input vector image //!is transformed through the passed affine \b aff, and put into a //!TRasterImage strictly covering the bounding box of the transformed //!vector image. The output image has its lower-left position in the //!world reference specified by the \b pos parameter, which is granted to //!be an integer displacement of the passed value. Additional parameters //!include an integer \b enlarge by which the output image is enlarged with //!respect to the transformed image's bbox, and the bool \b transformThickness //!to specify whether the transformation should involve strokes' thickensses //!or not. TRasterImageP TRasterImageUtils::vectorToFullColorImage( 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; //Transform the vector image through aff TVectorImageP vi = vimage->clone(); vi->transform(aff, transformThickness); //Allocate the output ToonzImage TRaster32P raster(outputSize.lx, outputSize.ly); raster->clear(); TRasterImageP ri(raster); ri->setPalette(palette->clone()); //Shift outputPos to the origin vi->transform(TTranslation(-outputPos)); int strokeCount = vi->getStrokeCount(); std::vector<int> strokeIndex(strokeCount); std::vector<TStroke *> strokes(strokeCount); int i; for (i = 0; i < strokeCount; ++i) { strokeIndex[i] = i; strokes[i] = vi->getStroke(i); } vi->notifyChangedStrokes(strokeIndex, strokes); int maxStyleId = palette->getStyleCount() - 1; for (i = 0; i < (int)vi->getRegionCount(); ++i) { TRegion *region = vi->getRegion(i); fastAddPaintRegion(ri, region, tmin(maxStyleId, region->getStyle()), maxStyleId); } 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 = toString(sandorData->m_blendParams.m_colorIndex); std::vector<std::string> items; parseIndexes(indexes, items); PaletteFilterFxRenderData paletteFilterData; insertIndexes(items, &paletteFilterData); colors = paletteFilterData.m_colors; break; } } } for (i = 0; i < strokeCount; ++i) { TStroke *stroke = vi->getStroke(i); 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(ri, stroke, TRectD(), 1, true); } return ri; }
void VectorBrushProp::draw(const TVectorRenderData &rd) { //Ensure that the stroke overlaps our clipping rect if (rd.m_clippingRect != TRect() && !rd.m_is3dView && !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) return; TPaletteP palette(m_brush->getPalette()); if (!palette) return; static TOutlineUtil::OutlineParameter param; //unused, but requested //Build a solid color style to draw each m_vi's stroke with. TSolidColorStyle colorStyle; //Push the specified rd affine before drawing glPushMatrix(); tglMultMatrix(rd.m_aff); //1. If necessary, build the outlines double currentPixelSize = sqrt(tglGetPixelSize2()); bool differentPixelSize = !isAlmostZero(currentPixelSize - m_pixelSize, 1e-5); m_pixelSize = currentPixelSize; int i, viRegionsCount = m_brush->getRegionCount(), viStrokesCount = m_brush->getStrokeCount(); if (differentPixelSize || m_strokeChanged) { m_strokeChanged = false; //1a. First, the regions m_regionOutlines.resize(viRegionsCount); for (i = 0; i < viRegionsCount; ++i) { TRegionOutline &outline = m_regionOutlines[i]; const TRegion *brushRegion = m_brush->getRegion(i); //Build the outline outline.clear(); TOutlineUtil::makeOutline(*getStroke(), *brushRegion, m_brushBox, outline); } //1b. Then, the strokes m_strokeOutlines.resize(viStrokesCount); for (i = 0; i < viStrokesCount; ++i) { TStrokeOutline &outline = m_strokeOutlines[i]; const TStroke *brushStroke = m_brush->getStroke(i); outline.getArray().clear(); TOutlineUtil::makeOutline(*getStroke(), *brushStroke, m_brushBox, outline, param); } } //2. Draw the outlines UINT s, t, r, strokesCount = m_brush->getStrokeCount(), regionCount = m_brush->getRegionCount(); for (s = 0; s < strokesCount; s = t) //Each cycle draws a group { //A vector image stores group strokes with consecutive indices. //2a. First, draw regions in the strokeIdx-th stroke's group for (r = 0; r < regionCount; ++r) { if (m_brush->sameGroupStrokeAndRegion(s, r)) { const TRegion *brushRegion = m_brush->getRegion(r); const TColorStyle *brushStyle = palette->getStyle(brushRegion->getStyle()); assert(brushStyle); //Draw the outline colorStyle.setMainColor(brushStyle->getMainColor()); colorStyle.drawRegion(0, false, m_regionOutlines[r]); } } //2b. Then, draw all strokes in strokeIdx-th stroke's group for (t = s; t < strokesCount && m_brush->sameGroup(s, t); ++t) { const TStroke *brushStroke = m_brush->getStroke(t); const TColorStyle *brushStyle = palette->getStyle(brushStroke->getStyle()); if (!brushStyle) continue; colorStyle.setMainColor(brushStyle->getMainColor()); colorStyle.drawStroke(0, &m_strokeOutlines[t], brushStroke); //brushStroke unused but requested } } glPopMatrix(); }
bool stroke_autofill_apply(const TVectorImageP &imgToApply, TStroke *stroke, bool selective) { if (!imgToApply || !stroke || stroke->getControlPointCount() == 0) return false; TVectorImage appImg; TStroke *appStroke = new TStroke(*stroke); appImg.addStroke(appStroke); appImg.findRegions(); if (regionsReference.size() <= 0) return false; double pbx, pby; double totalArea = 0; pbx = pby = 0.0; if (!regionsWork.isEmpty()) regionsWork.clear(); int i, j, index = 0; for (i = 0; i < (int)imgToApply->getRegionCount(); i++) { TRegion *currentRegion = imgToApply->getRegion(i); for (j = 0; j < (int)appImg.getRegionCount(); j++) { TRegion *region = appImg.getRegion(j); if (contains(region, currentRegion)) { scanRegion(currentRegion, index, regionsWork, region->getBBox()); index++; int k, subRegionCount = currentRegion->getSubregionCount(); for (k = 0; k < subRegionCount; k++) { TRegion *subRegion = currentRegion->getSubregion(k); if (contains(region, subRegion)) scanSubRegion(subRegion, index, regionsWork, region->getBBox()); } } } } if (regionsWork.size() <= 0) return false; QMap<int, Region>::Iterator it; for (it = regionsWork.begin(); it != regionsWork.end(); it++) { pbx += it.value().m_barycentre.x; pby += it.value().m_barycentre.y; totalArea += it.value().m_area; } workB = TPointD(pbx / totalArea, pby / totalArea); std::vector<MatchingProbs> probVector; RegionDataList::Iterator refIt, workIt; for (refIt = regionsReference.begin(); refIt != regionsReference.end(); refIt++) for (workIt = regionsWork.begin(); workIt != regionsWork.end(); workIt++) assignProbs(probVector, refIt.value(), workIt.value(), refIt.key(), workIt.key()); bool filledRegions = false; for (refIt = regionsReference.begin(); refIt != regionsReference.end(); refIt++) { int to = 0, from = 0; int valore = 0; do valore = match(probVector, from, to); while ((regionsWork[to].m_match != -1 || regionsReference[from].m_match != -1) && valore > 0); if (valore > AMB_TRESH) { regionsWork[to].m_match = from; regionsReference[from].m_match = to; regionsWork[to].m_styleId = regionsReference[from].m_styleId; TRegion *reg = regionsWork[to].m_region; if (reg && (!selective || selective && reg->getStyle() == 0)) { reg->setStyle(regionsWork[to].m_styleId); filledRegions = true; } } } return filledRegions; }
bool rect_autofill_apply(const TVectorImageP &imgToApply, const TRectD &rect, bool selective) { if (rect.getLx() * rect.getLy() < MIN_SIZE) return false; if (regionsReference.size() <= 0) return false; double pbx, pby; double totalArea = 0; pbx = pby = 0.0; if (!regionsWork.isEmpty()) regionsWork.clear(); int i, index = 0, regionCount = imgToApply->getRegionCount(); for (i = 0; i < regionCount; i++) { TRegion *region = imgToApply->getRegion(i); TRectD bbox = region->getBBox(); if (rect.contains(bbox)) { scanRegion(region, index, regionsWork, rect); index++; } int j, subRegionCount = region->getSubregionCount(); for (j = 0; j < subRegionCount; j++) { TRegion *subRegion = region->getSubregion(j); if (rect.contains(subRegion->getBBox())) scanSubRegion(subRegion, index, regionsWork, rect); } } if (regionsWork.size() <= 0) return false; QMap<int, Region>::Iterator it; for (it = regionsWork.begin(); it != regionsWork.end(); it++) { pbx += it.value().m_barycentre.x; pby += it.value().m_barycentre.y; totalArea += it.value().m_area; } workB = TPointD(pbx / totalArea, pby / totalArea); std::vector<MatchingProbs> probVector; RegionDataList::Iterator refIt, workIt; for (refIt = regionsReference.begin(); refIt != regionsReference.end(); refIt++) for (workIt = regionsWork.begin(); workIt != regionsWork.end(); workIt++) assignProbs(probVector, refIt.value(), workIt.value(), refIt.key(), workIt.key()); bool filledRegions = false; for (refIt = regionsReference.begin(); refIt != regionsReference.end(); refIt++) { int to = 0, from = 0; int valore = 0; do valore = match(probVector, from, to); while ((regionsWork[to].m_match != -1 || regionsReference[from].m_match != -1) && valore > 0); if (valore > AMB_TRESH) { regionsWork[to].m_match = from; regionsReference[from].m_match = to; regionsWork[to].m_styleId = regionsReference[from].m_styleId; TRegion *reg = regionsWork[to].m_region; if (reg && (!selective || selective && reg->getStyle() == 0)) { reg->setStyle(regionsWork[to].m_styleId); filledRegions = true; } } } return filledRegions; }