TScannerParameters::TScannerParameters() : m_bw(false) , m_gray(false) , m_rgb(false) , m_scanType(None) , m_scanArea(TRectD()) , m_cropBox(TRectD()) , m_isPreview(false) , m_maxPaperSize(TDimensionD(0, 0)) , m_paperOverflow(false) , m_brightness() , m_contrast() , m_threshold() , m_dpi() , m_paperFeeder() , m_twainVersion() , m_manufacturer() , m_prodFamily() , m_productName() , m_version() , m_reverseOrder(false) , m_validatedByCurrentScanner(false) { m_threshold.m_value = 127; m_brightness.m_value = 127; }
void TScannerParameters::setPaperFormat(std::string paperFormat) { TPaperFormatManager *formatManager = TPaperFormatManager::instance(); assert(formatManager->isValidFormat(paperFormat)); if (!formatManager->isValidFormat(paperFormat)) paperFormat = formatManager->getDefaultFormat(); m_paperFormat = paperFormat; TDimensionD d = TPaperFormatManager::instance()->getSize(paperFormat); m_scanArea = TRectD(TPointD(0, 0), d); cropScanArea(); if (m_cropBox == TRectD()) m_cropBox = m_scanArea; }
/*! rectangular rgb picking. The picked color will be an average of pixels in * specified rectangle */ void ImageViewer::rectPickColor(bool putValueToStyleEditor) { if (!m_isHistogramEnable) return; if (!m_histogramPopup->isVisible()) return; StylePicker picker(m_image); TPoint startPos = TPoint(m_pressedMousePos.x, height() - 1 - m_pressedMousePos.y); TPoint endPos = TPoint(m_pos.x(), height() - 1 - m_pos.y()); TRectD area = TRectD(convert(startPos), convert(endPos)); area = area.enlarge(-1, -1); if (area.getLx() < 2 || area.getLy() < 2) { m_histogramPopup->updateAverageColor(TPixel32::Transparent); return; } if (m_lutCalibrator && m_lutCalibrator->isValid() && m_fbo) m_fbo->bind(); const TPixel32 pix = picker.pickColor(area.enlarge(-1, -1)); if (m_lutCalibrator && m_lutCalibrator->isValid() && m_fbo) m_fbo->release(); // throw the picked color to the histogram m_histogramPopup->updateAverageColor(pix); // throw it to the style editor as well if (putValueToStyleEditor) setPickedColorToStyleEditor(pix); }
void MeshTexturizer::Imp::allocateTextures(int groupIdx, const TRaster32P &ras, const TRaster32P &aux, int x, int y, int textureLx, int textureLy, bool premultiplied) { TextureData *data = m_textureDatas[groupIdx].get(); // Test the specified texture allocation if (testTextureAlloc(textureLx, textureLy)) { TPointD scale(data->m_geom.getLx() / (double)ras->getLx(), data->m_geom.getLy() / (double)ras->getLy()); TRectD tileGeom( TRectD( scale.x * (x - TOTAL_BORDER), scale.y * (y - TOTAL_BORDER), scale.x * (x + textureLx + TOTAL_BORDER), scale.y * (y + textureLy + TOTAL_BORDER)) + data->m_geom.getP00()); GLuint texId = textureAlloc(ras, aux, x, y, textureLx, textureLy, premultiplied); TextureData::TileData td = {texId, tileGeom}; data->m_tileDatas.push_back(td); return; } if (textureLx <= 1 && textureLy <= 1) return; // No texture can be allocated // The texture could not be allocated. Then, bisecate and branch. if (textureLx > textureLy) { int textureLx_2 = textureLx >> 1; allocateTextures(groupIdx, ras, aux, x, y, textureLx_2, textureLy, premultiplied); allocateTextures(groupIdx, ras, aux, x + textureLx_2, y, textureLx_2, textureLy, premultiplied); } else {
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 const geom = TScale(ri->getSubsampling()) * TTranslation(convert(ri->getOffset()) - ras->getCenterD()) * TRectD(0, 0, ras->getLx(), ras->getLy()); return TTexturesStorage::instance()->loadTexture(texId, ras, geom); }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &ri) override { if (m_input.isConnected() && m_controller.isConnected()) { TRectD controlBox, inputBox; TRenderSettings ri2(ri); ri2.m_affine = TAffine(); m_controller->getBBox(frame, controlBox, ri2); TRenderSettings ri3(ri); int shrink = tround((ri.m_shrinkX + ri.m_shrinkY) / 2.0); // Should be there no need for the alias... SandorFxRenderData *artContourData = buildRenderData(frame, shrink, controlBox, ""); ri3.m_data.push_back(artContourData); return m_input->doGetBBox(frame, bBox, ri3); } else if (m_input.isConnected()) { m_input->doGetBBox(frame, bBox, ri); return false; } bBox = TRectD(); return false; }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (this->m_input.isConnected()) { return this->m_input->doGetBBox(frame, bBox, info); } else { bBox = TRectD(); return false; } }
//------------------------------------------------------------ bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (false == this->m_input.isConnected()) { bBox = TRectD(); return false; } const bool ret = this->m_input->doGetBBox(frame, bBox, info); this->get_render_enlarge(frame, info.m_affine, bBox); return ret; }
TRectD TRasterImageUtils::convertRasterToWorld(const TRect &area, const TRasterImageP ri) { if (area.isEmpty()) return TRectD(); TRectD rect(area.x0, area.y0, area.x1 + 1, area.y1 + 1); if (ri && ri->getRaster()) rect = rect - ri->getRaster()->getCenterD(); return rect; }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) override { if (m_input.isConnected()) { bool ret = m_input->doGetBBox(frame, bBox, info); return ret; } else { bBox = TRectD(); return false; } }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (m_input.isConnected()) { bool ret = m_input->doGetBBox(frame, bBox, info); // devo scurire bgColor return ret; } else { bBox = TRectD(); return false; } };
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) override { for (int ii = 0; ii < this->getInputPortCount(); ++ii) { std::string nm = this->getInputPortName(ii); TRasterFxPort *tmp_port = (TRasterFxPort *)this->getInputPort(nm); if (tmp_port->isConnected()) { return (*tmp_port)->doGetBBox(frame, bBox, info); } } bBox = TRectD(); return false; }
void ShiftTraceTool::clearData() { m_ghostIndex = 0; m_curveStatus = NoCurve; m_gadget = NoGadget; m_highlightedGadget = NoGadget; m_box = TRectD(); for (int i = 0; i < 2; i++) { m_row[i] = -1; m_aff[i] = TAffine(); m_center[i] = TPointD(); } }
TRectD getBBox() const { if (!m_isValidBBox) { m_bBox = TRectD(); for (UINT i = 0; i < m_edge.size(); i++) m_bBox += m_edge[i]->m_s->getBBox(tmin(m_edge[i]->m_w0, m_edge[i]->m_w1), tmax(m_edge[i]->m_w0, m_edge[i]->m_w1)); m_isValidBBox = true; } return m_bBox; }
bool Iwa_GradientWarpFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (!m_source.isConnected()) { bBox = TRectD(); return false; } const bool ret = m_source->doGetBBox(frame, bBox, info); get_render_enlarge(frame, info.m_affine, bBox); return ret; }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (m_input.isConnected()) { //Build the render data TRenderSettings info2(info); buildBlendData(info2, frame); return m_input->doGetBBox(frame, bBox, info2); } else { bBox = TRectD(); return false; } }
void CameraTestTool::mouseMove(const TPointD &p, const TMouseEvent &e) { if (m_lastPos.x != -1) // left mouse button is clicked { m_scaling = eNoScale; return; } CleanupParameters *cp = CleanupSettingsModel::instance()->getCurrentParameters(); double pixelSize = getPixelSize(); TPointD size(10 * pixelSize, 10 * pixelSize); TRectD r(cp->m_camera.getStageRect()); TPointD aux(Stage::inch * TPointD(0.5 * cp->m_offx, 0.5 * cp->m_offy)); r -= aux; double maxDist = 5 * pixelSize; if (TRectD(r.getP00() - size, r.getP00() + size).contains(p)) m_scaling = e00; else if (TRectD(r.getP01() - size, r.getP01() + size).contains(p)) m_scaling = e01; else if (TRectD(r.getP11() - size, r.getP11() + size).contains(p)) m_scaling = e11; else if (TRectD(r.getP10() - size, r.getP10() + size).contains(p)) m_scaling = e10; else if (isCloseToSegment(p, TSegment(r.getP00(), r.getP10()), maxDist)) m_scaling = eM0; else if (isCloseToSegment(p, TSegment(r.getP10(), r.getP11()), maxDist)) m_scaling = e1M; else if (isCloseToSegment(p, TSegment(r.getP11(), r.getP01()), maxDist)) m_scaling = eM1; else if (isCloseToSegment(p, TSegment(r.getP01(), r.getP00()), maxDist)) m_scaling = e0M; else m_scaling = eNoScale; }
void ShiftTraceTool::updateData() { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int row = TApp::instance()->getCurrentFrame()->getFrame(); int col = TApp::instance()->getCurrentColumn()->getColumnIndex(); TXshCell cell = xsh->getCell(row, col); m_box = TRectD(); for (int i = 0; i < 2; i++) m_row[i] = -1; m_dpiAff = TAffine(); // we must find the prev (m_row[0]) and next (m_row[1]) reference images // (either might not exist) // see also stage.cpp, StageBuilder::addCellWithOnionSkin if (cell.isEmpty()) { // current cell is empty. search for the prev ref img int r = row - 1; while (r >= 0 && xsh->getCell(r, col).getSimpleLevel() == 0) r--; if (r >= 0) m_row[0] = r; // else prev drawing doesn't exist : nothing to do } else { // current cell is not empty // search for prev ref img TXshSimpleLevel *sl = cell.getSimpleLevel(); int r = row - 1; if (r >= 0) { TXshCell otherCell = xsh->getCell(r, col); if (otherCell.getSimpleLevel() == sl) { // find the span start while (r - 1 >= 0 && xsh->getCell(r - 1, col) == otherCell) r--; m_row[0] = r; } } // search for next ref img r = row + 1; while (xsh->getCell(r, col) == cell) r++; // first cell after the current span has the same level if (xsh->getCell(r, col).getSimpleLevel() == sl) m_row[1] = r; } updateBox(); }
bool Iwa_MotionBlurCompFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (!m_input.isConnected() && !m_background.isConnected()) { bBox = TRectD(); return false; } /*- 取り急ぎ、背景が繋がっていたら無限サイズにする -*/ if (m_background.isConnected()) { bool _ret = m_background->doGetBBox(frame, bBox, info); bBox = TConsts::infiniteRectD; return _ret; } bool ret = m_input->doGetBBox(frame, bBox, info); if (bBox == TConsts::infiniteRectD) return true; QList<TPointD> points = getAttributes()->getMotionPoints(); /*- 移動した軌跡のバウンディングボックスからマージンを求める -*/ /*- 各軌跡点の座標の絶対値の最大値を得る -*/ /*- 上下左右のマージンを得る -*/ double minX = 0.0; double maxX = 0.0; double minY = 0.0; double maxY = 0.0; for (int p = 0; p < points.size(); p++) { if (points.at(p).x > maxX) maxX = points.at(p).x; if (points.at(p).x < minX) minX = points.at(p).x; if (points.at(p).y > maxY) maxY = points.at(p).y; if (points.at(p).y < minY) minY = points.at(p).y; } int marginLeft = (int)ceil(abs(minX)); int marginRight = (int)ceil(abs(maxX)); int marginTop = (int)ceil(abs(maxY)); int marginBottom = (int)ceil(abs(minY)); TRectD enlargedBBox( bBox.x0 - (double)marginLeft, bBox.y0 - (double)marginBottom, bBox.x1 + (double)marginRight, bBox.y1 + (double)marginTop); bBox = enlargedBBox; return ret; }
bool TGeometryFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { TRasterFxPort *input = dynamic_cast<TRasterFxPort *>(getInputPort(0)); assert(input); if (input->isConnected()) { TRasterFxP fx = input->getFx(); assert(fx); bool ret = fx->doGetBBox(frame, bBox, info); if (getActiveTimeRegion().contains(frame)) bBox = getPlacement(frame) * bBox; return ret; } else { bBox = TRectD(); return false; } return true; };
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { if (m_warped.isConnected()) { int ret = m_warped->doGetBBox(frame, bBox, info); if (ret && !bBox.isEmpty()) { if (bBox != TConsts::infiniteRectD) { WarpParams params; params.m_intensity = m_intensity->getValue(frame); bBox = bBox.enlarge(getWarpRadius(params)); } return true; } } bBox = TRectD(); return false; }
bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &rs) { TRectD up_bx; const bool up_sw = (m_up.isConnected() ? m_up->doGetBBox(frame, up_bx, rs) : false); TRectD dn_bx; const bool dn_sw = (m_down.isConnected() ? m_down->doGetBBox(frame, dn_bx, rs) : false); if (up_sw && dn_sw) { bBox = up_bx + dn_bx; return !bBox.isEmpty(); } else if (up_sw) { bBox = up_bx; return true; } else if (dn_sw) { bBox = dn_bx; return true; } else { bBox = TRectD(); return false; } }
/*! rgb picking */ void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) { if (!m_isHistogramEnable) return; if (!m_histogramPopup->isVisible()) return; QPoint curPos = event->pos() * getDevPixRatio(); // avoid to pick outside of the flip if ((!m_image) || !rect().contains(curPos)) { // throw transparent color m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1)); return; } StylePicker picker(m_image); TPoint mousePos = TPoint(curPos.x(), height() - 1 - curPos.y()); TRectD area = TRectD(mousePos.x, mousePos.y, mousePos.x, mousePos.y); if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->bind(); const TPixel32 pix = picker.pickColor(area); if (m_lutCalibrator && m_lutCalibrator->isValid()) m_fbo->release(); QPoint viewP = mapFrom(this, curPos); TPointD pos = getViewAff().inv() * TPointD(viewP.x() - width() / 2, -viewP.y() + height() / 2); TPointD imagePos = TPointD(0.5 * m_image->getBBox().getLx() + pos.x, 0.5 * m_image->getBBox().getLy() + pos.y); if (m_image->getBBox().contains(imagePos)) { // throw the picked color to the histogram m_histogramPopup->updateInfo(pix, imagePos); // throw it to the style editor as well if (putValueToStyleEditor) setPickedColorToStyleEditor(pix); } else { // throw transparent color if picking outside of the image m_histogramPopup->updateInfo(TPixel32::Transparent, TPointD(-1, -1)); } }
bool TExternalProgramFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { // bBox = TRectD(-30,-30,30,30); // return true; std::map<std::string, Port>::const_iterator portIt; for (portIt = m_ports.begin(); portIt != m_ports.end(); ++portIt) { if (portIt->second.m_port != 0) { TRasterFxPort *tmp; tmp = portIt->second.m_port; if (tmp->isConnected()) { TRectD tmpbBox; (*tmp)->doGetBBox(frame, tmpbBox, info); bBox += tmpbBox; } } } if (bBox.isEmpty()) { bBox = TRectD(); return false; } else return true; /* if(m_input1.isConnected() || m_input2.isConnected()) { bool ret = m_input1->doGetBBox(frame, bBox) || m_input1->doGetBBox(frame, bBox); return ret; } else { bBox = TRectD(); return false; } */ }
//!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 doCompute(TTile &tile, double frame, const TRenderSettings &info) { 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 evolution = m_evol->getValue(frame); double size = 100.0 / info.m_shrinkX; TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame)); //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(1, TPixel32::Black)}; TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors); //Build the warper warperInfo.m_affine = warperInfo.m_affine; TAffine aff = warperInfo.m_affine.inv(); TTile warperTile; TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); warperTile.m_pos = warperComputeRect.getP00(); warperTile.setRaster(rasWarper); { TRenderSettings info2(warperInfo); //Now, separate the part of the affine the Fx can handle from the rest. TAffine fxHandledAffine = handledAffine(warperInfo, frame); info2.m_affine = fxHandledAffine; TAffine aff = warperInfo.m_affine * fxHandledAffine.inv(); aff.a13 /= warperInfo.m_shrinkX; aff.a23 /= warperInfo.m_shrinkY; TRectD rectIn = aff.inv() * warperComputeRect; //rectIn = rectIn.enlarge(getResampleFilterRadius(info)); //Needed to counter the resample filter TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1, tceil(rectIn.y1) - 1); // rasIn e' un raster dello stesso tipo di tile.getRaster() TTile auxtile(warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()), convert(rectInI.getP00())); TPointD mypos(auxtile.m_pos - pos); double scale2 = sqrt(fabs(info2.m_affine.det())); doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0, 1.0, PNOISE_CLOUDS, scale2, frame); info2.m_affine = aff; TRasterFx::applyAffine(warperTile, auxtile, info2); } //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 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); }
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame, const TRenderSettings &ri, TPointD p00, TPointD p01, TPointD p11, TPointD p10, int details, bool wireframe, TDimension m_offScreenSize, bool isCast) { TPixel32 bgColor; TRectD outBBox, inBBox; outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); m_input->getBBox(frame, inBBox, ri); if (inBBox == TConsts::infiniteRectD) // e' uno zerario inBBox = outBBox; int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX; int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY; if (inBBox.isEmpty()) return; if (p00 == p01 && p00 == p10 && p00 == p11 && !isCast) // significa che non c'e' deformazione { m_input->compute(tile, frame, ri); return; } TRaster32P rasIn; TPointD rasInPos; if (!wireframe) { if (ri.m_bpp == 64 || ri.m_bpp == 48) { TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy); rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(aux, rasInPos); m_input->compute(tmp, frame, ri); rasIn = TRaster32P(inBBoxLx, inBBoxLy); TRop::convert(rasIn, aux); } else { rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos); m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy), TRaster32P(), frame, ri); rasIn = tmp.getRaster(); } } unsigned int texWidth = 2; unsigned int texHeight = 2; while (texWidth < (unsigned int)inBBoxLx) texWidth = texWidth << 1; while (texHeight < (unsigned int)inBBoxLy) texHeight = texHeight << 1; while (texWidth > 1024 || texHeight > 1024) // avevo usato la costante // GL_MAX_TEXTURE_SIZE invece di // 1024, ma non funzionava! { inBBoxLx = inBBoxLx >> 1; inBBoxLy = inBBoxLy >> 1; texWidth = texWidth >> 1; texHeight = texHeight >> 1; } if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) { TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy); TRop::resample(rasOut, rasIn, TScale((double)rasOut->getLx() / rasIn->getLx(), (double)rasOut->getLy() / rasIn->getLy())); rasIn = rasOut; } int rasterWidth = tile.getRaster()->getLx() + 2; int rasterHeight = tile.getRaster()->getLy() + 2; assert(rasterWidth > 0); assert(rasterHeight > 0); TRectD clippingRect = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); #if CREATE_GL_CONTEXT_ONE_TIME int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC); assert(ret == TRUE); #else TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight)); //#ifdef _WIN32 offScreenRendering.makeCurrent(); //#else //#if defined(LINUX) || defined(MACOSX) // offScreenRendering.m_offlineGL->makeCurrent(); //#endif #endif checkErrorsByGL // disabilito quello che non mi serve per le texture glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_DITHER); glDisable(GL_DEPTH_TEST); glCullFace(GL_FRONT); glDisable(GL_STENCIL_TEST); glDisable(GL_LOGIC_OP); // creo la texture in base all'immagine originale glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); checkErrorsByGL #if !CREATE_GL_CONTEXT_ONE_TIME TRaster32P rasaux; if (!wireframe) { TRaster32P texture(texWidth, texHeight); texture->clear(); rasaux = texture; rasaux->lock(); texture->copy(rasIn); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getRawData()); } #else unsigned int texWidth = 1024; unsigned int texHeight = 1024; rasaux = rasIn; rasaux->lock(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasIn->getLx(), rasIn->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, rasIn->getRawData()); #endif checkErrorsByGL glEnable(GL_TEXTURE_2D); // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5, rasterHeight * 0.5, -1, 1); glViewport(0, 0, rasterWidth, rasterHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // do OpenGL draw double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1); double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1); TPointD tex00 = TPointD(0.0, 0.0); TPointD tex10 = TPointD(lwTex, 0.0); TPointD tex11 = TPointD(lwTex, lhTex); TPointD tex01 = TPointD(0.0, lhTex); GLenum polygonStyle; if (wireframe) { polygonStyle = GL_LINE; glDisable(GL_TEXTURE_2D); } else polygonStyle = GL_FILL; checkErrorsByGL p00.x /= ri.m_shrinkX; p00.y /= ri.m_shrinkY; p10.x /= ri.m_shrinkX; p10.y /= ri.m_shrinkY; p11.x /= ri.m_shrinkX; p11.y /= ri.m_shrinkY; p01.x /= ri.m_shrinkX; p01.y /= ri.m_shrinkY; TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5, tile.m_pos.y + tile.getRaster()->getLy() * 0.5); glTranslated(-translate.x, -translate.y, 0.0); // disegno il poligono double dist_p00_p01 = tdistance2(p00, p01); double dist_p10_p11 = tdistance2(p10, p11); double dist_p01_p11 = tdistance2(p01, p11); double dist_p00_p10 = tdistance2(p00, p10); bool vertical = (dist_p00_p01 == dist_p10_p11); bool horizontal = (dist_p00_p10 == dist_p01_p11); if (vertical && horizontal) details = 1; glPolygonMode(GL_FRONT_AND_BACK, polygonStyle); subdivision(p00, p10, p11, p01, tex00, tex10, tex11, tex01, clippingRect, details); if (!wireframe) { // abilito l'antialiasing delle linee glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // disegno il bordo del poligono glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_QUADS); glTexCoord2d(tex00.x, tex00.y); tglVertex(p00); glTexCoord2d(tex10.x, tex10.y); tglVertex(p10); glTexCoord2d(tex11.x, tex11.y); tglVertex(p11); glTexCoord2d(tex01.x, tex01.y); tglVertex(p01); glEnd(); // disabilito l'antialiasing per le linee glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } // force to finish glFlush(); // rimetto il disegno dei poligoni a GL_FILL glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // metto il frame buffer nel raster del tile glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy()); newRas->lock(); glReadPixels(1, 1, newRas->getLx(), newRas->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, (void *)newRas->getRawData()); newRas->unlock(); checkErrorsByGL rasaux->unlock(); tile.getRaster()->copy(newRas); }
void subdivision(const TPointD &p00, const TPointD &p10, const TPointD &p11, const TPointD &p01, const TPointD &tex00, const TPointD &tex10, const TPointD &tex11, const TPointD &tex01, const TRectD &clippingRect, int details) { if (details == 1) { glBegin(GL_QUADS); glTexCoord2d(tex00.x, tex00.y); tglVertex(p00); glTexCoord2d(tex10.x, tex10.y); tglVertex(p10); glTexCoord2d(tex11.x, tex11.y); tglVertex(p11); glTexCoord2d(tex01.x, tex01.y); tglVertex(p01); glEnd(); } else { TPointD A = p00; TPointD B = p10; TPointD C = p11; TPointD D = p01; /* * D L2 C * +----------------+----------------+ * | | | * | | | * | | | * | | | * | | | * H1 +----------------+----------------+ H2 * | | M | * | | | * | | | * | | | * | | | * +----------------+----------------+ * A L1 B * */ TPointD M, L1, L2, H1, H2, P1, P2; bool intersection; // M intersection = lineIntersection(A, C, B, D, M); assert(intersection); // P1 (punto di fuga) intersection = lineIntersection(D, C, A, B, P1); if (!intersection) { P1.x = 0.5 * (A.x + D.x); P1.y = 0.5 * (A.y + D.y); } // H1 intersection = lineIntersection(A, D, P1, M, H1); assert(intersection); // H2 intersection = lineIntersection(B, C, P1, M, H2); assert(intersection); // P2 (punto di fuga) intersection = lineIntersection(A, D, B, C, P2); if (!intersection) { P2.x = 0.5 * (A.x + B.x); P2.y = 0.5 * (A.y + B.y); } // L1 intersection = lineIntersection(A, B, P2, M, L1); assert(intersection); // L2 intersection = lineIntersection(D, C, P2, M, L2); assert(intersection); TPointD texA = (tex00 + tex10) * 0.5; TPointD texB = (tex10 + tex11) * 0.5; TPointD texC = (tex11 + tex01) * 0.5; TPointD texD = (tex01 + tex00) * 0.5; TPointD texM = (texA + texC) * 0.5; details--; TRectD r1 = TRectD( std::min({A.x, L1.x, M.x, H1.x}), std::min({A.y, L1.y, M.y, H1.y}), std::max({A.x, L1.x, M.x, H1.x}), std::max({A.y, L1.y, M.y, H1.y})); TRectD r2 = TRectD( std::min({L1.x, B.x, H2.x, M.x}), std::min({L1.y, B.y, H2.y, M.y}), std::max({L1.x, B.x, H2.x, M.x}), std::max({L1.y, B.y, H2.y, M.y})); TRectD r3 = TRectD( std::min({M.x, H2.x, C.x, L2.x}), std::min({M.y, H2.y, C.y, L2.y}), std::max({M.x, H2.x, C.x, L2.x}), std::max({M.y, H2.y, C.y, L2.y})); TRectD r4 = TRectD( std::min({H1.x, M.x, L2.x, D.x}), std::min({H1.y, M.y, L2.y, D.y}), std::max({H1.x, M.x, L2.x, D.x}), std::max({H1.y, M.y, L2.y, D.y})); if (r1.overlaps(clippingRect)) subdivision(A, L1, M, H1, tex00, texA, texM, texD, clippingRect, details); if (r2.overlaps(clippingRect)) subdivision(L1, B, H2, M, texA, tex10, texB, texM, clippingRect, details); if (r3.overlaps(clippingRect)) subdivision(M, H2, C, L2, texM, texB, tex11, texC, clippingRect, details); if (r4.overlaps(clippingRect)) subdivision(H1, M, L2, D, texD, texM, texC, tex01, clippingRect, details); } }
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); }