void FunctionToolbar::setFrame(double frame) { m_frameNavigator->setFrame(tround(frame), false); if (m_curve) m_valueFld->setValue(m_curve->getValue(frame)); else m_valueFld->setValue(0); }
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; }
TPoint StylePicker::getRasterPoint(const TPointD &p) const { if (TToonzImageP ti = m_image) { // DpiScale dpiScale(ti); TDimension size = ti->getSize(); return TPoint(tround(0.5 * size.lx + p.x), /// dpiScale.getSx()), tround(0.5 * size.ly + p.y)); /// dpiScale.getSy())); } else if (TRasterImageP ri = m_image) { // DpiScale dpiScale(ri); TDimension size = ri->getRaster()->getSize(); return TPoint(tround(0.5 * size.lx + p.x), // /dpiScale.getSx()), tround(0.5 * size.ly + p.y)); // /dpiScale.getSy())); } else return TPoint(tround(p.x), tround(p.y)); }
// Builds the specified number of samples count, inside the specified distance // from the origin. If the pattern is radial, paths to the samples points are // calculated. BlurPattern::BlurPattern(double distance, unsigned int samplesCount, bool radial) { const double randFactor = 2.0 * distance / RAND_MAX; m_samples.resize(samplesCount); // Build the samples unsigned int i; for (i = 0; i < samplesCount; ++i) { // NOTE: The following method ensures a perfectly flat probability // distribution. TPoint candidatePoint(tround(rand() * randFactor - distance), tround(rand() * randFactor - distance)); double distanceSq = sq(distance); while (sq(candidatePoint.x) + sq(candidatePoint.y) > distanceSq) candidatePoint = TPoint(tround(rand() * randFactor - distance), tround(rand() * randFactor - distance)); m_samples[i] = candidatePoint; } m_samplePaths.resize(samplesCount); // If necessary, build the paths if (radial) { for (i = 0; i < samplesCount; ++i) { TPoint &sample = m_samples[i]; int l = std::max(abs(sample.x), abs(sample.y)); m_samplePaths[i].reserve(l); double dx = sample.x / (double)l; double dy = sample.y / (double)l; double x, y; int j; for (j = 0, x = dx, y = dy; j < l; x += dx, y += dy, ++j) m_samplePaths[i].push_back(TPoint(tround(x), tround(y))); } } }
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()); }
void TRop::brush( TRaster32P ras, const TPoint &aa, const TPoint &bb, int radius, const TPixel32 &col) { TPoint a = aa; TPoint b = bb; if (a.y > b.y) tswap(a, b); // a e' piu' in basso di b int lx = ras->getLx(); int ly = ras->getLy(); ras->lock(); // ----- radius = 0 if (radius == 0) { // k = +1/-1 se il rettangolo e' inclinato positivamente (0<=m)/negativamente (m<0) // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle // coordinate "di schermo") int k = 1; int dy = b.y - a.y; int dx = b.x - a.x; if (dx < 0) { dx = -dx; k = -1; } assert(dx >= 0); assert(dy >= 0); double m; // m sara' definita solo per dx!=0) if (dx > 0) { m = dy / (double)dx; } //double length = sqrt(dx*dx + dy*dy); const int alpha = dy, beta = -dx; const int incE = alpha; const int incNE = alpha + beta; const int incN = beta; // N.B. le coordinate sono relative ad un sist. di rif. con l'origine in a // l'eq. della retta e' alpha * x + beta * y = 0 int yMin = tmax(a.y, 0) - a.y; // clipping y + cambio riferimento int yMax = tmin(b.y, ly - 1) - a.y; // (trasporto dell'origine in a) if (dx > 0 && m <= 1) { // midpoint algorithm TPoint segm; if (dy == 0) // segmento orizzontale: inizializza segm { segm.x = 0; segm.y = yMin; } else // 0<m<=1 : inizializza segm { segm.x = tceil((yMin - 0.5) / m); segm.y = yMin; } int dSegm = tfloor(alpha * (segm.x + 1) + beta * (segm.y + 0.5)); while (segm.y <= yMax) { int count = 0; // i trati orizzontali di segm vengono disegnati in "blocco" while (dSegm < 0 && segm.x <= dx) // Est: segm.x<=dx evita il ciclo { // infinito quando m=0 (incE=0) dSegm = dSegm + incE; segm.x++; count++; } // NordEst int xMin, xMax; if (k > 0) { xMin = tmax(a.x + segm.x - count, a.x, 0); // clipping x + ritorno alle xMax = tmin(a.x + segm.x, b.x, lx - 1); // coordinate "di schermo" } else { xMin = tmax(a.x - segm.x, a.x - dx, 0); // clipping x + riflessione + ritorno xMax = tmin(a.x - segm.x + count, a.x, lx - 1); // alle coordinate "di schermo" } TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; dSegm = dSegm + incNE; segm.x++; segm.y++; } } else // m>1 oppure segmento verticale { // midpoint algorithm TPoint segm; if (dx == 0) // segmento verticale: inizializza segm { segm.x = 0; segm.y = yMin; } else // m>1 : inizializza segm { segm.x = tround(yMin / m); segm.y = yMin; } int dSegm = tfloor(alpha * (segm.x + 0.5) + beta * (segm.y + 1)); while (segm.y <= yMax) { int xMin, xMax; if (k > 0) { xMin = tmax(a.x + segm.x, 0); // clipping x + ritorno alle xMax = tmin(a.x + segm.x, lx - 1); // coordinate "di schermo" } else { xMin = tmax(a.x - segm.x, 0); // clipping x + riflessione + ritorno xMax = tmin(a.x - segm.x, lx - 1); // alle coordinate "di schermo" } TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; if (dSegm <= 0) // NordEst { dSegm = dSegm + incNE; segm.x++; } else // Nord { dSegm = dSegm + incN; } segm.y++; } } ras->unlock(); return; } HalfCord halfCord(radius); int x, y; // ----- punti iniziali coincidenti: disegna un cerchio if (a == b) { int yMin = tmax(a.y - radius, 0); // clipping y int yMax = tmin(a.y + radius, ly - 1); // clipping y for (y = yMin; y <= yMax; y++) { int deltay = abs(y - a.y); int xMin = tmax(a.x - halfCord.getCord(deltay), 0); // clipping x int xMax = tmin(a.x + halfCord.getCord(deltay), lx - 1); // clipping x TPixel32 *p = ras->pixels(y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; } ras->unlock(); return; } // ----- rettangolo orizzontale (a.y = b.y, a.x != b.x) if (a.y == b.y) { int yMin = tmax((a.y - radius), 0); // clipping y int yMax = tmin((a.y + radius), ly - 1); // clipping y int xLeft = tmin(a.x, b.x); int xRight = tmax(a.x, b.x); for (y = yMin; y <= yMax; y++) { int deltay = abs(y - a.y); int xMin = tmax(xLeft - halfCord.getCord(deltay), 0); // clipping x int xMax = tmin(xRight + halfCord.getCord(deltay), lx - 1); // clipping x TPixel32 *p = ras->pixels(y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; } ras->unlock(); return; } // ----- rettangolo verticale (a.x = b.x, a.y != b.y) if (a.x == b.x) { int xMin = tmax(a.x - radius, 0); // clipping x int xMax = tmin(a.x + radius, lx - 1); // clipping x for (x = xMin; x <= xMax; x++) { int deltax = abs(x - a.x); int yMin = tmax(a.y - halfCord.getCord(deltax), 0); // clipping y int yMax = tmin(b.y + halfCord.getCord(deltax), ly - 1); // clipping y if (yMin <= yMax) { TPixel32 *p = ras->pixels(yMin) + x; TPixel32 *q = ras->pixels(yMax) + x; int wrap = ras->getWrap(); while (p <= q) { *p = col; p += wrap; } } } ras->unlock(); return; } // ----- rettangolo inclinato // k = +1/-1 se il rettangolo e' inclinato positivamente/negativamente int k = 1; int dx = b.x - a.x; if (dx < 0) { dx = -dx; k = -1; } int dy = b.y - a.y; assert(dx > 0); assert(dy > 0); double length = sqrt((double)(dx * dx + dy * dy)); const double m = dy / (double)dx; //punto di tangenza superiore nel sistema di riferimento del cerchio TPointD up(-radius * dy / length, radius * dx / length); //semi-ampiezza orizzontale delle "calotte" circolari int halfAmplCap = tfloor(-up.x); // A meno di intersezioni relative tra le diverse zone: // le scanline della "calotta" circolare superiore sono (b.y+cutExt,b.y+radius] // le scanline del trapezoide circolare superiore sono [b.y-cutIn,b.y+cutExt] // le scanline del parallelogramma sono (a.y+cutIn,b.y-cutIn) // le scanline del trapezoide circolare inferiore sono [a.y-cutExt,a.y+cutIn] // le scanline della "calotta" circolare inferiore sono [a.y-radius,a.y-cutExt) int cutExt, cutIn; // vertici del parallelogramma TPointD rightUp; TPointD rightDown; TPointD leftUp; TPointD leftDown; double mParall; //coeff. angolare parallelogramma // NOTA BENE: halfAmplCap=0 <=> (radius=0 (caso a parte) , 1) if (radius > 1) { for (cutExt = radius; cutExt >= 0 && halfCord.getCord(cutExt) <= halfAmplCap; cutExt--) ; cutIn = cutExt; // vedi else successivo rightUp.x = dx + halfCord.getCord(cutIn); rightUp.y = dy - cutIn; rightDown.x = halfCord.getCord(cutIn); rightDown.y = -cutIn; leftUp.x = dx - halfCord.getCord(cutIn); leftUp.y = dy + cutIn; leftDown.x = -halfCord.getCord(cutIn); leftDown.y = cutIn; mParall = dy / (double)dx; } else // N.B. cutExt != cutIn solo quando radius=1 { cutExt = radius; // radius=1 => halfAmplCap=0 (non ci sono mai le "calotte" circolari) cutIn = 0; // anche per radius=1 il limite "interno" dei trapezoidi circolari e' < radius rightUp.x = dx - up.x; rightUp.y = dy - up.y; rightDown.x = -up.x; rightDown.y = -up.y; leftUp.x = dx + up.x; leftUp.y = dy + up.y; leftDown.x = up.x; leftDown.y = up.y; mParall = m; } // ----- riempie "calotte" circolari // ----- riempie "calotta" circolare inferiore int yMin = tmax(a.y - radius, 0); // clipping y int yMax = tmin(a.y - cutExt - 1, ly - 1); // clipping y for (y = yMin; y <= yMax; y++) { int r = halfCord.getCord(a.y - y); int xMin = tmax(a.x - r, 0); // clipping x int xMax = tmin(a.x + r, lx - 1); // clipping x TPixel32 *p = ras->pixels(y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; } // ----- riempie "calotta" circolare superiore yMin = tmax(b.y + cutExt + 1, 0); // clipping y yMax = tmin(b.y + radius, ly - 1); // clipping y for (y = yMin; y <= yMax; y++) { int r = halfCord.getCord(y - b.y); int xMin = tmax(b.x - r, 0); // clipping x int xMax = tmin(b.x + r, lx - 1); // clipping x TPixel32 *p = ras->pixels(y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; } // ----- riempie trapezoidi // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle // coordinate "di schermo") // limite destro assoluto delle scanline trapezoide: int xSegmMax = tround(dx - up.x); // coordinata x del punto di tangenza inferiore sul cerchio superiore // limite sinistro assoluto delle scanline: int xSegmMin = tround(up.x); // coordinata x del punto di tangenza superiore sul cerchio inferiore // ----- riempie trapezoide inferiore // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro // del cerchio inferiore yMin = tmax(a.y - cutExt, 0) - a.y; // clipping y yMax = tmin(a.y + cutIn, b.y - cutIn - 1, ly - 1) - a.y; // clipping y // l'eq. della retta e' alpha * x + beta * y + gammaRight = 0 const int alpha = dy, beta = -dx; const double gammaRight = rightDown.y * dx - rightDown.x * dy; const int incE = alpha; const int incNE = alpha + beta; const int incN = beta; if (m <= 1) { // midpoint algorithm; le scanline vengono disegnate solo // sul NordEst. L'ultima scanline non viene disegnata TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight); while (segmRight.y <= yMax) { if (dSegmRight < 0) // Est { dSegmRight = dSegmRight + incE; segmRight.x++; } else // NordEst { int xMin, xMax; if (k > 0) { xMin = tmax(a.x - halfCord.getCord(abs(segmRight.y)), 0); // clipping x xMax = tmin(a.x + tmin(segmRight.x, xSegmMax), lx - 1); // clipping x } else { xMin = tmax(a.x - tmin(segmRight.x, xSegmMax), 0); // clipping x + ritorno alle xMax = tmin(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; dSegmRight = dSegmRight + incNE; segmRight.x++; segmRight.y++; } } } else // m>1 { // midpoint algorithm; le scanline vengono disegnate sempre TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin); int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight); while (segmRight.y <= yMax) { int xMin, xMax; if (k > 0) { xMin = tmax(a.x - halfCord.getCord(abs(segmRight.y)), 0); // clipping x xMax = tmin(a.x + segmRight.x, lx - 1); // clipping x } else { xMin = tmax(a.x - segmRight.x, 0); // clipping x + ritorno alle coordinate xMax = tmin(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); // "di schermo" } TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; if (dSegmRight <= 0) // NordEst { dSegmRight = dSegmRight + incNE; segmRight.x++; } else // Nord { dSegmRight = dSegmRight + incN; } segmRight.y++; } } // ----- riempie trapezoide superiore // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro // del cerchio superiore yMin = tmax(b.y - cutIn, a.y + cutIn + 1, 0) - b.y; // clipping y yMax = tmin(b.y + cutExt, ly - 1) - b.y; // clipping y // l'eq. della retta e' alpha * x + beta * y + gammaLeft = 0 const double gammaLeft = leftDown.y * dx - leftDown.x * dy; if (m <= 1) { // midpoint algorithm; le scanline vengono disegnate solo // sul NordEst. L'ultima scanline non viene disegnata TPoint segmLeft(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin); int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft); while (segmLeft.y <= yMax) { int xMin, xMax; if (k > 0) { xMin = tmax(b.x + tmax(segmLeft.x, xSegmMin - dx), 0); // clipping x xMax = tmin(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); // clipping x } else { xMin = tmax(b.x - halfCord.getCord(abs(segmLeft.y)), 0); // clipping x + ritorno alle xMax = tmin(b.x - tmax(segmLeft.x, xSegmMin - dx), lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; while (dSegmLeft < 0) { dSegmLeft = dSegmLeft + incE; segmLeft.x++; } dSegmLeft = dSegmLeft + incNE; segmLeft.x++; segmLeft.y++; } } else // m>1 { // midpoint algorithm; le scanline vengono disegnate sempre TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft); while (segmLeft.y <= yMax) { int xMin, xMax; if (k > 0) { xMin = tmax(b.x + segmLeft.x, 0); // clipping x xMax = tmin(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); // clipping x } else { xMin = tmax(b.x - halfCord.getCord(abs(segmLeft.y)), 0); // clipping x + ritorno alle xMax = tmin(b.x - segmLeft.x, lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; if (dSegmLeft <= 0) // NordEst { dSegmLeft = dSegmLeft + incNE; segmLeft.x++; } else // Nord { dSegmLeft = dSegmLeft + incN; } segmLeft.y++; } } // ----- parallelogramma (in alternativa a "parallelogrammoide circolare") // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro // del cerchio inferiore // retta destra di equaz. alpha * x + beta * y + gammaRight = 0 // retta sinistra di equaz. alpha * x + beta * y + gammaLeft = 0 yMin = tmax(a.y + cutIn + 1, 0) - a.y; //clipping y yMax = tmin(b.y - cutIn - 1, ly - 1) - a.y; //clipping y if (m <= 1) { // midpoint algorithm; le scanline vengono disegnate solo // sul NordEst. L'ultima scanline non viene disegnata TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); TPoint segmLeft = TPoint(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin); int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight); int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft); while (segmRight.y <= yMax) { if (dSegmRight < 0) // segmRight a Est { dSegmRight = dSegmRight + incE; segmRight.x++; } else // segmRight a NordEst { int xMin, xMax; if (k > 0) { xMin = tmax(a.x + tmax(segmLeft.x, xSegmMin), 0); // clipping x xMax = tmin(a.x + tmin(segmRight.x, xSegmMax), lx - 1); // clipping x } else { xMin = tmax(a.x - tmin(segmRight.x, xSegmMax), 0); // clipping x + ritorno alle xMax = tmin(a.x - tmax(segmLeft.x, xSegmMin), lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; dSegmRight = dSegmRight + incNE; segmRight.x++; segmRight.y++; while (dSegmLeft < 0) // segmLeft a Est { dSegmLeft = dSegmLeft + incE; segmLeft.x++; } // segmLeft a NordEst dSegmLeft = dSegmLeft + incNE; segmLeft.x++; segmLeft.y++; } } } else // m>1 { // midpoint algorithm; le scanline vengono disegnate sempre TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin); TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight); int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft); while (segmRight.y <= yMax) { int xMin, xMax; if (k > 0) { xMin = tmax(a.x + segmLeft.x, 0); // clipping x xMax = tmin(a.x + segmRight.x, lx - 1); // clipping x } else { xMin = tmax(a.x - segmRight.x, 0); // clipping x + ritorno alle xMax = tmin(a.x - segmLeft.x, lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; if (dSegmRight <= 0) // segmRight a NordEst { dSegmRight = dSegmRight + incNE; segmRight.x++; } else // segmRight a Nord { dSegmRight = dSegmRight + incN; } segmRight.y++; if (dSegmLeft <= 0) // segmLeft a NordEst { dSegmLeft = dSegmLeft + incNE; segmLeft.x++; } else // segmLeft a Nord { dSegmLeft = dSegmLeft + incN; } } } // ---- parallelogrammoide circolare (in alternativa a parallelogramma) // N.B. coordinate di schermo (riflessione per k<0 ) yMin = tmax(b.y - cutIn, 0); yMax = tmin(a.y + cutIn, ly - 1); for (y = yMin; y <= yMax; y++) { int xMin, xMax; if (k > 0) { xMin = tmax(a.x - halfCord.getCord(abs(y - a.y)), 0); // clipping x xMax = tmin(b.x + halfCord.getCord(abs(b.y - y)), lx - 1); // clipping x } else { xMin = tmax(b.x - halfCord.getCord(abs(b.y - y)), 0); // clipping x + ritorno alle xMax = tmin(a.x + halfCord.getCord(abs(y - a.y)), lx - 1); // coordinate "di schermo" } TPixel32 *p = ras->pixels(y) + xMin; TPixel32 *q = p + (xMax - xMin); while (p <= q) *p++ = col; } ras->unlock(); }
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 doCompute(TTile &tile, double frame, const TRenderSettings &ri) override { Status status = getFxStatus(m_light, m_lighted); if (status & NoPortsConnected) // If no port, just do nothing :) return; // Calculate source if (status & Port1Connected) m_lighted->compute(tile, frame, ri); // Calculate light if (status & Port0Connected) { // Init light infos TDimension tileSize(tile.getRaster()->getSize()); TRectD tileRect(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly)); double scale = sqrt(fabs(ri.m_affine.det())); double blur = m_value->getValue(frame) * scale; // Build the light interesting rect TRectD lightRect, blurOutRect; m_light->getBBox(frame, lightRect, ri); buildLightRects(tileRect, lightRect, blurOutRect, blur); if ((lightRect.getLx() <= 0) || (lightRect.getLy() <= 0)) return; if ((blurOutRect.getLx() <= 0) || (blurOutRect.getLy() <= 0)) return; // Calculate the light tile TTile lightTile; TDimension lightSize(tround(lightRect.getLx()), tround(lightRect.getLy())); m_light->allocateAndCompute(lightTile, lightRect.getP00(), lightSize, tile.getRaster(), frame, ri); // Init glow parameters TPixel32 color = m_color->getValue(frame); double brightness = m_brightness->getValue(frame) / 100.0; double fade = m_fade->getValue(frame) / 100.0; // Now, apply the glow // First, deal with the fade { TRasterP light = lightTile.getRaster(); TRaster32P light32 = light; TRaster64P light64 = light; if (light32) ::fade(light32, fade, color); else if (light64) ::fade(light64, fade, toPixel64(color)); else assert(false); } // Then, build the blur TRasterP blurOut; if (blur > 0) { // Build a temporary output to the blur { TRasterP light(lightTile.getRaster()); blurOut = light->create(tround(blurOutRect.getLx()), tround(blurOutRect.getLy())); // Apply the blur. Please note that SSE2 should not be used for now - // I've seen it // doing strange things to the blur... TPointD displacement(lightRect.getP00() - blurOutRect.getP00()); TRop::blur(blurOut, light, blur, tround(displacement.x), tround(displacement.y), false); } } else blurOut = lightTile.getRaster(); // Apply the rgbm scale TRop::rgbmScale(blurOut, blurOut, 1, 1, 1, brightness); // Apply the add { TRectD interestingRect(tileRect * blurOutRect); TRect interestingTileRect(tround(interestingRect.x0 - tileRect.x0), tround(interestingRect.y0 - tileRect.y0), tround(interestingRect.x1 - tileRect.x0) - 1, tround(interestingRect.y1 - tileRect.y0) - 1); TRect interestingBlurRect( tround(interestingRect.x0 - blurOutRect.x0), tround(interestingRect.y0 - blurOutRect.y0), tround(interestingRect.x1 - blurOutRect.x0) - 1, tround(interestingRect.y1 - blurOutRect.y0) - 1); if ((interestingTileRect.getLx() <= 0) || (interestingTileRect.getLy() <= 0)) return; if ((interestingBlurRect.getLx() <= 0) || (interestingBlurRect.getLy() <= 0)) return; TRasterP tileInterestRas( tile.getRaster()->extract(interestingTileRect)); TRasterP blurInterestRas(blurOut->extract(interestingBlurRect)); TRop::add(blurInterestRas, tileInterestRas, tileInterestRas); } } }