void TCacheResource::release2(const TRect &rect) { //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", //"crStack", "release", ::traduce(rect)); if (m_locksCount > 0) return; std::map<PointLess, CellData>::iterator it; for (it = m_cellDatas.begin(); it != m_cellDatas.end();) { if (!it->second.m_referenced) { ++it; continue; } TPoint cellPos(getCellPos(it->first)); TRect cellRect(cellPos, TDimension(latticeStep, latticeStep)); if (isEmpty(cellRect * rect)) { ++it; continue; } QRect cellQRect(toQRect(cellRect)); if (--it->second.m_refsCount <= 0) { releaseCell(cellQRect, it->first, it->second.m_modified); std::map<PointLess, CellData>::iterator jt = it++; m_cellDatas.erase(jt); } else ++it; } }
//! Clears the complex on the specified region. Please observe that the actually cleared region //! consists of all lattice cells intersecting the passed region, therefore resulting in a cleared region //! typically larger than passed one, up to the lattice granularity. void TCacheResource::clear(QRegion region) { if (!m_region.intersects(region)) return; //Get the region bbox TRect bbox(toTRect(region.boundingRect())); //For all cells intersecting the bbox TPoint initialPos(getCellPos(bbox.getP00())); TPoint pos; for (pos.x = initialPos.x; pos.x <= bbox.x1; pos.x += latticeStep) for (pos.y = initialPos.y; pos.y <= bbox.y1; pos.y += latticeStep) { QRect cellQRect(toQRect(TRect(pos, TDimension(latticeStep, latticeStep)))); if (region.intersects(cellQRect) && m_region.intersects(cellQRect)) { //Release the associated cell from cache and clear the cell from the content region. TImageCache::instance()->remove(getCellCacheId(pos)); m_region -= cellQRect; --m_cellsCount; //DIAGNOSTICS_GLOADD("crCellsCnt", -1); //Release the cell from m_cellDatas m_cellDatas[getCellIndex(pos)].m_modified = true; } } if (m_region.isEmpty()) { m_tileType = NONE; m_locksCount = 0; } }
//! Copies the passed tile in the tile complex. The passed tile \b must //! possess integer geometry (ie tile.m_pos must have integer coordinates), //! otherwise this function is a no-op. bool TCacheResource::upload(const TPoint &pos, TRasterP ras) { int tileType; if (!checkRasterType(ras, tileType)) return false; if (m_tileType == NONE) m_tileType = tileType; //For all cells of the lattice which intersect the tile, upload the content in the //complex TRect tileRect(ras->getBounds() + pos); TPoint initialPos(getCellPos(tileRect.getP00())); //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", //"crStack", "upload", ::traduce(TRect(pos, ras->getSize()))); TPoint currPos; for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { //Copy tile's content into the cell's raster. TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); TRect overlapRect(tileRect * cellRect); assert(!overlapRect.isEmpty()); PointLess cellIndex(getCellIndex(currPos)); std::pair<TRasterP, CellData *> cellInfos(touch(cellIndex)); TRasterP cellRas(cellInfos.first); TRect temp(overlapRect - currPos); TRasterP overlappingCellRas(cellRas->extract(temp)); temp = TRect(overlapRect - tileRect.getP00()); TRasterP overlappingTileRas(ras->extract(temp)); assert(overlappingCellRas->getBounds() == overlappingTileRas->getBounds()); TRop::copy(overlappingCellRas, overlappingTileRas); cellInfos.second->m_modified = true; } //Update the complex's content region m_region += toQRect(tileRect); return true; }
TDimension Ffmpeg::getSize() { QStringList sizeArgs; sizeArgs << "-v"; sizeArgs << "error"; sizeArgs << "-of"; sizeArgs << "flat=s=_"; sizeArgs << "-select_streams"; sizeArgs << "v:0"; sizeArgs << "-show_entries"; sizeArgs << "stream=height,width"; sizeArgs << m_path.getQString(); QString sizeResults = runFfprobe(sizeArgs); QStringList split = sizeResults.split("\n"); m_lx = split[0].split("=")[1].toInt(); m_ly = split[1].split("=")[1].toInt(); return TDimension(m_lx, m_ly); }
bool TCacheResource::downloadAll(const TPoint &pos, TRasterP ras) { int tileType; if (!checkRasterType(ras, tileType)) return false; //Build the tile's rect TRect tileRect(ras->getBounds() + pos); if (!contains(m_region, tileRect)) return false; //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", //"crStack", "downloadAll", ::traduce(TRect(pos, ras->getSize()))); //For all cells intersecting the tile's rect, copy all those intersecting the //complex's content region. TPoint initialPos(getCellPos(tileRect.getP00())); TPoint currPos; for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); TRect overlapRect(tileRect * cellRect); assert(!overlapRect.isEmpty()); QRect overlapQRect(toQRect(overlapRect)); if (m_region.intersects(overlapQRect)) { //Extract the associated rasters and perform the copy to the input tile. std::pair<TRasterP, CellData *> cellInfos(touch(getCellIndex(currPos))); TRasterP cellRas(cellInfos.first); TRect temp(overlapRect - currPos); TRasterP overlappingCellRas(cellRas->extract(temp)); temp = TRect(overlapRect - tileRect.getP00()); TRasterP overlappingTileRas(ras->extract(temp)); TRop::copy(overlappingTileRas, overlappingCellRas); } } return true; }
//! Fills the passed tile with the data contained in the complex, returning //! the copied region. //! The same restriction of the upload() method applies here. QRegion TCacheResource::download(const TPoint &pos, TRasterP ras) { int tileType; if (!checkRasterType(ras, tileType)) return QRegion(); //Build the tile's rect TRect tileRect(ras->getBounds() + pos); if (!m_region.intersects(toQRect(tileRect))) return QRegion(); //For all cells intersecting the tile's rect, copy all those intersecting the //complex's content region. TPoint initialPos(getCellPos(tileRect.getP00())); TPoint currPos; for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); TRect overlapRect(tileRect * cellRect); assert(!overlapRect.isEmpty()); QRect overlapQRect(toQRect(overlapRect)); if (m_region.intersects(overlapQRect)) { //Extract the associated rasters and perform the copy to the input tile. std::pair<TRasterP, CellData *> cellInfos(touch(getCellIndex(currPos))); TRasterP cellRas(cellInfos.first); TRect temp(overlapRect - currPos); TRasterP overlappingCellRas(cellRas->extract(temp)); temp = TRect(overlapRect - tileRect.getP00()); TRasterP overlappingTileRas(ras->extract(temp)); TRop::copy(overlappingTileRas, overlappingCellRas); } } return m_region.intersected(QRegion(toQRect(tileRect))); }
void CameraTestTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) { // Reset full commit status - invokes preview rebuild on its own. CleanupSettingsModel::instance()->setCommitMask( CleanupSettingsModel::FULLPROCESS); CleanupParameters *cp = CleanupSettingsModel::instance()->getCurrentParameters(); /*-- カメラ位置移動のUndo --*/ if (m_scaling == eNoScale) { /*-- 値が変わったらUndoを登録 --*/ if (m_firstCameraOffset.x != cp->m_offx || m_firstCameraOffset.y != cp->m_offy) { UndoCameraTestMove *undo = new UndoCameraTestMove( m_firstCameraOffset, TPointD(cp->m_offx, cp->m_offy), cp); TUndoManager::manager()->add(undo); } } /*-- サイズ変更のUndo --*/ else { if (m_firstSize.lx != cp->m_camera.getSize().lx || m_firstSize.ly != cp->m_camera.getSize().ly) { UndoCameraTestScale *undo = new UndoCameraTestScale( m_firstRes, m_firstSize, cp->m_camera.getRes(), cp->m_camera.getSize(), cp); TUndoManager::manager()->add(undo); } } m_firstPos = TPointD(-1, -1); m_firstCameraOffset = TPointD(0, 0); m_firstRes = TDimension(0, 0); m_firstSize = TDimensionD(0, 0); m_lastPos = TPointD(-1, -1); m_dragged = false; }
/*- 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 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 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); }
bool Convert2Tlv::init(std::string &errorMessage) { m_lastIndex = m_maxPaletteIndex = 0; m_colorMap.clear(); try { m_lr1 = TLevelReaderP(m_levelIn1); if (m_lr1) m_level1 = m_lr1->loadInfo(); } catch (...) { errorMessage = "Error: can't read level " + toString(m_levelIn1.getWideString()); return false; } if (m_level1->getFrameCount() == 0) { errorMessage = "Error: can't find level " + toString(m_levelIn1.getWideString()); return false; } TLevelP level2; if (m_levelIn2 != TFilePath()) { try { m_lr2 = TLevelReaderP(m_levelIn2); if (m_lr2) level2 = m_lr2->loadInfo(); } catch (...) { errorMessage = "Error: can't read level " + toString(m_levelIn2.getWideString()); return false; } if (level2->getFrameCount() == 0) { errorMessage = "Error: can't find level " + toString(m_levelIn2.getWideString()); return false; } if (m_level1->getFrameCount() != level2->getFrameCount()) { errorMessage = "Error: the two input levels must have same frame number"; return false; } } m_size = TDimension(); m_lw = TLevelWriterP(m_levelOut); m_it = m_level1->begin(); TLevel::Iterator it2; if (level2->getFrameCount() > 0) it2 = level2->begin(); for (; m_it != m_level1->end(); ++m_it) { TImageReaderP ir1 = m_lr1->getFrameReader(m_it->first); const TImageInfo *info1 = ir1->getImageInfo(); if (!info1) { errorMessage = "Error: can't read frame " + toString(m_it->first.getNumber()) + " of level " + toString(m_levelIn1.getWideString()); return false; } if (info1->m_bitsPerSample != 8) { errorMessage = "Error: all frames must have 8 bits per channel!\n"; return false; } m_size.lx = tmax(m_size.lx, info1->m_lx); m_size.ly = tmax(m_size.ly, info1->m_ly); if (m_lr2 != TLevelReaderP()) { TImageReaderP ir2 = m_lr2->getFrameReader(it2->first); if (ir2) { const TImageInfo *info2 = ir2->getImageInfo(); if (!info1) { errorMessage = "Error: can't read frame " + toString(it2->first.getNumber()) + " of level " + toString(m_levelIn2.getWideString()); ; return false; } if (info1->m_lx != info2->m_lx || info1->m_ly != info2->m_ly) { errorMessage = "Error: painted frames must have same resolution of matching unpainted frames!\n"; return false; } if (info2->m_bitsPerSample != 8) { errorMessage = "Error: all frames must have 8 bits per channel!\n"; return false; } } ++it2; } } m_palette = new TPalette(); if (m_palettePath != TFilePath()) { TIStream is(m_palettePath); is >> m_palette; if (m_palette->getStyleInPagesCount() == 0) { errorMessage = "Error: invalid palette!\n"; return false; } for (int i = 0; i < m_palette->getStyleCount(); i++) if (m_palette->getStylePage(i)) { m_colorMap[m_palette->getStyle(i)->getMainColor()] = i; if (i > m_lastIndex) m_lastIndex = i; } assert(m_colorMap.size() == m_palette->getStyleInPagesCount()); }
TImageP TImageReader::load0() { if (!m_reader && !m_vectorReader) open(); if (m_reader) { TImageInfo info = m_reader->getImageInfo(); if (info.m_lx <= 0 || info.m_ly <= 0) return TImageP(); // Initialize raster info assert(m_shrink > 0); // Build loading rect int x0 = 0; int x1 = info.m_lx - 1; int y0 = 0; int y1 = info.m_ly - 1; if (!m_region.isEmpty()) { // Intersect with the externally specified loading region x0 = tmax(x0, m_region.x0); y0 = tmax(y0, m_region.y0); x1 = tmin(x1, m_region.x1); y1 = tmin(y1, m_region.y1); if (x0 >= x1 || y0 >= y1) return TImageP(); } if (m_shrink > 1) { // Crop to shrink multiples x1 -= (x1 - x0) % m_shrink; y1 -= (y1 - y0) % m_shrink; } assert(x0 <= x1 && y0 <= y1); TDimension imageDimension = TDimension((x1 - x0) / m_shrink + 1, (y1 - y0) / m_shrink + 1); if (m_path.getType() == "tzp" || m_path.getType() == "tzu") { // Colormap case TRasterCM32P ras(imageDimension); readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); // Build the savebox TRect saveBox(info.m_x0, info.m_y0, info.m_x1, info.m_y1); if (!m_region.isEmpty()) { // Intersect with the loading rect if (m_region.overlaps(saveBox)) { saveBox *= m_region; int sbx0 = saveBox.x0 - m_region.x0; int sby0 = saveBox.y0 - m_region.y0; int sbx1 = sbx0 + saveBox.getLx() - 1; int sby1 = sby0 + saveBox.getLy() - 1; assert(sbx0 >= 0); assert(sby0 >= 0); assert(sbx1 >= 0); assert(sby1 >= 0); saveBox = TRect(sbx0, sby0, sbx1, sby1); } else saveBox = TRect(0, 0, 1, 1); } if (m_shrink > 1) { saveBox.x0 = saveBox.x0 / m_shrink; saveBox.y0 = saveBox.y0 / m_shrink; saveBox.x1 = saveBox.x1 / m_shrink; saveBox.y1 = saveBox.y1 / m_shrink; } TToonzImageP ti(ras, ras->getBounds() * saveBox); ti->setDpi(info.m_dpix, info.m_dpiy); return ti; } else if (info.m_bitsPerSample >= 8) { // Common byte-based rasters (see below, we have black-and-white bit-based images too) if (info.m_samplePerPixel == 1 && m_readGreytones) { // Greymap case // NOTE: Uses a full 32-bit raster first, and then copies down to the GR8 // Observe that GR16 file images get immediately down-cast to GR8... // Should we implement that too? TRasterGR8P ras(imageDimension); readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); TRasterImageP ri(ras); ri->setDpi(info.m_dpix, info.m_dpiy); return ri; } // assert(info.m_samplePerPixel == 3 || info.m_samplePerPixel == 4); TRasterP _ras; if (info.m_bitsPerSample == 16) { if (m_is64BitEnabled || m_path.getType() != "tif") { // Standard 64-bit case. // Also covers down-casting to 32-bit from a 64-bit image file whenever // not a tif file (see below). TRaster64P ras(imageDimension); readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); _ras = ras; } else { // The Tif reader has got an automatically down-casting readLine(char*, ...) // in case the input file is 64-bit. The advantage is that no intermediate // 64-bit raster is required in this case. TRaster32P ras(imageDimension); readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); _ras = ras; } } else if (info.m_bitsPerSample == 8) { // Standard 32-bit case TRaster32P ras(imageDimension); readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); _ras = ras; } else throw TImageException(m_path, "Image format not supported"); // 64-bit to 32-bit conversions if necessary (64 bit images not allowed) if (!m_is64BitEnabled && (TRaster64P)_ras) { TRaster32P raux(_ras->getLx(), _ras->getLy()); TRop::convert(raux, _ras); _ras = raux; } // Return the image TRasterImageP ri(_ras); ri->setDpi(info.m_dpix, info.m_dpiy); return ri; } else if (info.m_samplePerPixel == 1 && info.m_valid == true) { // Previously dubbed as 'Palette cases'. No clue about what is this... :| TRaster32P ras(imageDimension); readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); TRasterImageP ri(ras); ri->setDpi(info.m_dpix, info.m_dpiy); return ri; } else if (info.m_samplePerPixel == 1 && m_readGreytones) { // Black-and-White case, I guess. Standard greymaps were considered above... TRasterGR8P ras(imageDimension); readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); TRasterImageP ri(ras); ri->setDpi(info.m_dpix, info.m_dpiy); if (info.m_bitsPerSample == 1) // I suspect this always evaluates true... ri->setScanBWFlag(true); return ri; } else return TImageP(); } else if (m_vectorReader) { TVectorImage *vi = m_vectorReader->read(); return TVectorImageP(vi); } else return TImageP(); }
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); }
TImageP ImageRasterizer::build(int imFlags, void *extData) { assert(!(imFlags & ~(ImageManager::dontPutInCache | ImageManager::forceRebuild))); TDimension d(10, 10); TPoint off(0, 0); // Fetch image assert(extData); ImageLoader::BuildExtData *data = (ImageLoader::BuildExtData *)extData; const std::string &srcImgId = data->m_sl->getImageId(data->m_fid); TImageP img = ImageManager::instance()->getImage(srcImgId, imFlags, extData); if (img) { TVectorImageP vi = img; if (vi) { TRectD bbox = vi->getBBox(); d = TDimension(tceil(bbox.getLx()) + 1, tceil(bbox.getLy()) + 1); off = TPoint((int)bbox.x0, (int)bbox.y0); TPalette *vpalette = vi->getPalette(); TVectorRenderData rd(TTranslation(-off.x, -off.y), TRect(TPoint(0, 0), d), vpalette, 0, true, true); TGlContext oldContext = tglGetCurrentContext(); // this is too slow. { QSurfaceFormat format; format.setProfile(QSurfaceFormat::CompatibilityProfile); TRaster32P ras(d); glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_MODELVIEW), glPushMatrix(); glMatrixMode(GL_PROJECTION), glPushMatrix(); { std::unique_ptr<QOpenGLFramebufferObject> fb(new QOpenGLFramebufferObject(d.lx, d.ly)); fb->bind(); assert(glGetError() == 0); glViewport(0, 0, d.lx, d.ly); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, d.lx, 0, d.ly); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.375, 0.375, 0.0); assert(glGetError() == 0); tglDraw(rd, vi.getPointer()); assert(glGetError() == 0); assert(glGetError() == 0); glFlush(); assert(glGetError() == 0); QImage img = fb->toImage().scaled(QSize(d.lx, d.ly), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); int wrap = ras->getLx() * sizeof(TPixel32); uchar *srcPix = img.bits(); uchar *dstPix = ras->getRawData() + wrap * (d.ly - 1); for (int y = 0; y < d.ly; y++) { memcpy(dstPix, srcPix, wrap); dstPix -= wrap; srcPix += wrap; } fb->release(); } glMatrixMode(GL_MODELVIEW), glPopMatrix(); glMatrixMode(GL_PROJECTION), glPopMatrix(); glPopAttrib(); tglMakeCurrent(oldContext); TRasterImageP ri = TRasterImageP(ras); ri->setOffset(off + ras->getCenter()); return ri; } } } // Error case: return a dummy image (is it really required?) TRaster32P ras(d); ras->fill(TPixel32(127, 0, 127, 127)); return TRasterImageP(ras); }