void DiffuseGain::applyPtmRGB(const PyramidCoeff& redCoeff, const PyramidCoeff& greenCoeff, const PyramidCoeff& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { int offsetBuf = 0; const PTMCoefficient* redPtr = redCoeff.getLevel(info.level); const PTMCoefficient* greenPtr = greenCoeff.getLevel(info.level); const PTMCoefficient* bluePtr = blueCoeff.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); // Creates the output texture. #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = ((y-info.offy)*info.width)<<2; int offset = y * mipMapSize[info.level].width() + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { buffer[offsetBuf + 0] = tobyte(applyModel(&(redPtr[offset][0]), normalsPtr[offset].X(), normalsPtr[offset].Y(), info.light.X(), info.light.Y())); buffer[offsetBuf + 1] = tobyte(applyModel(&(greenPtr[offset][0]), normalsPtr[offset].X(), normalsPtr[offset].Y(), info.light.X(), info.light.Y())); buffer[offsetBuf + 2] = tobyte(applyModel(&(bluePtr[offset][0]), normalsPtr[offset].X(), normalsPtr[offset].Y(), info.light.X(), info.light.Y())); buffer[offsetBuf + 3] = 255; offset++; offsetBuf += 4; } } //qDebug() << "gain = " << DiffuseGain::gain; }
void CoeffEnhancement::applyPtmRGB(const PyramidCoeff& redCoeff, const PyramidCoeff& greenCoeff, const PyramidCoeff& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { //int offsetBuf = 0; const PTMCoefficient* redPtr = redCoeff.getLevel(info.level); const PTMCoefficient* greenPtr = greenCoeff.getLevel(info.level); const PTMCoefficient* bluePtr = blueCoeff.getLevel(info.level); int lenght = info.width * info.height; PTMCoefficient* redC = new PTMCoefficient[lenght]; PTMCoefficient* greenC = new PTMCoefficient[lenght]; PTMCoefficient* blueC = new PTMCoefficient[lenght]; int width = mipMapSize[info.level].width(); // Creates the map of the coefficients of the sub-image in the current view of the browser #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { memcpy(&redC[offset2], &redPtr[offset], sizeof(PTMCoefficient)); memcpy(&greenC[offset2], &greenPtr[offset], sizeof(PTMCoefficient)); memcpy(&blueC[offset2], &bluePtr[offset], sizeof(PTMCoefficient)); offset++; offset2++; } } // Computes the enhanced coefficients enhancedCoeff(redC, info.width, info.height, 6); enhancedCoeff(greenC, info.width, info.height, 6); enhancedCoeff(blueC, info.width, info.height, 6); // Creates the output texture. LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width*4; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { buffer[offsetBuf] = tobyte(redC[offset2].evalPoly(lVec)); buffer[offsetBuf + 1] = tobyte(greenC[offset2].evalPoly(lVec)); buffer[offsetBuf + 2] = tobyte(blueC[offset2].evalPoly(lVec)); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2++; } } delete[] redC; delete[] greenC; delete[] blueC; }
void DiffuseGain::applyPtmLRGB(const PyramidCoeff& coeff, const PyramidRGB& rgb, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { int offsetBuf = 0; const unsigned char* rgbPtr = rgb.getLevel(info.level); const PTMCoefficient* coeffPtr = coeff.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); // Creates the output texture. #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = ((y-info.offy)*info.width)<<2; int offset = y * mipMapSize[info.level].width() + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { //int offset = y * mipMapSize[info.level].width() + x; float lum = applyModel(&(coeffPtr[offset][0]), normalsPtr[offset].X(), normalsPtr[offset].Y(), info.light.X(), info.light.Y()) / 256.0f; int offset3 = offset*3; for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(rgbPtr[offset3 + i] * lum); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset++; } } //qDebug() << "gain = " << DiffuseGain::gain; }
void SpecularEnhancement::applyPtmRGB(const PyramidCoeff& redCoeff, const PyramidCoeff& greenCoeff, const PyramidCoeff& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { // Creates the output texture. const PTMCoefficient* redPtr = redCoeff.getLevel(info.level); const PTMCoefficient* greenPtr = greenCoeff.getLevel(info.level); const PTMCoefficient* bluePtr = blueCoeff.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset = y * mipMapSize[info.level].width() + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { vcg::Point3f h(0, 0, 1); h += info.light; h /= 2; h.Normalize(); float nDotH = h * normalsPtr[offset]; if (nDotH < 0) nDotH = 0.0; else if (nDotH > 1) nDotH = 1.0; nDotH = pow(nDotH, exp); float r = redPtr[offset].evalPoly(lVec); float g = greenPtr[offset].evalPoly(lVec); float b = bluePtr[offset].evalPoly(lVec); float temp = (r + g + b)/3; float lum = temp * ks * 2 * nDotH; buffer[offsetBuf + 0] = tobyte( r * kd + lum); buffer[offsetBuf + 1] = tobyte( g * kd + lum ); buffer[offsetBuf + 2] = tobyte( b * kd + lum ); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset++; } } }
QImage* RGBPtm::createPreview(int width, int height) { // Computes the height and the width of the preview. int level = 3; int imageH = mipMapSize[3].height(); int imageW = mipMapSize[3].width(); for (int i = 0; i < 4; i++) { if (mipMapSize[i].width() <= width || mipMapSize[i].height() <= height) { if (mipMapSize[i].width() < width && mipMapSize[i].height() < height && i > 0) i--; imageH = mipMapSize[i].height(); imageW = mipMapSize[i].width(); level = i; break; } } // Creates the preview. unsigned char* buffer = new unsigned char[imageH*imageW*4]; const PTMCoefficient* redPtr = redCoefficients.getLevel(level); const PTMCoefficient* greenPtr = greenCoefficients.getLevel(level); const PTMCoefficient* bluePtr = blueCoefficients.getLevel(level); int offset = 0; for (int i = 0; i < imageH; i++) { for (int j = 0; j < imageW; j++) { offset = i * imageW + j; buffer[offset*4 + 2] = tobyte(evalPoly((int*)&(redPtr[offset][0]), 0, 0)); buffer[offset*4 + 1] = tobyte(evalPoly((int*)&(greenPtr[offset][0]), 0, 0)); buffer[offset*4 + 0] = tobyte(evalPoly((int*)&(bluePtr[offset][0]), 0, 0)); buffer[offset*4 + 3] = 255; } } QImage* image = new QImage(buffer, imageW, imageH, QImage::Format_RGB32); return image; }
void CoeffEnhancement::applyPtmLRGB(const PyramidCoeff& coeff, const PyramidRGB& rgb, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { //int offsetBuf = 0; const PTMCoefficient* coeffPtr = coeff.getLevel(info.level); const unsigned char* rgbPtr = rgb.getLevel(info.level); PTMCoefficient* coeffMap = new PTMCoefficient[info.width*info.height]; int width = mipMapSize[info.level].width(); // Creates the map of the coefficients of the sub-image in the current view of the browser #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { memcpy(coeffMap[offset2], coeffPtr[offset], sizeof(PTMCoefficient)); offset++; offset2++; } } // Computes the enhanced coefficients. enhancedCoeff(coeffMap, info.width, info.height, 6); // Creates the output texture. LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetLoc = (y-info.offy)*info.width; int offsetBuf = offsetLoc << 2; int offset = y * width + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { float lum = coeffMap[offsetLoc].evalPoly(lVec) / 255.0f; int offset3 = offset * 3; for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(rgbPtr[offset3 + i] * lum); buffer[offsetBuf + 3] = 255; offsetBuf +=4; offset++; offsetLoc++; } } delete[] coeffMap; }
void SpecularEnhancement::applyPtmLRGB(const PyramidCoeff& coeff, const PyramidRGB& rgb, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { // Creates the output texture. //int offsetBuf = 0; const PTMCoefficient* coeffPtr = coeff.getLevel(info.level); const unsigned char* rgbPtr = rgb.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width*4; int offset = y * mipMapSize[info.level].width() + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { float lum = coeffPtr[offset].evalPoly(lVec) / 255.0f; vcg::Point3f h(0, 0, 1); h += info.light; h /= 2; h.Normalize(); float nDotH = h * normalsPtr[offset]; if (nDotH < 0) nDotH = 0.0; else if (nDotH > 1) nDotH = 1.0; nDotH = pow(nDotH, exp); nDotH *= ks*255; int offset3 = offset*3; for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte((rgbPtr[offset3 + i]*kd + nDotH)*lum); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset++; } } }
void UnsharpMasking::applyPtmRGB(const PyramidCoeff& redCoeff, const PyramidCoeff& greenCoeff, const PyramidCoeff& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { int offsetBuf = 0; const PTMCoefficient* redPtr = redCoeff.getLevel(info.level); const PTMCoefficient* greenPtr = greenCoeff.getLevel(info.level); const PTMCoefficient* bluePtr = blueCoeff.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); float* lumMap = new float[info.width*info.height]; int width = mipMapSize[info.level].width(); if (type == 0) //classic unsharp masking { float* uvMap = new float[info.width*info.height*2]; LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { float r = redPtr[offset].evalPoly(lVec) / 255.0;//evalPoly((int*)&(redPtr[offset][0]), info.light.X(), info.light.Y()) / 255.0; float g = greenPtr[offset].evalPoly(lVec) / 255.0;//evalPoly((int*)&(greenPtr[offset][0]), info.light.X(), info.light.Y()) / 255.0; float b = bluePtr[offset].evalPoly(lVec) / 255.0;//evalPoly((int*)&(bluePtr[offset][0]), info.light.X(), info.light.Y()) / 255.0; getYUV(r, g, b, lumMap[offset2], uvMap[offset2*2], uvMap[offset2*2 + 1]); offset++; offset2++; } } enhancedLuminance(lumMap, info.width, info.height, info.mode); bool flag = (info.mode == LUM_UNSHARP_MODE || info.mode == SMOOTH_MODE || info.mode == CONTRAST_MODE || info.mode == ENHANCED_MODE); if (flag) { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset2 =(y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(lumMap[offset2] * 255.0); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2++; } } } else { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset2 =(y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { float r, g, b; getRGB(lumMap[offset2], uvMap[offset2*2], uvMap[offset2*2 +1], r, g, b); buffer[offsetBuf] = tobyte(r*255); buffer[offsetBuf + 1] = tobyte(g*255); buffer[offsetBuf + 2] = tobyte(b*255); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2++; } } } delete[] uvMap; } else //luminance unsharp masking { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offset= y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { lumMap[offset2] = getLum(normalsPtr[offset], info.light); offset++; offset2++; } } enhancedLuminance(lumMap, info.width, info.height, info.mode); bool flag = (info.mode == LUM_UNSHARP_MODE || info.mode == SMOOTH_MODE || info.mode == CONTRAST_MODE || info.mode == ENHANCED_MODE); LightMemoized lVec(info.light.X(), info.light.Y()); if (flag) { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { float lum = lumMap[offset2]; for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(lum / 2.0 * 255.0); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset++; offset2++; } } } else { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { float lum = lumMap[offset2]; buffer[offsetBuf] = tobyte(redPtr[offset].evalPoly(lVec)*lum);//evalPoly((int*)&(redPtr[offset][0]), info.light.X(), info.light.Y()) * lum); buffer[offsetBuf + 1] = tobyte(greenPtr[offset].evalPoly(lVec)*lum);//evalPoly((int*)&(greenPtr[offset][0]), info.light.X(), info.light.Y()) * lum); buffer[offsetBuf + 2] = tobyte(bluePtr[offset].evalPoly(lVec)*lum);//evalPoly((int*)&(bluePtr[offset][0]), info.light.X(), info.light.Y()) * lum); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset++; offset2++; } } } } delete[] lumMap; }
void UnsharpMasking::applyPtmLRGB(const PyramidCoeff& coeff, const PyramidRGB& rgb, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { int offsetBuf = 0; const PTMCoefficient* coeffPtr = coeff.getLevel(info.level); const unsigned char* rgbPtr = rgb.getLevel(info.level); float* lumMap = new float[info.width*info.height]; int width = mipMapSize[info.level].width(); if (type == 0) //image unsharp masking { // Creates a map for Y component and a map for UV component. float* uvMap = new float[info.width*info.height*2]; LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width<<2; int offset = (y * width + info.offx)*3; int offset2 = ((y - info.offy)*info.width)*2; for (int x = info.offx; x < info.offx + info.width; x++) { float lum = coeffPtr[offset / 3].evalPoly(lVec) / 255.0; float r = rgbPtr[offset]*lum / 255.0; float g = rgbPtr[offset + 1]*lum / 255.0; float b = rgbPtr[offset + 2]*lum / 255.0; getYUV(r, g, b, lumMap[offset2 / 2], uvMap[offset2], uvMap[offset2 + 1]); offset += 3; offset2 += 2; } } // Computes the enhanced luminance. enhancedLuminance(lumMap, info.width, info.height, info.mode); // Creates the output texture. bool flag = (info.mode == LUM_UNSHARP_MODE || info.mode == SMOOTH_MODE || info.mode == CONTRAST_MODE ||info.mode == ENHANCED_MODE); if (flag) { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y - info.offy) * info.width << 2; int offset2 =(y - info.offy) * info.width; for (int x = info.offx; x < info.offx + info.width; x++) { for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(lumMap[offset2] * 255.0); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2++; } } } else { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y - info.offy) * info.width << 2; int offset2 =(y - info.offy)*info.width * 2; for (int x = info.offx; x < info.offx + info.width; x++) { float r, g, b; getRGB(lumMap[offset2 / 2], uvMap[offset2], uvMap[offset2 + 1], r, g, b); buffer[offsetBuf ] = tobyte(r*255); buffer[offsetBuf + 1] = tobyte(g*255); buffer[offsetBuf + 2] = tobyte(b*255); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2 += 2; } } } delete[] uvMap; } else //unsharp masking luminance { // Creates a map for the polynomial luminance. LightMemoized lVec(info.light.X(), info.light.Y()); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offset = y * width + info.offx; int offset2 = (y - info.offy)*info.width; for (int x = info.offx; x < info.offx + info.width; x++) { lumMap[offset2] = coeffPtr[offset].evalPoly(lVec) / 255.0; offset++; offset2++; } } // Computes the enhanced luminance enhancedLuminance(lumMap, info.width, info.height, info.mode); // Creates the output texture. bool flag = (info.mode == LUM_UNSHARP_MODE || info.mode == SMOOTH_MODE || info.mode == CONTRAST_MODE || info.mode == ENHANCED_MODE); if (flag) { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y - info.offy) * info.width <<2; int offset2 = (y - info.offy) * info.width; for (int x = info.offx; x < info.offx + info.width; x++) { for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(lumMap[offset2] / 2.0 * 255.0); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset2++; } } } else { #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y - info.offy) * info.width << 2; int offset = (y * width + info.offx)*3; int offset2 = (y - info.offy) * info.width; for (int x = info.offx; x < info.offx + info.width; x++) { for (int i = 0; i < 3; i++) buffer[offsetBuf + i] = tobyte(rgbPtr[offset + i] * lumMap[offset2]); buffer[offsetBuf + 3] = 255; offsetBuf += 4; offset += 3; offset2++; } } } } delete[] lumMap; }
static void nonmax_suppress (float **dx, float **dy, imImage* mag) { int i,j; float xx, yy, g2, g1, g3, g4, g, xc, yc; unsigned char* mag_data = (unsigned char*)mag->data[0]; for (i=1; i<mag->height-1; i++) { for (j=1; j<mag->width-1; j++) { /* Treat the x and y derivatives as components of a vector */ xc = dx[i][j]; yc = dy[i][j]; if (fabs(xc)<0.01 && fabs(yc)<0.01) continue; g = norm (xc, yc); /* Follow the gradient direction, as indicated by the direction of the vector (xc, yc); retain pixels that are a local maximum. */ if (fabs(yc) > fabs(xc)) { /* The Y component is biggest, so gradient direction is basically UP/DOWN */ xx = (float)(fabs(xc)/fabs(yc)); yy = 1.0; g2 = norm (dx[i-1][j], dy[i-1][j]); g4 = norm (dx[i+1][j], dy[i+1][j]); if (xc*yc > 0.0) { g3 = norm (dx[i+1][j+1], dy[i+1][j+1]); g1 = norm (dx[i-1][j-1], dy[i-1][j-1]); } else { g3 = norm (dx[i+1][j-1], dy[i+1][j-1]); g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); } } else { /* The X component is biggest, so gradient direction is basically LEFT/RIGHT */ xx = (float)(fabs(yc)/fabs(xc)); yy = 1.0; g2 = norm (dx[i][j+1], dy[i][j+1]); g4 = norm (dx[i][j-1], dy[i][j-1]); if (xc*yc > 0.0) { g3 = norm (dx[i-1][j-1], dy[i-1][j-1]); g1 = norm (dx[i+1][j+1], dy[i+1][j+1]); } else { g1 = norm (dx[i-1][j+1], dy[i-1][j+1]); g3 = norm (dx[i+1][j-1], dy[i+1][j-1]); } } /* Compute the interpolated value of the gradient magnitude */ if ( (g > (xx*g1 + (yy-xx)*g2)) && (g > (xx*g3 + (yy-xx)*g4)) ) { mag_data[i*mag->width + j] = tobyte(g*MAG_SCALE); } } } }
int RGBPtm::createImage(unsigned char** buffer, int& width, int& height, const vcg::Point3f& light, const QRectF& rect, int level, int mode) { #ifdef PRINT_DEBUG QTime first = QTime::currentTime(); #endif // Computes height and width of the texture. width = ceil(rect.width()); height = ceil(rect.height()); int offx = rect.x(); int offy = rect.y(); if (currentRendering != DETAIL_ENHANCEMENT || mode == LUMR_MODE || mode == LUMG_MODE || mode == LUMB_MODE) { for (int i = 0; i < level; i++) { width = ceil(width/2.0); height = ceil(height/2.0); offx = offx/2; offy = offy/2; } } (*buffer) = new unsigned char[width*height*4]; int offsetBuf = 0; if (mode == LUMR_MODE || mode == LUMG_MODE || mode == LUMB_MODE) { // Creates map of the RGB component. const PTMCoefficient* coeffPtr = NULL; switch(mode) { case LUMR_MODE: coeffPtr = redCoefficients.getLevel(level); break; case LUMB_MODE: coeffPtr = greenCoefficients.getLevel(level); break; case LUMG_MODE: coeffPtr = blueCoefficients.getLevel(level); break; } for (int y = offy; y < offy + height; y++) { for (int x = offx; x < offx + width; x++) { int offset = y * mipMapSize[level].width() + x; unsigned char c = tobyte(evalPoly((int*)&(coeffPtr[offset][0]), light.X(), light.Y())); (*buffer)[offsetBuf + 0] = c; (*buffer)[offsetBuf + 1] = c; (*buffer)[offsetBuf + 2] = c; (*buffer)[offsetBuf + 3] = 255; offsetBuf += 4; } } } else { // Applies the current rendering mode. RenderingInfo info = {offx, offy, height, width, level, mode, light, 6}; list->value(currentRendering)->applyPtmRGB(redCoefficients, greenCoefficients, blueCoefficients, mipMapSize, normals, info, (*buffer)); } #ifdef PRINT_DEBUG QTime second = QTime::currentTime(); double diff = first.msecsTo(second) / 1000.0; if (mode == DEFAULT_MODE) { switch(currentRendering) { case DEFAULT: printf("Default rendering: %.5f s\n", diff); break; case NORMALS: printf("Normals: %.5f s\n", diff); break; case DIFFUSE_GAIN: printf("Diffuse gain: %.5f s\n", diff); break; case SPECULAR_ENHANCEMENT: printf("Specular enhancement: %.5f s\n", diff); break; case NORMAL_ENHANCEMENT: printf("Normal enhancement: %.5f s\n", diff); break; case UNSHARP_MASKING_IMG: printf("Unsharp masking image: %.5f s\n", diff); break; case UNSHARP_MASKING_LUM: printf("Unsharp masking luminance: %.5f s\n", diff); break; case COEFF_ENHANCEMENT: printf("Coefficient enhancement: %.5f s\n", diff); break; case DETAIL_ENHANCEMENT: printf("Detail enhancement: %.5f s\n", diff); break; case DYN_DETAIL_ENHANCEMENT: printf("Dynamic detail enhancement: %.5f s\n", diff); break; } } else printf("Browing mode: %.5f s\n", diff); #endif return 0; }
void SpecularEnhancement::applyHSH(const PyramidCoeffF& redCoeff, const PyramidCoeffF& greenCoeff, const PyramidCoeffF& blueCoeff, const QSize* mipMapSize, const PyramidNormals& normals, const RenderingInfo& info, unsigned char* buffer) { const float* redPtr = redCoeff.getLevel(info.level); const float* greenPtr = greenCoeff.getLevel(info.level); const float* bluePtr = blueCoeff.getLevel(info.level); const vcg::Point3f* normalsPtr = normals.getLevel(info.level); int tempW = mipMapSize[info.level].width(); float hweights[9]; vcg::Point3d temp(info.light.X(), info.light.Y(), info.light.Z()); temp.Normalize(); float phi = atan2(temp.Y(), temp.X()); if (phi<0) phi = 2*M_PI+phi; float theta = qMin<float>(acos(temp.Z()/temp.Norm()), M_PI / 2 - 0.04); //int offsetBuf = 0; getHSH(theta, phi, hweights, sqrt((float)info.ordlen)); #pragma omp parallel for schedule(static,CHUNK) for (int y = info.offy; y < info.offy + info.height; y++) { int offsetBuf = (y-info.offy)*info.width*4; int offset= y * tempW + info.offx; for (int x = info.offx; x < info.offx + info.width; x++) { float red = 0, green = 0, blue = 0; int offset2 = offset * info.ordlen; for (int k = 0; k < info.ordlen; k++) { int offset3 = offset2 + k; red += redPtr[offset3] * hweights[k]; green += greenPtr[offset3] * hweights[k]; blue += bluePtr[offset3] * hweights[k]; } red *= 256; green *= 256; blue *= 256; vcg::Point3f h(0.0f, 0.0f, 1.0f); h += info.light; h /= 2.0f; h.Normalize(); float nDotH = h * normalsPtr[offset]; if (nDotH < 0) nDotH = 0.0; else if (nDotH > 1.0f) nDotH = 1.0; nDotH = pow(nDotH, exp/5.0f); float temp = (red + green + blue)/3; float lum = temp * ks * 4.0f * nDotH; buffer[offsetBuf + 0] = tobyte( red * kd + lum); buffer[offsetBuf + 1] = tobyte( green * kd + lum ); buffer[offsetBuf + 2] = tobyte( blue * kd + lum ); buffer[offsetBuf + 3] = 0xff; offsetBuf += 4; offset++; } } }