//------------------------------------------------ inline void setMatteAndYMirror(const TRaster32P &ras) { ras->lock(); TPixel32 *upRow = ras->pixels(); TPixel32 *dwRow = ras->pixels(ras->getLy() - 1); int hLy = (int)(ras->getLy() / 2. + 0.5); //piccola pessimizzazione... int wrap = ras->getWrap(); int lx = ras->getLx(); TPixel32 *upPix = 0; TPixel32 *lastPix = ras->pixels(hLy); while (upPix < lastPix) { upPix = upRow; TPixel32 *dwPix = dwRow; TPixel32 *endPix = upPix + lx; while (upPix < endPix) { TPixel32 tmpPix(upPix->r, upPix->g, upPix->b, 0xff); *upPix = *dwPix; upPix->m = 0xff; *dwPix = tmpPix; ++upPix; ++dwPix; } upRow += wrap; dwRow -= wrap; } ras->unlock(); }
void TRop::swapRBChannels(const TRaster32P &r) { int lx = r->getLx(); int y = r->getLy(); r->lock(); while (--y >= 0) { TPixel32 *pix = r->pixels(y); TPixel32 *endPix = pix + lx; while (pix < endPix) { tswap(pix->r, pix->b); ++pix; } } r->unlock(); }
static void addBackground32(TRaster32P ras, const TPixel32 &col) { ras->lock(); int nrows = ras->getLy(); while (nrows-- > 0) { TPixel32 *pix = ras->pixels(nrows); TPixel32 *endPix = pix + ras->getLx(); while (pix < endPix) { *pix = overPix(col, *pix); pix++; } } ras->unlock(); }
TImageP TImageReaderBmp::load() { TImageP image; void *buff; int retCode = readbmp(getFilePath().getWideString().c_str(), &m_lx, &m_ly, &buff); if (retCode != OK) { throw TImageException(getFilePath(), buildBMPExceptionString(retCode)); } TRaster32P raster; raster.create(m_lx, m_ly); raster->lock(); memcpy(raster->pixels(), buff, m_lx * m_ly * sizeof(TPixel32)); raster->unlock(); TRasterImageP rasImage(raster); // image->setRaster(raster); delete[] buff; return TImageP(rasImage); }
TRaster32P TRop::copyAndSwapRBChannels(const TRaster32P &srcRaster) { TRaster32P newRaster(srcRaster->getSize()); int lx = srcRaster->getLx(); int y = srcRaster->getLy(); srcRaster->lock(); newRaster->lock(); while (--y >= 0) { TPixel32 *pix = srcRaster->pixels(y); TPixel32 *newpix = newRaster->pixels(y); TPixel32 *endPix = pix + lx; while (pix < endPix) { newpix->r = pix->b; newpix->g = pix->g; newpix->b = pix->r; newpix->m = pix->m; ++pix; ++newpix; } } srcRaster->unlock(); newRaster->unlock(); return newRaster; }
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 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 TLevelReader3gp::load(const TRasterP &rasP, int frameIndex, const TPoint &pos, int shrinkX, int shrinkY) { TRaster32P ras = rasP; { QMutexLocker sl(&m_mutex); ras->lock(); if (m_IOError != QTNoError) goto error; Rect rect; rect.right = pos.x + ras->getLx(); rect.left = pos.x; rect.bottom = pos.y + ras->getLy(); rect.top = pos.y; GWorldPtr offscreenGWorld; OSErr err; #if defined TNZ_MACHINE_CHANNEL_ORDER_BGRM OSType pixelFormat = k32BGRAPixelFormat; #elif defined TNZ_MACHINE_CHANNEL_ORDER_MRGB OSType pixelFormat = k32ARGBPixelFormat; #endif err = QTNewGWorldFromPtr( &offscreenGWorld, pixelFormat, &rect, 0, 0, 0, ras->getRawData(), ras->getWrap() * 4); if (err != noErr) { m_IOError = QTUnableToCreateResource; goto error; } SetMovieBox(m_movie, &rect); err = GetMoviesError(); if (err != noErr) { m_IOError = QTUnableToSetMovieBox; #if 0 DisposeGWorld(offscreenGWorld); #endif goto error; } #if 0 SetMovieGWorld(m_movie, offscreenGWorld, GetGWorldDevice(offscreenGWorld)); #endif err = GetMoviesError(); if (err != noErr) { m_IOError = QTUnableToSetMovieGWorld; #if 0 DisposeGWorld(offscreenGWorld); #endif goto error; } TimeValue currentTime = currentTimes[frameIndex]; SetMovieTimeValue(m_movie, currentTime); err = GetMoviesError(); if (err != noErr) { m_IOError = QTUnableToSetTimeValue; #if 0 DisposeGWorld(offscreenGWorld); #endif goto error; } err = UpdateMovie(m_movie); if (err != noErr) { m_IOError = QTUnableToUpdateMovie; #if 0 DisposeGWorld(offscreenGWorld); #endif goto error; } MoviesTask(m_movie, 0); err = GetMoviesError(); if (err != noErr) { m_IOError = QTUnableToDoMovieTask; #if 0 DisposeGWorld(offscreenGWorld); #endif goto error; } SetMovieGWorld(m_movie, 0, 0); #if 0 DisposeGWorld(offscreenGWorld); #endif ras->unlock(); } if (m_depth != 32) { setMatteAndYMirror(rasP); } else { rasP->yMirror(); } return; error: ras->unlock(); throw TImageException(m_path, buildQTErrorString(m_IOError)); }
void tglDraw(const TRectD &rect, const TRaster32P &tex, bool blending) { CHECK_ERRORS_BY_GL; glPushAttrib(GL_ALL_ATTRIB_BITS); if (blending) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } unsigned int texWidth = 1; unsigned int texHeight = 1; while (texWidth < (unsigned int)tex->getLx()) texWidth = texWidth << 1; while (texHeight < (unsigned int)tex->getLy()) texHeight = texHeight << 1; double lwTex = 1.0; double lhTex = 1.0; TRaster32P texture; unsigned int texLx = (unsigned int)tex->getLx(); unsigned int texLy = (unsigned int)tex->getLy(); if (texWidth != texLx || texHeight != texLy) { texture = TRaster32P(texWidth, texHeight); texture->fill(TPixel32(0, 0, 0, 0)); texture->copy(tex); lwTex = (texLx) / (double)(texWidth); lhTex = (texLy) / (double)(texHeight); if (lwTex > 1.0) lwTex = 1.0; if (lhTex > 1.0) lhTex = 1.0; } else texture = tex; GLenum fmt = #ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM GL_BGRA_EXT; #elif TNZ_MACHINE_CHANNEL_ORDER_MBGR GL_ABGR_EXT; #elif TNZ_MACHINE_CHANNEL_ORDER_RGBM GL_RGBA; #elif TNZ_MACHINE_CHANNEL_ORDER_MRGB GL_BGRA; #else // Error PLATFORM NOT SUPPORTED #error "unknown channel order!" #endif // Generate a texture id and bind it. GLuint texId; glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->getWrap()); texture->lock(); glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, fmt, #ifdef TNZ_MACHINE_CHANNEL_ORDER_MRGB GL_UNSIGNED_INT_8_8_8_8_REV, #else GL_UNSIGNED_BYTE, #endif texture->getRawData()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); double rectLx = rect.getLx(); double rectLy = rect.getLy(); tglColor(TPixel32(0, 0, 0, 0)); glPushMatrix(); glTranslated(rect.x0, rect.y0, 0.0); glBegin(GL_POLYGON); glTexCoord2d(0, 0); tglVertex(TPointD(0.0, 0.0)); glTexCoord2d(lwTex, 0); tglVertex(TPointD(rectLx, 0.0)); glTexCoord2d(lwTex, lhTex); tglVertex(TPointD(rectLx, rectLy)); glTexCoord2d(0, lhTex); tglVertex(TPointD(0.0, rectLy)); glEnd(); glDisable(GL_TEXTURE_2D); glPopMatrix(); glPopAttrib(); // Delete texture glDeleteTextures(1, &texId); texture->unlock(); }
void TglTessellator::tessellate(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &outline, TRaster32P texture) { //QMutexLocker sl(m_mutex); checkErrorsByGL; glEnable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); checkErrorsByGL; TextureInfoForGL texInfo; int pow2Lx = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLx()); int pow2Ly = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLy()); TAffine aff; if (texture->getLx() != pow2Lx || texture->getLy() != pow2Ly) { TRaster32P r(pow2Lx, pow2Ly); aff = TScale((double)pow2Lx / texture->getLx(), (double)pow2Ly / texture->getLy()); TRop::resample(r, texture, aff.place(texture->getCenterD(), r->getCenterD())); texture = r; glPushMatrix(); tglMultMatrix(aff.inv()); } // If GL_BRGA isn't present make a proper texture to use (... obsolete?) texture->lock(); TRasterP texImage = prepareTexture(texture, texInfo); checkErrorsByGL; if (texImage != texture) texImage->lock(); assert(texImage->getLx() == texImage->getWrap()); GLuint texId; glGenTextures(1, &texId); // Generate a texture name checkErrorsByGL; glBindTexture(GL_TEXTURE_2D, texId); // Bind it 'active' checkErrorsByGL; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // These must be invoked glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // on a bound texture glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // checkErrorsByGL; glTexEnvf(GL_TEXTURE_ENV, // This too ? GL_TEXTURE_ENV_MODE, // Better here anyway GL_MODULATE); // checkErrorsByGL; glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); checkErrorsByGL; glTexImage2D(GL_TEXTURE_2D, 0, // one level only texInfo.internalformat, // pixel channels count texInfo.width, // width texInfo.height, // height 0, // border size texInfo.type, // pixel format // crappy names texInfo.format, // pixel data type // oh, SO much texImage->getRawData()); checkErrorsByGL; texture->unlock(); if (texImage != texture) texImage->unlock(); TglTessellator::GLTess glTess; gluTessCallback(glTess.m_tess, GLU_TESS_VERTEX, (GluCallback)tessellateTexture); checkErrorsByGL; //------------------------// if (aff != TAffine()) doTessellate(glTess, cf, antiAliasing, outline, aff); // Tessellate & render else doTessellate(glTess, cf, antiAliasing, outline); // Tessellate & render checkErrorsByGL; //------------------------// if (aff != TAffine()) glPopMatrix(); glDeleteTextures(1, &texId); // Delete & unbind texture checkErrorsByGL; glDisable(GL_TEXTURE_2D); checkErrorsByGL; }
void TRop::over(TRaster32P rout, const TRasterGR8P &rup, const TPixel32 &color) { rout->lock(); do_over(rout, rup, color); rout->unlock(); }