// @@ Not tested! CubeSurface CubeSurface::fastResample(int size, EdgeFixup fixupMethod) const { // Allocate output cube. CubeSurface resampledCube; resampledCube.m->allocate(size); // For each texel of the output cube. for (uint f = 0; f < 6; f++) { nvtt::Surface resampledFace = resampledCube.m->face[f]; FloatImage * resampledImage = resampledFace.m->image; for (uint y = 0; y < uint(size); y++) { for (uint x = 0; x < uint(size); x++) { const Vector3 filterDir = texelDirection(f, x, y, size, fixupMethod); Vector3 color = m->sample(filterDir); resampledImage->pixel(0, x, y, 0) = color.x; resampledImage->pixel(1, x, y, 0) = color.y; resampledImage->pixel(2, x, y, 0) = color.z; } } } // @@ Implement edge averaging. Share this code with cosinePowerFilter if (fixupMethod == EdgeFixup_Average) { } return resampledCube; }
FloatImage *VectorField::get_divergence(int xs, int ys) { int i,j; FloatImage *image = new FloatImage(xsize-2, ysize-2); float d = 0.1 / xsize; for (i = 1; i < xsize-1; i++) for (j = 1; j < ysize-1; j++) { float dx = xval(i+1, j) - xval(i-1, j); float dy = yval(i, j+1) - yval(i, j-1); float div = (dx + dy) / (2 * d); image->pixel(i-1, j-1) = div; } FloatImage *image2 = new FloatImage(xs, ys); for (i = 0; i < xs; i++) for (j = 0; j < ys; j++) { float x = (i + 0.5) / xs; float y = (j + 0.5) / ys; image2->pixel(i,j) = image->get_value(x,y); } delete image; return (image2); }
FloatImage *VectorField::get_vorticity(int xs, int ys) { int i,j; FloatImage *image = new FloatImage(xsize-2, ysize-2); float d = 0.1 / xsize; for (i = 1; i < xsize-1; i++) for (j = 1; j < ysize-1; j++) { float dx = yval(i+1, j) - yval(i-1, j); float dy = xval(i, j+1) - xval(i, j-1); float vort = (dx/d) - (dy/d); image->pixel(i-1, j-1) = vort; } FloatImage *image2 = new FloatImage(xs, ys); for (i = 0; i < xs; i++) for (j = 0; j < ys; j++) { float x = (i + 0.5) / xs; float y = (j + 0.5) / ys; image2->pixel(i,j) = image->get_value(x,y); } delete image; return (image2); }
void FloatImage::blur(int steps) { int i,j; int i0,i1,j0,j1; float val; FloatImage *image = new FloatImage (xsize, ysize); /* blur several times */ for (int k = 0; k < steps; k++) { /* one step of blurring */ for (i = 0; i < xsize; i++) { i0 = i-1; i1 = i+1; if (i == 0) i0 = 0; if (i == xsize-1) i1 = xsize-1; for (j = 0; j < ysize; j++) { j0 = j-1; j1 = j+1; if (j == 0) j0 = 0; if (j == ysize-1) j1 = ysize-1; val = pixel(i0,j) + pixel(i1,j) + pixel(i,j0) + pixel(i,j1); val += 4 * pixel(i,j); val *= 0.125; image->pixel(i, j) = val; } } /* copy result into original array */ for (i = 0; i < xsize; i++) for (j = 0; j < ysize; j++) pixel(i,j) = image->pixel(i,j); } delete image; }
FloatImage *FloatImage::copy() { FloatImage *image = new FloatImage (xsize, ysize); for (int i = 0; i < xsize * ysize; i++) image->pixel(i) = pixels[i]; return (image); }
FloatImage *VectorField::get_magnitude() { FloatImage *image = new FloatImage(xsize, ysize); for (int i = 0; i < xsize * ysize * 2; i += 2) { float x = values[i]; float y = values[i+1]; image->pixel(i/2) = sqrt (x*x + y*y); } return (image); }
void ApplyAngularFilterTask(void * context, int id) { ApplyAngularFilterContext * ctx = (ApplyAngularFilterContext *)context; int size = ctx->filteredCube->edgeLength; int f = id / (size * size); int idx = id % (size * size); int y = idx / size; int x = idx % size; nvtt::Surface & filteredFace = ctx->filteredCube->face[f]; FloatImage * filteredImage = filteredFace.m->image; const Vector3 filterDir = texelDirection(f, x, y, size, ctx->fixupMethod); // Convolve filter against cube. Vector3 color = ctx->inputCube->applyAngularFilter(filterDir, ctx->coneAngle, ctx->filterTable, ctx->tableSize); filteredImage->pixel(0, idx) = color.x; filteredImage->pixel(1, idx) = color.y; filteredImage->pixel(2, idx) = color.z; }
FloatImage *FloatImage::normalize() { int count = getwidth() * getheight(); FloatImage *newimage = new FloatImage(getwidth(), getheight()); /* find minimum and maximum values */ float min,max; get_extrema (min, max); if (max == min) min = max - 1; float scale = 255 * (max - min); float trans = -min; for (int i = 0; i < count; i++) newimage->pixel(i) = (pixel(i) - min) / (max - min); return (newimage); }
CubeSurface CubeSurface::cosinePowerFilter(int size, float cosinePower, EdgeFixup fixupMethod) const { // Allocate output cube. CubeSurface filteredCube; filteredCube.m->allocate(size); // Texel table is stored along with the surface so that it's compute only once. m->allocateTexelTable(); const float threshold = 0.001f; const float coneAngle = acosf(powf(threshold, 1.0f/cosinePower)); // For each texel of the output cube. /*for (uint f = 0; f < 6; f++) { nvtt::Surface filteredFace = filteredCube.m->face[f]; FloatImage * filteredImage = filteredFace.m->image; for (uint y = 0; y < uint(size); y++) { for (uint x = 0; x < uint(size); x++) { const Vector3 filterDir = texelDirection(f, x, y, size, fixupMethod); // Convolve filter against cube. Vector3 color = m->applyCosinePowerFilter(filterDir, coneAngle, cosinePower); filteredImage->pixel(0, x, y, 0) = color.x; filteredImage->pixel(1, x, y, 0) = color.y; filteredImage->pixel(2, x, y, 0) = color.z; } } }*/ ApplyAngularFilterContext context; context.inputCube = m; context.filteredCube = filteredCube.m; context.coneAngle = coneAngle; context.fixupMethod = fixupMethod; context.tableSize = 512; context.filterTable = new float[context.tableSize]; // @@ Instead of looking up table between [0 - 1] we should probably use [cos(coneAngle), 1] for (int i = 0; i < context.tableSize; i++) { float f = float(i) / (context.tableSize - 1); context.filterTable[i] = powf(f, cosinePower); } nv::ParallelFor parallelFor(ApplyAngularFilterTask, &context); parallelFor.run(6 * size * size); // @@ Implement edge averaging. if (fixupMethod == EdgeFixup_Average) { for (uint f = 0; f < 6; f++) { nvtt::Surface filteredFace = filteredCube.m->face[f]; FloatImage * filteredImage = filteredFace.m->image; // For each component. for (uint c = 0; c < 3; c++) { // @@ For each corner, sample the two adjacent faces. filteredImage->pixel(c, 0, 0, 0); filteredImage->pixel(c, size-1, 0, 0); filteredImage->pixel(c, 0, size-1, 0); filteredImage->pixel(c, size-1, size-1, 0); // @@ For each edge, sample the adjacent face. } } } return filteredCube; }