void CleanupSwatch::CleanupSwatchArea::keyPressEvent(QKeyEvent *event) { if (!m_sw->m_resampledRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; int key = event->key(); if (key != '+' && key != '-' && key != '0') return; if (key == '0') m_sw->m_viewAff = TAffine(); else { bool forward = (key == '+'); double currZoomScale = sqrt(m_sw->m_viewAff.det()); double factor = getQuantizedZoomFactor(currZoomScale, forward); double minZoom = tmin((double)m_sw->m_lx / m_sw->m_resampledRaster->getLx(), (double)m_sw->m_ly / m_sw->m_resampledRaster->getLy()); if ((!forward && factor < minZoom) || (forward && factor > 40.0)) return; TPointD delta(0.5 * width(), 0.5 * height()); m_sw->m_viewAff = (TTranslation(delta) * TScale(factor / currZoomScale) * TTranslation(-delta)) * m_sw->m_viewAff; } m_sw->m_leftSwatch->updateRaster(); m_sw->m_rightSwatch->updateRaster(); }
/*! Add to current trasformation matrix a \b center traslation matched with a scale of factor \b factor. Apply a zoom of factor \b factor with center \b center. */ void ImageViewer::zoomQt(const QPoint ¢er, double factor) { if (factor == 1.0) return; TPointD delta(center.x(), center.y()); setViewAff(TTranslation(delta) * TScale(factor) * TTranslation(-delta) * m_viewAff); update(); }
//! Returns the affine transform from image reference to widget's pixel one. TAffine ImageViewer::getImgToWidgetAffine(const TRectD &geom) const { TPointD geomCenter((geom.x0 + geom.x1) * 0.5, (geom.y0 + geom.y1) * 0.5); QRect widGeom(rect()); TPointD viewerCenter((widGeom.left() + widGeom.right() + 1) * 0.5, (widGeom.top() + widGeom.bottom() + 1) * 0.5); return TAffine(TAffine(1.0, 0.0, 0.0, 0.0, -1.0, height()) * TTranslation(viewerCenter) * m_viewAff * TTranslation(-geomCenter)); }
void PlaneViewer::draw(TRasterP ras, double dpiX, double dpiY, TPalette *pal) { TPointD rasCenter(ras->getCenterD()); TRaster32P aux(rasterBuffer()); aux->lock(); ras->lock(); glGetDoublev(GL_MODELVIEW_MATRIX, m_matrix); TAffine viewAff(m_matrix[0], m_matrix[4], m_matrix[12], m_matrix[1], m_matrix[5], m_matrix[13]); viewAff = viewAff * TScale(Stage::inch / dpiX, Stage::inch / dpiY) * TTranslation(-rasCenter); pushGLWinCoordinates(); aux->clear(); if (pal) TRop::quickPut(aux, (TRasterCM32P)ras, pal, viewAff); else TRop::quickPut(aux, ras, viewAff); flushRasterBuffer(); popGLCoordinates(); }
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; }
/*! Add to current trasformation matrix a \b delta traslation. */ void ImageViewer::panQt(const QPoint &delta) { if (delta == QPoint()) return; // stop panning when the image is at the edge of window QPoint delta_(delta.x(), delta.y()); TToonzImageP timg = (TToonzImageP)m_image; TRasterImageP rimg = (TRasterImageP)m_image; if (timg || rimg) { bool isXPlus = delta.x() > 0; bool isYPlus = delta.y() > 0; TDimension imgSize((timg) ? timg->getSize() : rimg->getRaster()->getSize()); int subSampling = (timg) ? timg->getSubsampling() : rimg->getSubsampling(); TPointD cornerPos = TPointD(imgSize.lx * ((isXPlus) ? -1 : 1), imgSize.ly * ((isYPlus) ? 1 : -1)) * (0.5 / (double)subSampling); cornerPos = m_viewAff * cornerPos; if ((cornerPos.x > 0) == isXPlus) delta_.setX(0); if ((cornerPos.y < 0) == isYPlus) delta_.setY(0); } setViewAff(TTranslation(delta_.x(), -delta_.y()) * m_viewAff); update(); }
DrawableTextureDataP texture_utils::getTextureData( const TXshSimpleLevel *sl, const TFrameId &fid, int subsampling) { const std::string &texId = sl->getImageId(fid); // Now, we must associate a texture DrawableTextureDataP data(TTexturesStorage::instance()->getTextureData(texId)); if (data) return data; // There was no associated texture. We must bind the texture and repeat // First, retrieve the image to be used as texture TRasterImageP ri(::getTexture(sl, fid, subsampling)); if (!ri) return DrawableTextureDataP(); TRaster32P ras(ri->getRaster()); assert(ras); TRectD geom(0, 0, ras->getLx(), ras->getLy()); geom = TScale(ri->getSubsampling()) * TTranslation(convert(ri->getOffset()) - ras->getCenterD()) * geom; return TTexturesStorage::instance()->loadTexture(texId, ras, geom); }
void PlaneViewer::resizeGL(int width, int height) { width *= getDevPixRatio(); height *= getDevPixRatio(); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, width, 0, height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (m_firstResize) { m_firstResize = false; m_aff = TTranslation(0.5 * width, 0.5 * height); m_width = width; m_height = height; } else { TPointD oldCenter(m_width * 0.5, m_height * 0.5); TPointD newCenter(width * 0.5, height * 0.5); m_aff = m_aff.place(m_aff.inv() * oldCenter, newCenter); m_width = width; m_height = height; } }
// // Compute m_aff[0] and m_aff[1] according to the current curve // void ShiftTraceTool::updateCurveAffs() { if (m_curveStatus != ThreePointsCurve) { m_aff[0] = m_aff[1] = TAffine(); } else { double phi0 = 0, phi1 = 0; TPointD center; if (circumCenter(center, m_p0, m_p1, m_p2)) { TPointD v0 = normalize(m_p0 - center); TPointD v1 = normalize(m_p1 - center); TPointD v2 = normalize(m_p2 - center); TPointD u0(-v0.y, v0.x); TPointD u1(-v1.y, v1.x); phi0 = atan2((v2 * u0), (v2 * v0)) * 180.0 / 3.1415; phi1 = atan2((v2 * u1), (v2 * v1)) * 180.0 / 3.1415; } m_aff[0] = TTranslation(m_p2 - m_p0) * TRotation(m_p0, phi0); m_aff[1] = TTranslation(m_p2 - m_p1) * TRotation(m_p1, phi1); } }
void CleanupSwatch::CleanupSwatchArea::wheelEvent(QWheelEvent *event) { if (!m_sw->m_resampledRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return; int step = event->delta() > 0 ? 120 : -120; double factor = exp(0.001 * step); if (factor == 1.0) return; double scale = m_sw->m_viewAff.det(); double minZoom = tmin((double)m_sw->m_lx / m_sw->m_resampledRaster->getLx(), (double)m_sw->m_ly / m_sw->m_resampledRaster->getLy()); if ((factor < 1 && sqrt(scale) < minZoom) || (factor > 1 && scale > 1200.0)) return; TPointD delta(event->pos().x(), height() - event->pos().y()); m_sw->m_viewAff = (TTranslation(delta) * TScale(factor) * TTranslation(-delta)) * m_sw->m_viewAff; m_sw->m_leftSwatch->updateRaster(); m_sw->m_rightSwatch->updateRaster(); }
TRect TRasterImageUtils::addStroke(const TRasterImageP &ri, TStroke *stroke, TRectD clip, double opacity, bool doAntialiasing) { TStroke *s = new TStroke(*stroke); TPoint riCenter = ri->getRaster()->getCenter(); s->transform(TTranslation(riCenter.x, riCenter.y)); TRect rect = fastAddInkStroke(ri, s, clip, opacity, doAntialiasing); rect -= riCenter; delete s; return rect; }
void MorphTool::draw() { m_pixelSize = sqrt(tglGetPixelSize2()); if (m_vi2) { TVectorRenderData rd(TTranslation(10, 10), TRect(), 0, 0); tglDraw(rd, m_vi2.getPointer()); } double u = m_pixelSize * 5; for (int i = 0; i < (int)deformation.m_controlPoints.size(); i++) { TPointD p = deformation.m_controlPoints[i]; bool selected = deformation.m_selected == i; bool base = (i & 1) == 0; if (base) if (selected) glColor3d(0.8, 0.8, 0.1); else glColor3d(0.5, 0.5, 0.1); else if (selected) glColor3d(0.8, 0.3, 0.1); else glColor3d(0.5, 0.1, 0.1); double r = base ? u * 2 : u * 1; tglDrawDisk(p, r); glColor3d(0, 0, 0); tglDrawCircle(p, r); } glColor3f(0, 1, 0); for (int i = 0; i + 1 < (int)deformation.m_controlPoints.size(); i += 2) { TPointD a = deformation.m_controlPoints[i]; TPointD b = deformation.m_controlPoints[i + 1]; tglDrawSegment(a, b); } /* deformation.update(); glBegin(GL_LINES); for(double x = -200; x<=200; x+=20) for(double y = -200; y<=200; y+=20) { TPointD p0(x,y); TPointD p1 = deformation.apply(p0); glColor3d(0,1,0); tglVertex(p0); glColor3d(1,0,0); tglVertex(p1); } glEnd(); */ }
//! Adapts image viewer's affine to display the passed image rect at maximized //! ratio void ImageViewer::adaptView(const TRect &imgRect, const TRect &viewRect) { QRect viewerRect(rect()); double imageScale = std::min(viewerRect.width() / (double)viewRect.getLx(), viewerRect.height() / (double)viewRect.getLy()); TPointD viewRectCenter((viewRect.x0 + viewRect.x1 + 1) * 0.5, (viewRect.y0 + viewRect.y1 + 1) * 0.5); TPointD imgRectCenter((imgRect.x0 + imgRect.x1 + 1) * 0.5, (imgRect.y0 + imgRect.y1 + 1) * 0.5); TAffine newViewAff(TScale(imageScale, imageScale) * TTranslation(imgRectCenter - viewRectCenter)); setViewAff(newViewAff); }
void TRop::over(const TRasterP &out, const TRasterP &up, const TPoint &pos, const TAffine &aff, ResampleFilterType filterType) { if (aff.isIdentity()) //simple over with offset TRop::over(out, up, pos); else { TRect rasterBounds = up->getBounds(); TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1, rasterBounds.y1); dbounds = aff * dbounds; TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1), tceil(dbounds.y1)); TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); resample(tmp, up, TTranslation(-dbounds.getP00()) * aff, filterType); TRop::over(out, tmp, pos); } }
void CleanupSwatch::CleanupSwatchArea::updateCleanupped(bool dragging) { TAffine aff = getFinalAff(); TRect rectToCompute = convert(aff.inv() * convert(m_r->getBounds())); rectToCompute = rectToCompute.enlarge(TCleanupper::instance()->getParameters()->m_despeckling); TRect outRect = m_sw->m_resampledRaster->getBounds() * rectToCompute; if (outRect.isEmpty()) return; TRasterP rasCleanupped = TCleanupper::instance()->processColors(m_sw->m_resampledRaster->extract(outRect)); TPointD cleanuppedPos = convert(outRect.getP00()); TRop::quickPut(m_r, rasCleanupped, aff * TTranslation(cleanuppedPos)); }
void ShiftTraceTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &) { if (m_gadget == NoGadget) { if (norm(pos - m_oldPos) > 10 * getPixelSize()) { m_curveStatus = TwoPointsCurve; m_p0 = m_oldPos; m_gadget = CurveP1Gadget; } } if (isCurveGadget(m_gadget)) { if (m_gadget == CurveP0Gadget) m_p0 = pos; else if (m_gadget == CurveP1Gadget) m_p1 = pos; else m_p2 = pos; updateCurveAffs(); } else if (m_gadget == RotateGadget) { TAffine aff = getGhostAff(); TPointD c = aff * m_center[m_ghostIndex]; TPointD a = m_oldPos - c; TPointD b = pos - c; m_oldPos = pos; TPointD u = normalize(a); double phi = atan2(-u.y * b.x + u.x * b.y, u.x * b.x + u.y * b.y) * 180.0 / 3.14153; TPointD imgC = aff * m_center[m_ghostIndex]; m_aff[m_ghostIndex] = TRotation(imgC, phi) * m_aff[m_ghostIndex]; } else if (m_gadget == MoveCenterGadget) { TAffine aff = getGhostAff().inv(); TPointD delta = aff * pos - aff * m_oldPos; m_oldPos = pos; m_center[m_ghostIndex] += delta; } else if (m_gadget == TranslateGadget) { TPointD delta = pos - m_oldPos; m_oldPos = pos; m_aff[m_ghostIndex] = TTranslation(delta) * m_aff[m_ghostIndex]; } updateGhost(); invalidate(); }
//---------------------------------------------------------------- void CleanupSwatch::CleanupSwatchArea::mouseMoveEvent(QMouseEvent *event) { if (!m_panning) return; TPoint curPos = TPoint(event->pos().x(), event->pos().y()); QPoint delta = event->pos() - m_pos; if (delta == QPoint()) return; TAffine oldAff = m_sw->m_viewAff; m_sw->m_viewAff = TTranslation(delta.x(), -delta.y()) * m_sw->m_viewAff; m_sw->m_leftSwatch->updateRaster(); m_sw->m_rightSwatch->updateRaster(true); m_pos = event->pos(); }
RasterMovieGenerator(const TFilePath &fp, const TDimension cameraSize, TOutputProperties &properties) : Imp(fp, cameraSize, properties.getFrameRate()) , m_frameIndex(1) , m_started(false) , m_offlineGlContext(*TOfflineGL::getStock(cameraSize)) , m_st(0) , m_whiteSample(0) , m_fileOptions(0) , m_alphaEnabled(false) , m_alphaNeeded(false) , m_status(0) { m_bgColor = TPixel32(255, 255, 255, 0); TPointD center(0.5 * cameraSize.lx, 0.5 * cameraSize.ly); m_viewAff = TTranslation(center); std::string ext = fp.getType(); m_isFrames = ext != "avi" && ext != "mov" && ext != "3gp"; m_fileOptions = properties.getFileFormatProperties(ext); }
void CleanupSwatch::CleanupSwatchArea::updateCleanupped Versione ricalcolo Al Release Del mouse(bool dragging) { TAffine aff = getFinalAff(); TRect rectToCompute = convert(aff.inv() * convert(m_r->getBounds())); rectToCompute = rectToCompute.enlarge(TCleanupper::instance()->getParameters()->m_despeckling); TRect outRect = m_sw->m_resampledRaster->getBounds() * rectToCompute; if (outRect.isEmpty()) return; if (dragging && m_sw->m_lastRasCleanupped) m_r->fill(TPixel(200, 200, 200)); else { m_sw->m_lastRasCleanupped = TCleanupper::instance()->processColors(m_sw->m_resampledRaster->extract(outRect)); m_sw->m_lastCleanuppedPos = convert(outRect.getP00()); } TRop::quickPut(m_r, m_sw->m_lastRasCleanupped, aff * TTranslation(m_sw->m_lastCleanuppedPos)); }
void TRop::over(const TRasterP &out, const TRasterP &up, const TAffine &aff, ResampleFilterType filterType) { out->lock(); up->lock(); if (filterType == ClosestPixel || filterType == Bilinear) ::quickPut(out, up, aff, filterType); else { TRect rasterBounds = up->getBounds(); TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1 + 1, rasterBounds.y1 + 1); dbounds = aff * dbounds; TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1) - 1, tceil(dbounds.y1) - 1); TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); resample(tmp, up, TTranslation(-bounds.x0, -bounds.y0) * aff, filterType); over(out, tmp, bounds.getP00()); } out->unlock(); up->unlock(); }
//!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 RenderCommand::flashRender() { ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); TSceneProperties *sprop = scene->getProperties(); FILE *fileP = fopen(m_fp, "wb"); if (!fileP) return; ProgressDialog pb("rendering " + toQString(m_fp), "Cancel", 0, m_numFrames); pb.show(); TDimension cameraSize = scene->getCurrentCamera()->getRes(); double frameRate = sprop->getOutputProperties()->getFrameRate(); TFlash flash( cameraSize.lx, cameraSize.ly, m_numFrames, frameRate, sprop->getOutputProperties()->getFileFormatProperties("swf")); flash.setBackgroundColor(sprop->getBgColor()); std::vector<TXshSoundColumn *> columns; scene->getSoundColumns(columns); if (!columns.empty()) { TXsheet::SoundProperties *prop = new TXsheet::SoundProperties(); prop->m_frameRate = frameRate; TSoundTrack *st = scene->getXsheet()->makeSound(prop); if (st) flash.putSound(st, 0); } int i = 0; for (i = 0; i < m_numFrames; ++i, m_r += m_stepd) { flash.beginFrame(m_step * i + 1); TRasterFxP rfx = buildSceneFx(scene, m_r, 0, false); assert(rfx); rfx->compute(flash, tround(m_r)); // WARNING: This should accept a DOUBLE... #ifdef BRAVODEMO TRasterImageP ri(loadBravo(scene->getCurrentCamera()->getRes())); int lx = ri->getRaster()->getLx(); int ly = ri->getRaster()->getLx(); flash.pushMatrix(); int dx = tround(0.1 * (cameraSize.lx - lx)); int dy = tround(0.1 * (cameraSize.ly - ly)); flash.multMatrix(TTranslation((cameraSize.lx - lx) / 2 - (dx > 0 ? dx : 0), -(cameraSize.ly - ly) / 2 + (dy > 0 ? dy : 0))); flash.draw(ri, 0); flash.popMatrix(); #endif flash.endFrame(i == m_numFrames - 1, 0, true); if (pb.wasCanceled()) break; pb.setValue(i + 1); } flash.writeMovie(fileP); fclose(fileP); TSystem::showDocument(m_fp); //QDesktopServices::openUrl(QUrl(toQString(m_fp))); TImageCache::instance()->remove(toString(m_fp.getWideString() + L".0")); TNotifier::instance()->notify(TSceneNameChange()); }
/*- render_particles から呼ばれる。粒子の数だけ繰り返し -*/ void Particles_Engine::do_render( TFlash *flash, Particle *part, TTile *tile, std::vector<TRasterFxPort *> part_ports, std::map<int, TTile *> porttiles, const TRenderSettings &ri, TDimension &p_size, TPointD &p_offset, int lastframe, std::vector<TLevelP> partLevel, struct particles_values &values, double opacity_range, int dist_frame, std::map<std::pair<int, int>, double> &partScales) { // Retrieve the particle frame - that is, the *column frame* from which we are // picking // the particle to be rendered. int ndx = part->frame % lastframe; TRasterP tileRas(tile->getRaster()); std::string levelid; double aim_angle = 0; if (values.pathaim_val) { double arctan = atan2(part->vy, part->vx); aim_angle = arctan * M_180_PI; } // Calculate the rotational and scale components we have to apply on the // particle TRotation rotM(part->angle + aim_angle); TScale scaleM(part->scale); TAffine M(rotM * scaleM); // Particles deal with dpi affines on their own TAffine scaleAff(m_parent->handledAffine(ri, m_frame)); double partScale = scaleAff.a11 * partScales[std::pair<int, int>(part->level, ndx)]; TDimensionD partResolution(0, 0); TRenderSettings riNew(ri); // Retrieve the bounding box in the standard reference TRectD bbox(-5.0, -5.0, 5.0, 5.0), standardRefBBox; if (part->level < (int)part_ports.size() && // Not the default levelless cases part_ports[part->level]->isConnected()) { TRenderSettings riIdentity(ri); riIdentity.m_affine = TAffine(); (*part_ports[part->level])->getBBox(ndx, bbox, riIdentity); // A particle's bbox MUST be finite. Gradients and such which have an // infinite bbox // are just NOT rendered. // NOTE: No fx returns half-planes or similar (ie if any coordinate is // either // (std::numeric_limits<double>::max)() or its opposite, then the rect IS // THE infiniteRectD) if (bbox == TConsts::infiniteRectD) return; } // Now, these are the particle rendering specifications bbox = bbox.enlarge(3); standardRefBBox = bbox; riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * bbox; /*- 縮小済みのParticleのサイズ -*/ partResolution = TDimensionD(tceil(bbox.getLx()), tceil(bbox.getLy())); if (flash) { if (!partLevel[part->level]->frame(ndx)) { if (part_ports[0]->isConnected()) { TTile auxTile; TRaster32P tmp; tmp = TRaster32P(p_size); (*part_ports[0]) ->allocateAndCompute(auxTile, p_offset, p_size, tmp, ndx, ri); partLevel[part->level]->setFrame(ndx, TRasterImageP(auxTile.getRaster())); } } flash->pushMatrix(); const TAffine aff; flash->multMatrix(scaleM * aff.place(0, 0, part->x, part->y)); // if(curr_opacity!=1.0 || part->gencol.fadecol || part->fincol.fadecol || // part->foutcol.fadecol) { TColorFader cf(TPixel32::Red, .5); flash->draw(partLevel[part->level]->frame(ndx), &cf); } // flash->draw(partLevel->frame(ndx), 0); flash->popMatrix(); } else { TRasterP ras; std::string alias; TRasterImageP rimg; if (rimg = partLevel[part->level]->frame(ndx)) { ras = rimg->getRaster(); } else { alias = "PART: " + (*part_ports[part->level])->getAlias(ndx, riNew); if (rimg = TImageCache::instance()->get(alias, false)) { ras = rimg->getRaster(); // Check that the raster resolution is sufficient for our purposes if (ras->getLx() < partResolution.lx || ras->getLy() < partResolution.ly) ras = 0; else partResolution = TDimensionD(ras->getLx(), ras->getLy()); } } // We are interested in making the relation between scale and (integer) // resolution // bijective - since we shall cache by using resolution as a partial // identification parameter. // Therefore, we find the current bbox Lx and take a unique scale out of it. partScale = partResolution.lx / standardRefBBox.getLx(); riNew.m_affine = TScale(partScale); bbox = riNew.m_affine * standardRefBBox; // If no image was retrieved from the cache (or it was not scaled enough), // calculate it if (!ras) { TTile auxTile; (*part_ports[part->level]) ->allocateAndCompute(auxTile, bbox.getP00(), TDimension(partResolution.lx, partResolution.ly), tile->getRaster(), ndx, riNew); ras = auxTile.getRaster(); // For now, we'll just use 32 bit particles TRaster32P rcachepart; rcachepart = ras; if (!rcachepart) { rcachepart = TRaster32P(ras->getSize()); TRop::convert(rcachepart, ras); } ras = rcachepart; // Finally, cache the particle addRenderCache(alias, TRasterImageP(ras)); } if (!ras) return; // At this point, it should never happen anyway... // Deal with particle colors/opacity TRaster32P rfinalpart; double curr_opacity = part->set_Opacity(porttiles, values, opacity_range, dist_frame); if (curr_opacity != 1.0 || part->gencol.fadecol || part->fincol.fadecol || part->foutcol.fadecol) { /*- 毎フレーム現在位置のピクセル色を参照 -*/ if (values.pick_color_for_every_frame_val && values.gencol_ctrl_val && (porttiles.find(values.gencol_ctrl_val) != porttiles.end())) part->get_image_reference(porttiles[values.gencol_ctrl_val], values, part->gencol.col); rfinalpart = ras->clone(); part->modify_colors_and_opacity(values, curr_opacity, dist_frame, rfinalpart); } else rfinalpart = ras; // Now, let's build the particle transform before it is overed on the output // tile // First, complete the transform by adding the rotational and scale // components from // Particles parameters M = ri.m_affine * M * TScale(1.0 / partScale); // Then, retrieve the particle position in current reference. TPointD pos(part->x, part->y); pos = ri.m_affine * pos; // Finally, add the translational component to the particle // NOTE: p_offset is added to account for the particle relative position // inside its level's bbox M = TTranslation(pos - tile->m_pos) * M * TTranslation(bbox.getP00()); if (TRaster32P myras32 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else if (TRaster64P myras64 = tile->getRaster()) TRop::over(tileRas, rfinalpart, M); else throw TException("ParticlesFx: unsupported Pixel Type"); } }
void PlaneViewer::resetView() { m_aff = TTranslation(0.5 * width(), 0.5 * height()); update(); }
void doCompute(TTile &tile, double frame, const TRenderSettings &info) override { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double period = m_period->getValue(frame) / info.m_shrinkX; double count = m_count->getValue(frame); double cycle = m_cycle->getValue(frame) / info.m_shrinkX; double scaleX = m_scaleX->getValue(frame) / 100.0; double scaleY = m_scaleY->getValue(frame) / 100.0; double angle = -m_angle->getValue(frame); TPointD center = m_center->getValue(frame) * (1.0 / info.m_shrinkX); // The warper is calculated on a standard reference, with fixed dpi. This // makes sure // that the lattice created for the warp does not depend on camera // transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; // Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } // Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); // Compute the warped tile TTile tileIn; m_warped->allocateAndCompute( tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); // Compute the warper tile TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(0.5, TPixel32::Black), TSpectrum::ColorKey(1, TPixel32::White)}; TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors); // Build the multiradial warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) * TRotation(angle) * TScale(scaleX, scaleY); TAffine aff = warperInfo.m_affine.inv(); TPointD posTrasf = aff * (warperComputeRect.getP00()); TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff, frame); // TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper); // Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos( (TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); }
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 tglDraw(const TMeshImage &meshImage, const DrawableTextureData &texData, const TAffine &meshToTexAff, const PlasticDeformerDataGroup &group) { typedef MeshTexturizer::TextureData::TileData TileData; // Prepare OpenGL glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT); // Preserve original status bits glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glLineWidth(1.0f); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Prepare variables const std::vector<TTextureMeshP> &meshes = meshImage.meshes(); const TTextureMesh *mesh; typedef std::vector<std::pair<int, int>> SortedFacesVector; const SortedFacesVector &sortedFaces = group.m_sortedFaces; const MeshTexturizer::TextureData *td = texData.m_textureData; int t, tCount = td->m_tileDatas.size(); GLuint texId = -1; int m = -1; const double *dstCoords; int v0, v1, v2; int e1ovi, e2ovi; // Edge X's Other Vertex Index (see below) // Prepare each tile's affine std::vector<TAffine> tileAff(tCount); for (t = 0; t != tCount; ++t) { const TileData &tileData = td->m_tileDatas[t]; const TRectD &tileRect = tileData.m_tileGeometry; tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) * TTranslation(-tileRect.x0, -tileRect.y0) * meshToTexAff; } // Draw each face individually, according to the group's sorted faces list. // Change tile and mesh data only if they change - improves performance SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end()); for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) { int f = sft->first, m_ = sft->second; if (m != m_) { // Change mesh if different from current m = m_; mesh = meshes[m].getPointer(); dstCoords = group.m_datas[m].m_output.get(); } // Draw each face const TTextureMesh::face_type &fc = mesh->face(f); const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)), &ed1 = mesh->edge(fc.edge(1)), &ed2 = mesh->edge(fc.edge(2)); { v0 = ed0.vertex(0); v1 = ed0.vertex(1); v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1)); e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes e2ovi = 1 - e1ovi; // with index 2 and these. } const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P(); for (t = 0; t != tCount; ++t) { // Draw face against tile const TileData &tileData = td->m_tileDatas[t]; // Map each face vertex to tile coordinates TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2}; // Test the face bbox - tile intersection if (std::min({s[0].x, s[1].x, s[2].x}) > 1.0 || std::min({s[0].y, s[1].y, s[2].y}) > 1.0 || std::max({s[0].x, s[1].x, s[2].x}) < 0.0 || std::max({s[0].y, s[1].y, s[2].y}) < 0.0) continue; // If the tile has changed, interrupt the glBegin/glEnd block and bind the // OpenGL texture corresponding to the new tile if (tileData.m_textureId != texId) { texId = tileData.m_textureId; glBindTexture( GL_TEXTURE_2D, tileData .m_textureId); // This must be OUTSIDE a glBegin/glEnd block } const double *d[3] = {dstCoords + (v0 << 1), dstCoords + (v1 << 1), dstCoords + (v2 << 1)}; /* Now, draw primitives. A note about pixel arithmetic, here. Since line antialiasing in OpenGL just manipulates output fragments' alpha components, we must require that the input texture is NONPREMULTIPLIED. Furthermore, this function does not rely on the assumption that the output alpha component is discarded (as it happens when drawing on screen). This means that just using a simple glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this way THE INPUT SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows. The solution is to separate the rendering of RGB and M components - the formers use GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image. */ // First, draw antialiased face edges on the mesh border. bool drawEd0 = (ed0.facesCount() < 2), drawEd1 = (ed1.facesCount() < 2), drawEd2 = (ed2.facesCount() < 2); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glBegin(GL_LINES); { if (drawEd0) { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); } if (drawEd1) { glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } if (drawEd2) { glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } } glEnd(); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glBegin(GL_LINES); { if (drawEd0) { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); } if (drawEd1) { glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } if (drawEd2) { glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } } glEnd(); // Finally, draw the face glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glBegin(GL_TRIANGLES); { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } glEnd(); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glBegin(GL_TRIANGLES); { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } glEnd(); } } glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture glPopAttrib(); }
QString ImageBuilder::add(const TImageP &img, const TAffine &aff) { if (fabs(aff.det()) < 0.001) return ""; if (m_img && (m_img->getType() != img->getType())) return "Image type mismatch"; if (!m_img && img->getType() != TImage::VECTOR && m_width > 0 && m_height > 0) { TRasterP ras = img->raster()->create(m_width, m_height); if (img->getType() == TImage::RASTER) m_img = TRasterImageP(ras); else if (img->getType() == TImage::TOONZ_RASTER) { m_img = TToonzImageP(ras, ras->getBounds()); m_img->setPalette(img->getPalette()); } else return "Bad image type"; } if (!m_img && aff.isIdentity()) { m_img = img->cloneImage(); } else if (img->getType() == TImage::VECTOR) { // vector image if (!m_img) { // transform TVectorImageP vi = img->cloneImage(); vi->transform(aff); m_img = vi; } else { // merge TVectorImageP up = img; TVectorImageP dn = m_img; dn->mergeImage(up, aff); } } else { if (img->getType() != TImage::TOONZ_RASTER && img->getType() != TImage::RASTER) { // this should not ever happen return "Bad image type"; } TRasterP up = img->raster(); if (!m_img) { // create an empty bg TRasterP ras = up->create(); ras->clear(); if (img->getType() == TImage::TOONZ_RASTER) { TRasterCM32P rasCm = ras; m_img = TToonzImageP(rasCm, TRect(0, 0, ras->getLx() - 1, ras->getLy() - 1)); m_img->setPalette(img->getPalette()); } else { m_img = TRasterImageP(ras); } } TRasterP dn = m_img->raster(); if (aff.isTranslation() && aff.a13 == floor(aff.a13) && aff.a23 == floor(aff.a23)) { // just a integer coord translation TPoint delta = -up->getCenter() + dn->getCenter() + TPoint((int)aff.a13, (int)aff.a23); TRop::over(dn, up, delta); } else { TAffine aff1 = TTranslation(dn->getCenterD()) * aff * TTranslation(-up->getCenterD()); TRop::over(dn, up, aff1, TRop::Mitchell); } } return ""; }
QScriptValue Transform::translate(double x, double y) { return create(engine(), new Transform(TTranslation(x, y) * m_affine)); }
void ImageViewer::paintGL() { if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->bind(); TDimension viewerSize(width(), height()); TAffine aff = m_viewAff; // if (!m_visualSettings.m_defineLoadbox && m_flipbook && // m_flipbook->getLoadbox()!=TRect()) // offs = // convert(m_flipbook->getLoadbox().getP00())-TPointD(m_flipbook->getImageSize().lx/2.0, // m_flipbook->getImageSize().ly/2.0); TDimension imageSize; TRect loadbox; if (m_flipbook) { QString title = (!m_image) ? m_flipbook->getTitle() + tr(" :: Zoom : ") + QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %" : m_flipbook->getLevelZoomTitle() + tr(" :: Zoom : ") + QString::number(tround(sqrt(m_viewAff.det()) * 100)) + " %"; m_flipbook->parentWidget()->setWindowTitle(title); imageSize = m_flipbook->getImageSize(); if (m_visualSettings.m_useLoadbox && m_flipbook->getLoadbox() != TRect()) loadbox = m_flipbook->getLoadbox(); } m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); // enable checks only in the color model m_visualSettings.m_useChecks = m_isColorModel; ImagePainter::paintImage(m_image, imageSize, viewerSize, aff, m_visualSettings, m_compareSettings, loadbox); // when fx parameter is modified with showing the fx preview, // a flipbook shows a red border line before the rendered result is shown. if (m_isRemakingPreviewFx) { glPushMatrix(); glLoadIdentity(); glColor3d(1.0, 0.0, 0.0); glBegin(GL_LINE_LOOP); glVertex2d(5, 5); glVertex2d(5, height() - 5); glVertex2d(width() - 5, height() - 5); glVertex2d(width() - 5, 5); glEnd(); glBegin(GL_LINE_LOOP); glVertex2d(10, 10); glVertex2d(10, height() - 10); glVertex2d(width() - 10, height() - 10); glVertex2d(width() - 10, 10); glEnd(); glPopMatrix(); } if (!m_image) { if (m_lutCalibrator && m_lutCalibrator->isValid()) m_lutCalibrator->onEndDraw(m_fbo); return; } if (safeAreaToggle.getStatus() && !m_isColorModel) { TRasterImageP rimg = (TRasterImageP)m_image; TVectorImageP vimg = (TVectorImageP)m_image; TToonzImageP timg = (TToonzImageP)m_image; TRect bbox; TPointD centerD; TRect bounds; if (rimg) { centerD = rimg->getRaster()->getCenterD(); bounds = rimg->getRaster()->getBounds(); } else if (timg) { centerD = timg->getRaster()->getCenterD(); bounds = timg->getRaster()->getBounds(); } if (!vimg) { TAffine aff = TTranslation(viewerSize.lx * 0.5, viewerSize.ly * 0.5) * m_viewAff * TTranslation(-centerD); TRectD bbox = aff * TRectD(0, 0, bounds.getLx() - 1, bounds.getLy() - 1); drawSafeArea(bbox); } } TPoint fromPos, toPos; if (m_visualSettings.m_defineLoadbox && m_flipbook) { TRect loadbox = convert(getImgToWidgetAffine() * convert(m_flipbook->getLoadbox())); if (loadbox != TRect()) { TPoint p00 = loadbox.getP00(); TPoint p11 = loadbox.getP11(); fromPos = TPoint(p00.x - width() * 0.5, height() * 0.5 - p00.y); // m_flipbook->getLoadbox().getP00(); toPos = TPoint(p11.x - width() * 0.5, height() * 0.5 - p11.y); // m_flipbook->getLoadbox().getP11(); } } else if (m_draggingZoomSelection || m_rectRGBPick) { fromPos = TPoint(m_pressedMousePos.x - width() * 0.5, height() * 0.5 - m_pressedMousePos.y); toPos = TPoint(m_pos.x() - width() * 0.5, height() * 0.5 - m_pos.y()); } if (fromPos != TPoint() || toPos != TPoint()) { if (m_rectRGBPick) { tglColor(TPixel32::Red); // TODO: glLineStipple is deprecated in the latest OpenGL. Need to be // replaced. (shun_iwasawa 2015/12/25) glLineStipple(1, 0x3F33); glEnable(GL_LINE_STIPPLE); glBegin(GL_LINE_STRIP); // do not draw the rect around the mouse cursor int margin = (fromPos.y < toPos.y) ? -3 : 3; glVertex2i(toPos.x, toPos.y + margin); glVertex2i(toPos.x, fromPos.y); glVertex2i(fromPos.x, fromPos.y); glVertex2i(fromPos.x, toPos.y); margin = (fromPos.x < toPos.x) ? -3 : 3; glVertex2i(toPos.x + margin, toPos.y); glEnd(); glDisable(GL_LINE_STIPPLE); } else { tglColor(m_draggingZoomSelection ? TPixel32::Red : TPixel32::Blue); glBegin(GL_LINE_STRIP); glVertex2i(fromPos.x, fromPos.y); glVertex2i(fromPos.x, toPos.y); glVertex2i(toPos.x, toPos.y); glVertex2i(toPos.x, fromPos.y); glVertex2i(fromPos.x, fromPos.y); glEnd(); } } if (m_lutCalibrator && m_lutCalibrator->isValid()) m_lutCalibrator->onEndDraw(m_fbo); }