TVectorImageP Naa2TlvConverter::vectorize(const TToonzImageP &ti) { CenterlineConfiguration conf; if (!ti) return TVectorImageP(); TPalette *palette = ti->getPalette(); VectorizerCore vc; TAffine dpiAff; double factor = Stage::inch; double dpix = factor / 72, dpiy = factor / 72; ti->getDpi(dpix, dpiy); TPointD center = ti->getRaster()->getCenterD(); if (dpix != 0.0 && dpiy != 0.0) dpiAff = TScale(factor / dpix, factor / dpiy); factor = norm(dpiAff * TPointD(1, 0)); conf.m_affine = dpiAff * TTranslation(-center); conf.m_thickScale = factor; conf.m_leaveUnpainted = false; conf.m_makeFrame = true; conf.m_penalty = 0.0; conf.m_despeckling = 0; TImageP img(ti.getPointer()); TVectorImageP vi = vc.vectorize(img, conf, palette); vi->setPalette(palette); return vi; }
StrokesData *FullColorImageData::toStrokesData(ToonzScene *scene) const { assert(scene); TRectD rect; if (!m_rects.empty()) rect = m_rects[0]; else if (!m_strokes.empty()) rect = m_strokes[0].getBBox(); unsigned int i; for (i = 0; i < m_rects.size(); i++) rect += m_rects[i]; for (i = 0; i < m_strokes.size(); i++) rect += m_strokes[i].getBBox(); TRasterImageP image(m_copiedRaster); image->setPalette(FullColorPalette::instance()->getPalette(scene)); image->setDpi(m_dpiX, m_dpiY); const VectorizerParameters *vParams = scene->getProperties()->getVectorizerParameters(); assert(vParams); std::auto_ptr<VectorizerConfiguration> config(vParams->getCurrentConfiguration(0.0)); TVectorImageP vi = vectorize(image, rect, *config, m_transformation); StrokesData *sd = new StrokesData(); std::set<int> indexes; for (i = 0; i < vi->getStrokeCount(); i++) indexes.insert(i); sd->setImage(vi, indexes); return sd; }
void SceneViewerContextMenu::exitVectorImageGroup() { TVectorImageP vi = (TVectorImageP)TTool::getImage(false); // getCurrentImage(); if (!vi) return; vi->exitGroup(); m_viewer->update(); }
StrokesData *ToonzImageData::toStrokesData(ToonzScene *scene) const { assert(scene); TRectD rect; if (!m_rects.empty()) rect = m_rects[0]; else if (!m_strokes.empty()) rect = m_strokes[0].getBBox(); unsigned int i; for (i = 0; i < m_rects.size(); i++) rect += m_rects[i]; for (i = 0; i < m_strokes.size(); i++) rect += m_strokes[i].getBBox(); TToonzImageP image(m_copiedRaster, m_copiedRaster->getBounds()); image->setPalette(m_palette.getPointer()); image->setDpi(m_dpiX, m_dpiY); const VectorizerParameters &vParams = *scene->getProperties()->getVectorizerParameters(); CenterlineConfiguration cConf = vParams.getCenterlineConfiguration(0.0); NewOutlineConfiguration oConf = vParams.getOutlineConfiguration(0.0); const VectorizerConfiguration &config = vParams.m_isOutline ? static_cast<const VectorizerConfiguration &>(oConf) : static_cast<const VectorizerConfiguration &>(cConf); TVectorImageP vi = vectorize(image, rect, config, m_transformation); StrokesData *sd = new StrokesData(); std::set<int> indexes; for (i = 0; i < vi->getStrokeCount(); i++) indexes.insert(i); sd->setImage(vi, indexes); return sd; }
void PlaneViewer::draw(TVectorImageP vi) { TRectD bbox(vi->getBBox()); TRect bboxI(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1) - 1, tceil(bbox.y1) - 1); TVectorRenderData rd(TAffine(), bboxI, vi->getPalette(), 0, true, true); tglDraw(rd, vi.getPointer()); }
void ImagePainter::paintImage(const TImageP &image, const TDimension &imageSize, const TDimension &viewerSize, const TAffine &aff, const VisualSettings &visualSettings, const CompareSettings &compareSettings, const TRect &loadbox) { glDisable(GL_DEPTH_TEST); if (visualSettings.m_drawExternalBG) { glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); } GLenum error = glGetError(); // assert(error==GL_NO_ERROR); if (error != GL_NO_ERROR) { printf("ImagePainter::paintImage() gl_error:%d\n", error); } if (!image) return; TRasterImageP rimg = (TRasterImageP)image; TVectorImageP vimg = (TVectorImageP)image; TToonzImageP timg = (TToonzImageP)image; TRect clipRect(viewerSize); clipRect -= TPoint(viewerSize.lx * 0.5, viewerSize.ly * 0.5); Painter painter(viewerSize, imageSize, aff, image->getPalette(), visualSettings); if (rimg) painter.onRasterImage(rimg.getPointer()); else if (vimg) painter.onVectorImage(vimg.getPointer()); else if (timg) painter.onToonzImage(timg.getPointer()); if (visualSettings.m_blankColor != TPixel::Transparent) { painter.drawBlank(); return; } // if I have a color filter applied using a glmask, , drawing of images must // be done on black bg! if (!vimg) painter.flushRasterImages( loadbox, visualSettings.m_doCompare ? compareSettings.m_compareX : DefaultCompareValue, visualSettings.m_doCompare ? compareSettings.m_compareY : DefaultCompareValue, compareSettings.m_swapCompared); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (visualSettings.m_doCompare) drawCompareLines(viewerSize, compareSettings.m_compareX, compareSettings.m_compareY); }
void multiApplyAutoclose(TFrameId firstFid, TFrameId lastFid, TRectD firstRect, TRectD lastRect, TStroke *firstStroke = 0, TStroke *lastStroke = 0) { bool backward = false; if (firstFid > lastFid) { tswap(firstFid, lastFid); backward = true; } assert(firstFid <= lastFid); std::vector<TFrameId> allFids; m_level->getFids(allFids); std::vector<TFrameId>::iterator i0 = allFids.begin(); while (i0 != allFids.end() && *i0 < firstFid) i0++; if (i0 == allFids.end()) return; std::vector<TFrameId>::iterator i1 = i0; while (i1 != allFids.end() && *i1 <= lastFid) i1++; assert(i0 < i1); std::vector<TFrameId> fids(i0, i1); int m = fids.size(); assert(m > 0); TVectorImageP firstImage; TVectorImageP lastImage; if ((m_closeType.getValue() == FREEHAND_CLOSE || m_closeType.getValue() == POLYLINE_CLOSE) && firstStroke && lastStroke) { TStroke *first = new TStroke(*firstStroke); TStroke *last = new TStroke(*lastStroke); firstImage = new TVectorImage(); lastImage = new TVectorImage(); firstImage->addStroke(first); lastImage->addStroke(last); } TUndoManager::manager()->beginBlock(); for (int i = 0; i < m; ++i) { TFrameId fid = fids[i]; TToonzImageP img = (TToonzImageP)m_level->getFrame(fid, true); if (!img) continue; double t = m > 1 ? (double)i / (double)(m - 1) : 0.5; if (m_closeType.getValue() == RECT_CLOSE) applyAutoclose(img, interpolateRect(firstRect, lastRect, t)); else if ((m_closeType.getValue() == FREEHAND_CLOSE || m_closeType.getValue() == POLYLINE_CLOSE) && firstStroke && lastStroke) doClose(t, img, firstImage, lastImage); m_level->getProperties()->setDirtyFlag(true); } TUndoManager::manager()->endBlock(); TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); // TNotifier::instance()->notify(TLevelChange()); // TNotifier::instance()->notify(TStageChange()); }
void updateLevel() { TTool::Application *app = TTool::getApplication(); if (!app->getCurrentLevel()->getLevel()) return; TXshSimpleLevelP xl = app->getCurrentLevel()->getLevel()->getSimpleLevel(); if (app->getCurrentFrame()->getFrameType() != TFrameHandle::LevelFrame) return; TFrameId fid = app->getCurrentFrame()->getFid(); TVectorImageP src = xl->getFrame(fid, true); int count = src->getStrokeCount(); for (int i = 1; i < 10; i++) { ++fid; if (!xl->isFid(fid)) { TVectorImageP vi = new TVectorImage(); xl->setFrame(fid, vi); } TVectorImageP vi = xl->getFrame(fid, true); TVectorImageP dst = src->clone(); deform(dst.getPointer(), src.getPointer(), (double)i / (double)9); count = dst->getStrokeCount(); vi->mergeImage(dst, TAffine()); app->getCurrentTool()->getTool()->notifyImageChanged(fid); } }
void SceneViewerContextMenu::enterVectorImageGroup() { if (m_groupIndexToBeEntered == -1) return; TVectorImageP vi = (TVectorImageP)TTool::getImage(false); // getCurrentImage(); if (!vi) return; vi->enterGroup(m_groupIndexToBeEntered); TSelection *selection = TSelection::getCurrent(); if (selection) selection->selectNone(); m_viewer->update(); }
TStroke *PinchTool::getClosestStroke(const TPointD &pos, double &w) const { TVectorImageP vi = TImageP(getImage(false)); if (!vi) return 0; double dist = 0; UINT index; if (vi->getNearestStroke(pos, w, index, dist, true)) return vi->getStroke(index); else return 0; }
TColorStyle *TVectorBrushStyle::clone() const { TVectorImageP brush; if (m_brush) { //Clone m_brush and its palette brush = m_brush->clone(); //NOTE: This does NOT clone the palette, too. brush->setPalette(m_brush->getPalette()->clone()); } TVectorBrushStyle *theClone = new TVectorBrushStyle(m_brushName, brush); theClone->assignNames(this); theClone->setFlags(getFlags()); return theClone; }
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); }
TVectorImageP MyInbetweener::tween(double t) { TVectorImageP vi = m_vi0->clone(); int n = tmin(m_vi0->getStrokeCount(), m_vi1->getStrokeCount()); for (int i = 0; i < n; i++) { TStroke *stroke0 = m_vi0->getStroke(i); TStroke *stroke1 = m_vi1->getStroke(i); TStroke *stroke = vi->getStroke(i); int m = tmin(stroke0->getControlPointCount(), stroke1->getControlPointCount()); for (int j = 0; j < m; j++) { TThickPoint p0 = stroke0->getControlPoint(j); TThickPoint p1 = stroke1->getControlPoint(j); TThickPoint p = (1 - t) * p0 + t * p1; stroke->setControlPoint(j, p); } /* for(int j=2;j+2<m;j+=2) { TThickPoint p0 = stroke0->getControlPoint(j-2); TThickPoint p1 = stroke0->getControlPoint(j-1); TThickPoint p2 = stroke0->getControlPoint(j); TThickPoint p3 = stroke0->getControlPoint(j+1); TThickPoint p4 = stroke0->getControlPoint(j+2); if(tdistance2(p0,p1)<0.001 && tdistance2(p3,p4)<0.001) { p2 = 0.5*(p1+p2); stroke->setControlPoint(j,p2); } } */ } return vi; }
void leftButtonDrag(const TPointD &p, const TMouseEvent &) { if (!m_active) return; // double dx = p.x - m_pointAtMouseDown.x; double pixelSize = getPixelSize(); if (tdistance2(p, m_oldPos) < 9.0 * pixelSize * pixelSize) return; m_oldPos = p; m_pointAtMouseDown = p; //double sc = exp(0.001 * (double)dx); TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; QMutexLocker lock(vi->getMutex()); TPointD offset = p - m_pointAtMove; /* if( tdistance2(m_pointAtMouseDown, p ) > sq(m_pointSize * 0.5) ) // reincremento { leftButtonUp(p); lefrightButtonDown(p); } */ UINT i, j; for (i = 0; i < m_strokeHit.size(); ++i) modifyControlPoints(*m_strokeHit[i], TStrokePointDeformation(offset, m_pointAtMouseDown, m_pointSize * 0.7)); for (i = 0; i < m_strokeToModify.size(); ++i) for (j = 0; j < m_strokeToModify[i].m_splittedToMove.size(); ++j) { TStroke *temp = m_strokeToModify[i].m_splittedToMove[j]; modifyControlPoints(*temp, TStrokePointDeformation(offset, m_pointAtMouseDown, m_pointSize * 0.7)); } m_pointAtMove = p; invalidate(); };
static TToonzImageP vectorToToonzRaster(const TVectorImageP &vi, const TDimension &size, const TAffine &aff, const TPointD &dpi) { /* TScale sc(dpi.x/Stage::inch, dpi.y/Stage::inch); TRectD bbox = sc*vi->getBBox(); bbox.x0 = tfloor(bbox.x0); bbox.y0 = tfloor(bbox.y0); bbox.x1 = tceil(bbox.x1); bbox.y1 = tceil(bbox.y1); TDimension size(bbox.getLx(), bbox.getLy()); */ TToonzImageP ti = ToonzImageUtils::vectorToToonzImage( vi, aff, vi->getPalette(), TPointD(0, 0), size, 0, true); ti->setPalette(vi->getPalette()); // e' necessario? return ti; }
void StrokeSelection::paste() { TTool *tool = TTool::getApplication()->getCurrentTool()->getTool(); if (!tool) return; if (TTool::getApplication()->getCurrentObject()->isSpline()) { const StrokesData *stData = dynamic_cast<const StrokesData *>( QApplication::clipboard()->mimeData()); if (!stData) return; TVectorImageP splineImg = tool->getImage(true); TVectorImageP img = stData->m_image; if (!splineImg || !img) return; QMutexLocker lock(splineImg->getMutex()); TUndo *undo = new ToolUtils::UndoPath( tool->getXsheet()->getStageObject(tool->getObjectId())->getSpline()); while (splineImg->getStrokeCount() > 0) splineImg->deleteStroke(0); TStroke *stroke = img->getStroke(0); splineImg->addStroke(new TStroke(*stroke), false); TUndoManager::manager()->add(undo); tool->notifyImageChanged(); tool->invalidate(); return; } TVectorImageP tarImg = tool->touchImage(); if (!tarImg) return; TPaletteP palette = tarImg->getPalette(); TPaletteP oldPalette = new TPalette(); if (palette) oldPalette = palette->clone(); bool isPaste = pasteStrokesWithoutUndo(tarImg, m_indexes, m_sceneHandle); if (isPaste) { TXshSimpleLevel *level = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); TUndoManager::manager()->add(new PasteStrokesUndo( level, tool->getCurrentFid(), m_indexes, oldPalette, m_sceneHandle)); m_updateSelectionBBox = isPaste; } tool->notifyImageChanged(); tool->getApplication() ->getPaletteController() ->getCurrentLevelPalette() ->notifyPaletteChanged(); m_updateSelectionBBox = false; tool->invalidate(); }
void SkeletonTool::drawLevelBoundingBox(int frame, int columnIndex) { TAffine affine = getCurrentColumnMatrix(); TXshCell cell = getXsheet()->getCell(frame, columnIndex); TImageP image = cell.getImage(false); TToonzImageP ti = image; TVectorImageP vi = image; glPushMatrix(); if (affine != getMatrix()) tglMultMatrix(getMatrix().inv() * affine); if (ti) { TPointD dpiScale = getViewer()->getDpiScale(); glScaled(dpiScale.x, dpiScale.y, 1); TRectD bbox = ToonzImageUtils::convertRasterToWorld(convert(ti->getBBox()), ti); ToolUtils::drawRect(bbox * ti->getSubsampling(), TPixel32(200, 200, 200), 0x5555); } if (vi) { TRectD bbox = vi->getBBox(); ToolUtils::drawRect(bbox, TPixel32(200, 200, 200), 0x5555); } glPopMatrix(); }
void SceneViewerContextMenu::addEnterGroupCommands(const TPointD &pos) { bool ret = true; TVectorImageP vi = (TVectorImageP)TTool::getImage(false); if (!vi) return; if (vi->isInsideGroup() > 0) { addAction(CommandManager::instance()->getAction(MI_ExitGroup)); } StrokeSelection *ss = dynamic_cast<StrokeSelection *>(TSelection::getCurrent()); if (!ss) return; for (int i = 0; i < vi->getStrokeCount(); i++) if (ss->isSelected(i) && vi->canEnterGroup(i)) { m_groupIndexToBeEntered = i; addAction(CommandManager::instance()->getAction(MI_EnterGroup)); return; } assert(ret); }
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); }
void SkeletonTool::getImageBoundingBox(TRectD &bbox, TAffine &aff, int frame, int columnIndex) { TAffine columnAff = getXsheet()->getPlacement(TStageObjectId::ColumnId(columnIndex), frame); // TAffine affine = getColumnMatrix(columnIndex); TXshCell cell = getXsheet()->getCell(frame, columnIndex); TImageP image = cell.getImage(false); TToonzImageP ti = image; TVectorImageP vi = image; if (ti) { TAffine imageDpiAff; if (cell.m_level->getSimpleLevel()) imageDpiAff = getDpiAffine(cell.m_level->getSimpleLevel(), cell.m_frameId, true); aff = columnAff * imageDpiAff; bbox = ToonzImageUtils::convertRasterToWorld(convert(ti->getBBox()), ti) * ti->getSubsampling(); ToolUtils::drawRect(bbox * ti->getSubsampling(), TPixel32(200, 200, 200), 0x5555); } else if (vi) { bbox = vi->getBBox(); aff = columnAff; } else { bbox = TRectD(); aff = TAffine(); } }
void doClose(double t, const TImageP &img, const TVectorImageP &firstImage, const TVectorImageP &lastImage) { if (t == 0) applyAutoclose(img, TRectD(), firstImage->getStroke(0)); else if (t == 1) applyAutoclose(img, TRectD(), lastImage->getStroke(0)); else { assert(firstImage->getStrokeCount() == 1); assert(lastImage->getStrokeCount() == 1); TVectorImageP vi = TInbetween(firstImage, lastImage).tween(t); assert(vi->getStrokeCount() == 1); applyAutoclose(img, TRectD(), vi->getStroke(0)); } }
void OutlineVectorizer::createOutlineStrokes() { m_vimage->enableRegionComputing(true, false); int j; for (j = 0; j < (int)m_nodes.size(); j++) { Node *node = m_nodes[j]; if (node->m_pixel == 0 || node->m_visited) continue; traceOutline(node); } #ifdef DEBUG for (j = 0; j < (int)m_nodes.size(); j++) { Node *node = m_nodes[j]; if (node->m_pixel == 0 || node->m_flag) continue; outputNodes(node); } #endif std::list<std::vector<TThickPoint>>::iterator it_outlines = m_protoOutlines.begin(); for (it_outlines; it_outlines != m_protoOutlines.end(); it_outlines++) { if (it_outlines->size() > 3) { std::vector<TThickPoint> points; std::vector<TThickPoint>::iterator it; if (it_outlines->size() > 10) { it = it_outlines->begin() + 1; for (;;) { //Baco: Ricontrolla l'if seguente - in alcuni casi va fuori bounds... if ((int)it_outlines->size() <= m_configuration.m_smoothness + 1) break; if (it >= it_outlines->end() - (m_configuration.m_smoothness + 1)) break; for (j = 0; j < m_configuration.m_smoothness; j++) it = it_outlines->erase(it); ++it; } } points.push_back(it_outlines->front()); it = it_outlines->begin(); TThickPoint old = *it; ++it; for (; it != it_outlines->end(); ++it) { TThickPoint point((1 / 2.0) * (*it + old)); points.push_back(point); old = *it; } points.push_back(it_outlines->back()); points.push_back(it_outlines->front()); TStroke *stroke = TStroke::interpolate(points, m_configuration.m_interpolationError); stroke->setStyle(m_configuration.m_strokeStyleId); stroke->setSelfLoop(); m_vimage->addStroke(stroke); } } }
//!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 leftButtonDown(const TPointD &pos, const TMouseEvent &e) { TPointD p(pos); m_oldPos = pos; m_pointAtMouseDown = p; m_startingPos = p; m_active = false; TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; QMutexLocker lock(vi->getMutex()); m_active = true; m_pointAtMove = m_pointAtMouseDown = p; m_strokeHit.clear(); m_changedStrokes.clear(); m_strokeToModify.clear(); std::vector<TStroke *> strokeUndo; TStroke *ref; m_hitStrokeCorners.clear(); m_strokeToModifyCorners.clear(); UINT i = 0; for (; i < vi->getStrokeCount(); ++i) { if (!vi->inCurrentGroup(i)) continue; TStroke *stroke = vi->getStroke(i); ref = stroke; // calcola le intersezioni std::vector<double> intersections; intersect(*ref, p, m_pointSize, intersections); if (intersections.empty()) { if (increaseControlPoints(*ref, TStrokePointDeformation(p, m_pointSize))) { m_changedStrokes.push_back(i); m_strokeHit.push_back(ref); std::vector<int> *corners = new std::vector<int>; corners->push_back(0); detectCorners(ref, 20, *corners); corners->push_back(ref->getChunkCount()); m_hitStrokeCorners.push_back(corners); ref->disableComputeOfCaches(); strokeUndo.push_back(ref); } } else { strokeUndo.push_back(ref); MagnetTool::strokeCollection sc; sc.m_parent = ref; splitStroke(*sc.m_parent, intersections, sc.m_splitted); selectStrokeToMove(sc.m_splitted, p, m_pointSize, sc.m_splittedToMove); for (UINT ii = 0; ii < sc.m_splittedToMove.size(); ++ii) { TStroke *temp = sc.m_splittedToMove[ii]; bool test = increaseControlPoints(*temp, TStrokePointDeformation(p, m_pointSize)); assert(test); std::vector<int> *corners = new std::vector<int>; corners->push_back(0); detectCorners(temp, 20, *corners); corners->push_back(temp->getChunkCount()); m_strokeToModifyCorners.push_back(corners); } m_strokeToModify.push_back(sc); m_changedStrokes.push_back(i); } } m_oldStrokesArray.resize(m_changedStrokes.size()); for (i = 0; i < m_changedStrokes.size(); i++) m_oldStrokesArray[i] = new TStroke(*(vi->getStroke(m_changedStrokes[i]))); if (!strokeUndo.empty()) { if (TTool::getApplication()->getCurrentObject()->isSpline()) m_undo = new UndoPath(getXsheet()->getStageObject(getObjectId())->getSpline()); else { TXshSimpleLevel *sl = TTool::getApplication()->getCurrentLevel()->getSimpleLevel(); assert(sl); TFrameId id = getCurrentFid(); m_undo = new UndoModifyListStroke(sl, id, strokeUndo); } } invalidate(); // vi->validateRegionEdges(ref, true); };
void leftButtonUp(const TPointD &, const TMouseEvent &) { if (!m_active) return; m_active = false; m_pointAtMouseDown = m_pointAtMove = TConsts::napd; TStroke *ref; TVectorImageP vi = TImageP(getImage(true)); if (!vi) return; QMutexLocker lock(vi->getMutex()); UINT i, j; for (i = 0; i < m_strokeHit.size(); ++i) { ref = m_strokeHit[i]; ref->enableComputeOfCaches(); ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_hitStrokeCorners[i])); // vi->validateRegionEdges(ref, false); } clearPointerContainer(m_hitStrokeCorners); m_hitStrokeCorners.clear(); UINT count = 0; for (i = 0; i < m_strokeToModify.size(); ++i) { // recupero la stroke collection MagnetTool::strokeCollection &sc = m_strokeToModify[i]; for (j = 0; j < sc.m_splittedToMove.size(); ++j) { ref = sc.m_splittedToMove[j]; ref->enableComputeOfCaches(); ref->reduceControlPoints(getPixelSize() * ReduceControlPointCorrection, *(m_strokeToModifyCorners[count++])); } // ricostruisco una stroke con quella data ref = merge(sc.m_splitted); if (sc.m_parent->isSelfLoop()) { int cpCount = ref->getControlPointCount(); TThickPoint p1 = ref->getControlPoint(0); TThickPoint p2 = ref->getControlPoint(cpCount - 1); TThickPoint midP = (p1 + p2) * 0.5; ref->setControlPoint(0, midP); ref->setControlPoint(cpCount - 1, midP); ref->setSelfLoop(true); } sc.m_parent->swapGeometry(*ref); delete ref; // elimino la curva temporanea clearPointerContainer(sc.m_splitted); // pulisco le stroke trovate con lo split sc.m_splittedToMove.clear(); // pulisco il contenitore ( le stroke // che erano contenute qua sono state // eliminate nella clearPointer.... } clearPointerContainer(m_strokeToModifyCorners); m_strokeToModifyCorners.clear(); for (i = 0; i < vi->getStrokeCount(); ++i) { ref = vi->getStroke(i); ref->invalidate(); } vi->notifyChangedStrokes(m_changedStrokes, m_oldStrokesArray); notifyImageChanged(); if (m_undo) TUndoManager::manager()->add(m_undo); m_undo = 0; clearPointerContainer(m_oldStrokesArray); m_oldStrokesArray.clear(); invalidate(); };
void MyInbetweener::stabilizeSegments(TVectorImageP &image) { for (int i = 0; i < image->getStrokeCount(); i++) stabilizeSegments(image->getStroke(i)); }
void TColorStyle::makeIcon(const TDimension &d) { checkErrorsByGL; TColorStyle *style = this->clone(); checkErrorsByGL; TPaletteP tmpPalette = new TPalette(); checkErrorsByGL; int id = tmpPalette->addStyle(style); checkErrorsByGL; int contextLx = pow(2.0, tceil(log((double)d.lx) / log(2.0))); int contextLy = pow(2.0, tceil(log((double)d.ly) / log(2.0))); TDimension dim(contextLx, contextLy); TOfflineGL *glContext = TOfflineGL::getStock(dim); checkErrorsByGL; glContext->clear(TPixel32::White); checkErrorsByGL; TVectorImageP img = new TVectorImage; checkErrorsByGL; img->setPalette(tmpPalette.getPointer()); checkErrorsByGL; std::vector<TThickPoint> points(3); if (isRegionStyle() && !isStrokeStyle()) { points[0] = TThickPoint(-55, -50, 1); points[1] = TThickPoint(0, -60, 1); points[2] = TThickPoint(55, -50, 1); TStroke *stroke1 = new TStroke(points); img->addStroke(stroke1); points[0] = TThickPoint(50, -55, 1); points[1] = TThickPoint(60, 0, 1); points[2] = TThickPoint(50, 55, 1); TStroke *stroke2 = new TStroke(points); img->addStroke(stroke2); points[0] = TThickPoint(55, 50, 1); points[1] = TThickPoint(0, 60, 1); points[2] = TThickPoint(-55, 50, 1); TStroke *stroke3 = new TStroke(points); img->addStroke(stroke3); points[0] = TThickPoint(-50, 55, 1); points[1] = TThickPoint(-60, 0, 1); points[2] = TThickPoint(-50, -55, 1); TStroke *stroke4 = new TStroke(points); img->addStroke(stroke4); img->fill(TPointD(0, 0), id); } else if (isStrokeStyle() && !isRegionStyle()) { double rasX05 = d.lx * 0.5; double rasY05 = d.ly * 0.5; points[0] = TThickPoint(-rasX05, -rasY05, 7); points[1] = TThickPoint(0, -rasY05, 9); points[2] = TThickPoint(rasX05, rasY05, 12); TStroke *stroke1 = new TStroke(points); stroke1->setStyle(id); img->addStroke(stroke1); points.clear(); } else if (!isRasterStyle()) { assert(isStrokeStyle() && isRegionStyle()); points[0] = TThickPoint(-60, -30, 0.5); points[1] = TThickPoint(0, -30, 0.5); points[2] = TThickPoint(60, -30, 0.5); TStroke *stroke1 = new TStroke(points); stroke1->setStyle(id); img->addStroke(stroke1); points[0] = TThickPoint(60, -30, 0.5); points[1] = TThickPoint(60, 0, 0.5); points[2] = TThickPoint(60, 30, 0.5); TStroke *stroke2 = new TStroke(points); stroke2->setStyle(id); img->addStroke(stroke2); points[0] = TThickPoint(60, 30, 0.5); points[1] = TThickPoint(0, 30, 0.5); points[2] = TThickPoint(-60, 30, 0.5); TStroke *stroke3 = new TStroke(points); stroke3->setStyle(id); img->addStroke(stroke3); points[0] = TThickPoint(-60, 30, 0.5); points[1] = TThickPoint(-60, 0, 0.5); points[2] = TThickPoint(-60, -30, 0.5); TStroke *stroke4 = new TStroke(points); stroke4->setStyle(id); img->addStroke(stroke4); img->fill(TPointD(0, 0), id); } TRectD bbox = img->getBBox(); checkErrorsByGL; bbox = bbox.enlarge(TDimensionD(-10, -10)); checkErrorsByGL; double scx = 0.9 * d.lx / bbox.getLx(); double scy = 0.9 * d.ly / bbox.getLy(); double sc = std::min(scx, scy); double dx = (d.lx - bbox.getLx() * sc) * 0.5; double dy = (d.ly - bbox.getLy() * sc) * 0.5; TAffine aff = TScale(scx, scy) * TTranslation(-bbox.getP00() + TPointD(dx, dy)); checkErrorsByGL; if (isRegionStyle() && !isStrokeStyle()) aff = aff * TTranslation(-10, -10); checkErrorsByGL; const TVectorRenderData rd(aff, TRect(), tmpPalette.getPointer(), 0, true); checkErrorsByGL; glContext->draw(img, rd); checkErrorsByGL; TRect rect(d); if (!m_icon || m_icon->getSize() != d) { checkErrorsByGL; m_icon = glContext->getRaster()->extract(rect)->clone(); } else { checkErrorsByGL; m_icon->copy(glContext->getRaster()->extract(rect)); } }
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(); }
void Iwa_TiledParticlesFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { std::vector<int> lastframe; std::vector<TLevelP> partLevel; TPointD p_offset; TDimension p_size(0, 0); /*- 参照画像ポートの取得 -*/ std::vector<TRasterFxPort *> part_ports; /*- テクスチャ素材画像のポート -*/ std::map<int, TRasterFxPort *> ctrl_ports; /*- コントロール画像のポート番号/ポート -*/ int portsCount = this->getInputPortCount(); for (int i = 0; i < portsCount; ++i) { std::string tmpName = this->getInputPortName(i); QString portName = QString::fromStdString(tmpName); if (portName.startsWith("T")) { TRasterFxPort *tmpPart = (TRasterFxPort *)this->getInputPort(tmpName); if (tmpPart->isConnected()) part_ports.push_back((TRasterFxPort *)this->getInputPort(tmpName)); } else { portName.replace(QString("Control"), QString("")); TRasterFxPort *tmpCtrl = (TRasterFxPort *)this->getInputPort(tmpName); if (tmpCtrl->isConnected()) ctrl_ports[portName.toInt()] = (TRasterFxPort *)this->getInputPort(tmpName); } } /*- テクスチャ素材のバウンディングボックスを足し合わせる ←この工程、いらないかも?-*/ if (!part_ports.empty()) { TRectD outTileBBox(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); TRectD bbox; for (unsigned int i = 0; i < (int)part_ports.size(); ++i) { const TFxTimeRegion &tr = (*part_ports[i])->getTimeRegion(); lastframe.push_back(tr.getLastFrame() + 1); partLevel.push_back(new TLevel()); partLevel[i]->setName((*part_ports[i])->getAlias(0, ri)); // The particles offset must be calculated without considering the affine's translational // component TRenderSettings riZero(ri); riZero.m_affine.a13 = riZero.m_affine.a23 = 0; // Calculate the bboxes union for (int t = 0; t <= tr.getLastFrame(); ++t) { TRectD inputBox; (*part_ports[i])->getBBox(t, inputBox, riZero); bbox += inputBox; } } if (bbox == TConsts::infiniteRectD) bbox *= outTileBBox; p_size.lx = (int)bbox.getLx() + 1; p_size.ly = (int)bbox.getLy() + 1; p_offset = TPointD(0.5 * (bbox.x0 + bbox.x1), 0.5 * (bbox.y0 + bbox.y1)); } else { partLevel.push_back(new TLevel()); partLevel[0]->setName("particles"); TDimension vecsize(10, 10); TOfflineGL *offlineGlContext = new TOfflineGL(vecsize); offlineGlContext->clear(TPixel32(0, 0, 0, 0)); TStroke *stroke; stroke = makeEllipticStroke(0.07, TPointD((vecsize.lx - 1) * .5, (vecsize.ly - 1) * .5), 2.0, 2.0); TVectorImageP vectmp = new TVectorImage(); TPalette *plt = new TPalette(); vectmp->setPalette(plt); vectmp->addStroke(stroke); TVectorRenderData rd(AffI, TRect(vecsize), plt, 0, true, true); offlineGlContext->makeCurrent(); offlineGlContext->draw(vectmp, rd); partLevel[0]->setFrame(0, TRasterImageP(offlineGlContext->getRaster()->clone())); p_size.lx = vecsize.lx + 1; p_size.ly = vecsize.ly + 1; lastframe.push_back(1); delete offlineGlContext; } Iwa_Particles_Engine myEngine(this, frame); // Retrieving the dpi multiplier from the accumulated affine (which is isotropic). That is, // the affine will be applied *before* this effect - and we'll multiply geometrical parameters // by this dpi mult. in order to compensate. float dpi = sqrt(fabs(ri.m_affine.det())) * 100; TTile tileIn; if (TRaster32P raster32 = tile.getRaster()) { TFlash *flash = 0; myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel, 1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier()); } else if (TRaster64P raster64 = tile.getRaster()) { TFlash *flash = 0; myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel, 1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier()); } else throw TException("ParticlesFx: unsupported Pixel Type"); }
void mergeColumns(int column, int mColumn, bool isRedo) { MergeColumnsSessionId++; TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int start, end; xsh->getCellRange(column, start, end); if (start > end) return; vector<TXshCell> cell(end - start + 1); vector<TXshCell> mCell(end - start + 1); xsh->getCells(start, column, cell.size(), &(cell[0])); xsh->getCells(start, mColumn, cell.size(), &(mCell[0])); TXshColumn *col = xsh->getColumn(column); TXshColumn *mcol = xsh->getColumn(mColumn); vector<MatchlinePair> matchingLevels; std::set<TFrameId> alreadyDoneSet; TXshSimpleLevel *level = 0, *mLevel = 0; TXshLevelP xl; bool areRasters = false; std::map<TFrameId, QString> images; for (int i = 0; i < (int)cell.size(); i++) { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!level) { level = cell[i].getSimpleLevel(); xl = cell[i].m_level; } else if (level != cell[i].getSimpleLevel()) { MsgBox(WARNING, QObject::tr("It is not possible to perform a merging involving more than one level per column.")); return; } if (!mLevel) mLevel = mCell[i].getSimpleLevel(); else if (mLevel != mCell[i].getSimpleLevel()) { MsgBox(WARNING, QObject::tr("It is not possible to perform a merging involving more than one level per column.")); return; } TImageP img = cell[i].getImage(true); TImageP match = mCell[i].getImage(false); TFrameId fid = cell[i].m_frameId; TFrameId mFid = mCell[i].m_frameId; if (!img || !match) continue; if (alreadyDoneSet.find(fid) == alreadyDoneSet.end()) { TRasterImageP timg = (TRasterImageP)img; TRasterImageP tmatch = (TRasterImageP)match; TVectorImageP vimg = (TVectorImageP)img; TVectorImageP vmatch = (TVectorImageP)match; if (timg) { if (!tmatch) { MsgBox(WARNING, QObject::tr("Only raster levels can be merged to a raster level.")); return; } areRasters = true; } else if (vimg) { if (!vmatch) { MsgBox(WARNING, QObject::tr("Only vector levels can be merged to a vector level.")); return; } } else { MsgBox(WARNING, QObject::tr("It is possible to merge only Toonz vector levels or standard raster levels.")); return; } QString id = "MergeColumnsUndo" + QString::number(MergeColumnsSessionId) + "-" + QString::number(fid.getNumber()); TImageCache::instance()->add(id, (timg) ? timg->cloneImage() : vimg->cloneImage()); images[fid] = id; TAffine imgAff, matchAff; getColumnPlacement(imgAff, xsh, start + i, column, false); getColumnPlacement(matchAff, xsh, start + i, mColumn, false); TAffine dpiAff = getDpiAffine(level, fid); TAffine mdpiAff = getDpiAffine(mLevel, mFid); matchingLevels.push_back(MatchlinePair(cell[i], imgAff * dpiAff, mCell[i], matchAff * mdpiAff)); alreadyDoneSet.insert(fid); } } if (matchingLevels.empty()) { MsgBox(WARNING, QObject::tr("It is possible to merge only Toonz vector levels or standard raster levels.")); return; } ToonzScene *sc = TApp::instance()->getCurrentScene()->getScene(); TXshSimpleLevel *simpleLevel = sc->getLevelSet()->getLevel(column)->getSimpleLevel(); if (!isRedo) TUndoManager::manager()->add(new MergeColumnsUndo(xl, MergeColumnsSessionId, column, level, images, mColumn, level->getPalette())); if (areRasters) { mergeRasterColumns(matchingLevels); for (int i = 0; i < (int)cell.size(); i++) //the saveboxes must be updated { if (cell[i].isEmpty() || mCell[i].isEmpty()) continue; if (!cell[i].getImage(false) || !mCell[i].getImage(false)) continue; ToolUtils::updateSaveBox(cell[i].getSimpleLevel(), cell[i].m_frameId); } } else mergeVectorColumns(matchingLevels); TXshLevel *sl = TApp::instance()->getCurrentScene()->getScene()->getLevelSet()->getLevel(column); vector<TFrameId> fidsss; sl->getFids(fidsss); invalidateIcons(sl, fidsss); sl->setDirtyFlag(true); level->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }