R2Image * CreateGaussianImage(double sigma) { // Get useful variables if (sigma <= 0) return NULL; const double sqrt_of_two_pi = 2.506628274631; double a = 1.0 / (sigma * sqrt_of_two_pi); double b = -1.0 / (2.0 * sigma * sigma); int radius = (int) (3.0*sigma + 0.5); int width = 2 * radius + 1; // Create image R2Image *image = new R2Image(width, width, 1); if (!image) return NULL; // Fill image for (int i = -radius; i <= radius; i++) { double g1 = a*exp(b*i*i); for (int j = -radius; j <= radius; j++) { double g2 = a*exp(b*j*j); double value = g1 * g2; image->SetValue(i + radius, j + radius, 0, value); } } // Return image return image; }
R2Image *RenderImage(R3Scene *scene, int width, int height, int max_depth, int num_primary_rays_per_pixel, int num_distributed_rays_per_intersection) { // Allocate image R2Image *image = new R2Image(width, height); if (!image) { fprintf(stderr, "Unable to allocate image\n"); return NULL; } // Calculate each pixel value for (int i = 0; i < width; i++) { cout << i << endl; for (int j = 0; j < height; j++) { // Cast primary ray through the pixel R3Ray ray = RayThoughPixel(scene->Camera(), i, j, width, height); // Compute the radiance traveling into the camera along that ray R3Rgb rgb = ComputeRadiance(scene, ray, 0, max_depth, num_distributed_rays_per_intersection); // set image pixel value image->SetPixel(i, j, rgb); } } // Return image return image; }
void R2Image:: Multiply(const R2Image& image) { // Multiply by image pixel-by-pixel assert(image.Width() == Width()); assert(image.Height() == Height()); assert(image.NChannels() == NChannels()); int nvalues = NValues(); for (int i = 0; i < nvalues; i++) { pixels[i] *= image.pixels[i]; } }
void R2Image:: Subtract(const R2Image& image) { // Subtract image pixel-by-pixel assert(image.Width() == Width()); assert(image.Height() == Height()); assert(image.NChannels() == NChannels()); int nvalues = NValues(); for (int i = 0; i < nvalues; i++) { pixels[i] -= image.pixels[i]; } }
void R2Image:: Divide(const R2Image& image) { // Add image pixel-by-pixel assert(image.Width() == Width()); assert(image.Height() == Height()); assert(image.NChannels() == NChannels()); int nvalues = NValues(); for (int i = 0; i < nvalues; i++) { if (image.pixels[i] == 0) { if (pixels[i] == 0.0) continue; else pixels[i] = FLT_MAX; } else { pixels[i] /= image.pixels[i]; } } }
static R2Image * ReadImage(const char *filename) { // Allocate a image R2Image *image = new R2Image(); if (!image) { fprintf(stderr, "Unable to allocate image"); return NULL; } // Read image if (!image->Read(filename)) { fprintf(stderr, "Unable to read image file %s", filename); return NULL; } // Print message if (print_verbose) { printf("Read image from %s\n", filename); printf(" Resolution = %d %d\n", image->Width(), image->Height()); printf(" L1Norm = %g\n", image->L1Norm()); printf(" L2Norm = %g\n", image->L2Norm()); fflush(stdout); } // Return image return image; }
void R2Image:: Filter(const R2Image& filter) { // Get useful variables int xr = filter.Width()/2; int yr = filter.Height()/2; R2Image copy(*this); // This is the straight-forward implementation (slow for large filters) for (int j = 0; j < Height(); j++) { for (int i = 0; i < Width(); i++) { for (int c = 0; c < NChannels(); c++) { int fc = (NChannels() == filter.NChannels()) ? c : 0; // Compute new value double sum = 0; for (int s = 0; s < filter.Width(); s++) { int x = i - xr + s; if (x < 0) x = 0; else if (x >= Width()) x = Width()-1; for (int t = 0; t < filter.Height(); t++) { int y = j - yr + t; if (y < 0) y = 0; else if (y >= Height()) y = Height()-1; double filter_value = filter.Value(s, t, fc); double image_value = copy.Value(x, y, c); sum += filter_value * image_value; } } // Assign new value for channel SetValue(i, j, c, sum); } } } }
int main(int argc, char **argv) { // Look for help for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-help")) { ShowUsage(); } } // Read input and output filenames if (argc < 3) ShowUsage(); argv++, argc--; // First argument is program name char *input_scene_name = *argv; argv++, argc--; char *output_image_name = *argv; argv++, argc--; // Initialize arguments to default values int width = 256; int height = 256; int max_depth = 0; int num_distributed_rays_per_intersection = 0; int num_primary_rays_per_pixel = 1; bool hard_shadow = false; // Parse arguments while (argc > 0) { if (!strcmp(*argv, "-width")) { CheckOption(*argv, argc, 2); width = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-height")) { CheckOption(*argv, argc, 2); height = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-max_depth")) { CheckOption(*argv, argc, 2); max_depth = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-antialias")) { CheckOption(*argv, argc, 2); num_primary_rays_per_pixel = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-distribute")) { CheckOption(*argv, argc, 2); num_distributed_rays_per_intersection = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-hard_shadow")) { hard_shadow = true; argv += 1, argc -= 1; } else { // Unrecognized program argument fprintf(stderr, "meshpro: invalid option: %s\n", *argv); ShowUsage(); } } // Read scene R3Scene *scene = ReadScene(input_scene_name, width, height); if (!scene) { fprintf(stderr, "Unable to read scene from %s\n", input_scene_name); exit(-1); } // Render image R2Image *image = RenderImage(scene, width, height, max_depth, num_primary_rays_per_pixel, num_distributed_rays_per_intersection, hard_shadow); if (!image) { fprintf(stderr, "Did not render image from scene\n"); exit(-1); } // Transfer the image to sRGB color space: for Windows + Linux and Mac OS X // 10.6+ (for earlier MAC OS X it will look slightly too bright, but not as // much as it would be too dark otherwise. This function also clamps the // image values; however, it does not scale the brightness and also does not // perform any more complicated tone mapping image->TosRGB(); // Write output image if (!image->Write(output_image_name)) { fprintf(stderr, "Did not write image to %s\n", output_image_name); exit(-1); } // Delete everything delete scene; delete image; // Return success return EXIT_SUCCESS; }
int R3Mesh:: ReadImage(const char *filename) { // Create a mesh by reading an image file, // constructing vertices at (x,y,luminance), // and connecting adjacent pixels into faces. // That is, the image is interpretted as a height field, // where the luminance of each pixel provides its z-coordinate. // Read image R2Image *image = new R2Image(); if (!image->Read(filename)) return 0; // Create vertices and store in arrays R3MeshVertex ***vertices = new R3MeshVertex **[image->Width() ]; for (int i = 0; i < image->Width(); i++) { vertices[i] = new R3MeshVertex *[image->Height() ]; for (int j = 0; j < image->Height(); j++) { double luminance = image->Pixel(i, j).Luminance(); double z = luminance * image->Width(); R3Point position((double) i, (double) j, z); R2Point texcoords((double) i, (double) j); vertices[i][j] = CreateVertex(position, R3zero_vector, texcoords); } } // Create faces vector<R3MeshVertex *> face_vertices; for (int i = 1; i < image->Width(); i++) { for (int j = 1; j < image->Height(); j++) { face_vertices.clear(); face_vertices.push_back(vertices[i-1][j-1]); face_vertices.push_back(vertices[i][j-1]); face_vertices.push_back(vertices[i][j]); face_vertices.push_back(vertices[i-1][j]); CreateFace(face_vertices); } } // Delete vertex arrays for (int i = 0; i < image->Width(); i++) delete [] vertices[i]; delete [] vertices; // Delete image delete image; // Return success return 1; }
void LoadMaterial(R3Material *material) { GLfloat c[4]; // Check if same as current static R3Material *current_material = NULL; if (material == current_material) return; current_material = material; // Compute "opacity" double opacity = 1 - material->kt.Luminance(); // Load ambient c[0] = material->ka[0]; c[1] = material->ka[1]; c[2] = material->ka[2]; c[3] = opacity; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); // Load diffuse c[0] = material->kd[0]; c[1] = material->kd[1]; c[2] = material->kd[2]; c[3] = opacity; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); // Load specular c[0] = material->ks[0]; c[1] = material->ks[1]; c[2] = material->ks[2]; c[3] = opacity; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); // Load emission c[0] = material->emission.Red(); c[1] = material->emission.Green(); c[2] = material->emission.Blue(); c[3] = opacity; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); // Load shininess c[0] = material->shininess; glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, c[0]); // Load texture if (material->texture) { if (material->texture_index <= 0) { // Create texture in OpenGL GLuint texture_index; glGenTextures(1, &texture_index); material->texture_index = (int) texture_index; glBindTexture(GL_TEXTURE_2D, material->texture_index); R2Image *image = material->texture; int npixels = image->NPixels(); R2Pixel *pixels = image->Pixels(); GLfloat *buffer = new GLfloat [ 4 * npixels ]; R2Pixel *pixelsp = pixels; GLfloat *bufferp = buffer; for (int j = 0; j < npixels; j++) { *(bufferp++) = pixelsp->Red(); *(bufferp++) = pixelsp->Green(); *(bufferp++) = pixelsp->Blue(); *(bufferp++) = pixelsp->Alpha(); pixelsp++; } glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, 4, image->Width(), image->Height(), 0, GL_RGBA, GL_FLOAT, buffer); delete [] buffer; } // Select texture glBindTexture(GL_TEXTURE_2D, material->texture_index); glEnable(GL_TEXTURE_2D); } else { glDisable(GL_TEXTURE_2D); } // Enable blending for transparent surfaces if (opacity < 1) { glDepthMask(false); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } else { glDisable(GL_BLEND); glBlendFunc(GL_ONE, GL_ZERO); glDepthMask(true); } }
int R3Model:: ReadObjMtlFile(const char *dirname, const char *mtlname) { // Open file char filename[1024]; sprintf(filename, "%s/%s", dirname, mtlname); FILE *fp = fopen(filename, "r"); if (!fp) { RNFail("Unable to open file %s", filename); return 0; } // Parse file char buffer[1024]; int line_count = 0; R3Brdf *brdf = NULL; R2Texture *texture = NULL; R3Material *material = NULL; while (fgets(buffer, 1023, fp)) { // Increment line counter line_count++; // Skip white space char *bufferp = buffer; while (isspace(*bufferp)) bufferp++; // Skip blank lines and comments if (*bufferp == '#') continue; if (*bufferp == '\0') continue; // Get keyword char keyword[80]; if (sscanf(bufferp, "%s", keyword) != 1) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Check keyword if (!strcmp(keyword, "newmtl")) { // Parse line char name[1024]; if (sscanf(bufferp, "%s%s", keyword, name) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Create new material texture = NULL; brdf = new R3Brdf(); material = new R3Material(brdf, texture, name); materials.Insert(material); RNArray<R3Triangle *> *mat_tris = new RNArray<R3Triangle *>(); material_triangles.Insert(mat_tris); } else if (!strcmp(keyword, "Ka")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set ambient reflectance if (material && brdf) { brdf->SetAmbient(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Kd")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set diffuse reflectance if (material && brdf) { brdf->SetDiffuse(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Ks")) { // Parse line double r, g, b; if (sscanf(bufferp, "%s%lf%lf%lf", keyword, &r, &g, &b) != (unsigned int) 4) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set specular reflectance if (material && brdf) { brdf->SetSpecular(RNRgb(r, g, b)); material->Update(); } } else if (!strcmp(keyword, "Ns")) { // Parse line double ns; if (sscanf(bufferp, "%s%lf", keyword, &ns) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set shininess if (material && brdf) { brdf->SetShininess(ns); material->Update(); } } else if (!strcmp(keyword, "Ni")) { // Parse line double index_of_refraction; if (sscanf(bufferp, "%s%lf", keyword, &index_of_refraction) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set index of refraction if (material && brdf) { brdf->SetIndexOfRefraction(index_of_refraction); material->Update(); } } else if (!strcmp(keyword, "d")) { // Parse line double transparency; if (sscanf(bufferp, "%s%lf", keyword, &transparency) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set opacity if (material && brdf) { brdf->SetOpacity(1 - transparency); material->Update(); } } else if (!strcmp(keyword, "map_Kd")) { // Parse line char texture_name[1024]; if (sscanf(bufferp, "%s%s", keyword, texture_name) != (unsigned int) 2) { RNFail("Syntax error on line %d in file %s", line_count, filename); return 0; } // Set texture if (material) { char texture_filename[1024]; sprintf(texture_filename, "%s/%s", dirname, texture_name); R2Image *image = new R2Image(); if (!image->Read(texture_filename)) return 0; R2Texture *texture = new R2Texture(image); material->SetTexture(texture); material->Update(); } } } // Close file fclose(fp); // Return success return 1; }
int main(int argc, char **argv) { // Look for help for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-help")) { ShowUsage(); } if (!strcmp(argv[i], "-svdTest")) { R2Image *image = new R2Image(); image->svdTest(); return 0; } } // Read input and output image filenames if (argc < 3) ShowUsage(); argv++, argc--; // First argument is program name char *input_image_name = *argv; argv++, argc--; char *output_image_name = *argv; argv++, argc--; // Allocate image R2Image *image = new R2Image(); if (!image) { fprintf(stderr, "Unable to allocate image\n"); exit(-1); } // Read input image if (!image->Read(input_image_name)) { fprintf(stderr, "Unable to read image from %s\n", input_image_name); exit(-1); } // Initialize sampling method int sampling_method = R2_IMAGE_POINT_SAMPLING; // Parse arguments and perform operations while (argc > 0) { if (!strcmp(*argv, "-brightness")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -=2; image->Brighten(factor); } else if (!strcmp(*argv, "-sobelX")) { argv++, argc--; image->SobelX(); } else if (!strcmp(*argv, "-sobelY")) { argv++, argc--; image->SobelY(); } else if (!strcmp(*argv, "-log")) { argv++, argc--; image->LoG(); } else if (!strcmp(*argv, "-saturation")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -= 2; image->ChangeSaturation(factor); } else if (!strcmp(*argv, "-harris")) { CheckOption(*argv, argc, 2); double sigma = atof(argv[1]); argv += 2, argc -= 2; image->Harris(sigma); } else if (!strcmp(*argv, "-blur")) { CheckOption(*argv, argc, 2); double sigma = atof(argv[1]); argv += 2, argc -= 2; image->Blur(sigma); } else if (!strcmp(*argv, "-sharpen")) { argv++, argc--; image->Sharpen(); } else if (!strcmp(*argv, "-matchTranslation")) { CheckOption(*argv, argc, 2); R2Image *other_image = new R2Image(argv[1]); argv += 2, argc -= 2; image->blendOtherImageTranslated(other_image); delete other_image; } else if (!strcmp(*argv, "-matchHomography")) { CheckOption(*argv, argc, 2); R2Image *other_image = new R2Image(argv[1]); argv += 2, argc -= 2; image->blendOtherImageHomography(other_image); delete other_image; } else { // Unrecognized program argument fprintf(stderr, "image: invalid option: %s\n", *argv); ShowUsage(); } } // Write output image if (!image->Write(output_image_name)) { fprintf(stderr, "Unable to read image from %s\n", output_image_name); exit(-1); } // Delete image delete image; // Return success return EXIT_SUCCESS; }
int main(int argc, char **argv) { // Look for help for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], "-help")) { ShowUsage(); } } // Read input and output image filenames if (argc < 3) ShowUsage(); argv++, argc--; // First argument is program name char *input_image_name = *argv; argv++, argc--; char *output_image_name = *argv; argv++, argc--; // Allocate image R2Image *image = new R2Image(); if (!image) { fprintf(stderr, "Unable to allocate image\n"); exit(-1); } // Read input image if (!image->Read(input_image_name)) { fprintf(stderr, "Unable to read image from %s\n", input_image_name); exit(-1); } // Initialize sampling method int sampling_method = R2_IMAGE_POINT_SAMPLING; // Parse arguments and perform operations while (argc > 0) { if (!strcmp(*argv, "-bilateral")) { CheckOption(*argv, argc, 3); double sx = atof(argv[1]); double sy = atof(argv[2]); argv += 3, argc -= 3; image->BilateralFilter(sy, sx); } else if (!strcmp(*argv, "-blackandwhite")) { argv++, argc--; image->BlackAndWhite(); } else if (!strcmp(*argv, "-blur")) { CheckOption(*argv, argc, 2); double sigma = atof(argv[1]); argv += 2, argc -= 2; image->Blur(sigma); } else if (!strcmp(*argv, "-brightness")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -=2; image->Brighten(factor); } else if (!strcmp(*argv, "-composite")) { CheckOption(*argv, argc, 5); R2Image *top_image = new R2Image(argv[2]); R2Image *bottom_mask = new R2Image(argv[1]); R2Image *top_mask = new R2Image(argv[3]); int operation = atoi(argv[4]); argv += 5, argc -= 5; image->CopyChannel(*bottom_mask, R2_IMAGE_BLUE_CHANNEL, R2_IMAGE_ALPHA_CHANNEL); top_image->CopyChannel(*top_mask, R2_IMAGE_BLUE_CHANNEL, R2_IMAGE_ALPHA_CHANNEL); image->Composite(*top_image, operation); delete top_image; delete bottom_mask; delete top_mask; } else if (!strcmp(*argv, "-contrast")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -= 2; image->ChangeContrast(factor); } else if (!strcmp(*argv, "-crop")) { CheckOption(*argv, argc, 5); int x = atoi(argv[1]); int y = atoi(argv[2]); int w = atoi(argv[3]); int h = atoi(argv[4]); argv += 5, argc -= 5; image->Crop(x, y, w, h); } else if (!strcmp(*argv, "-dither")) { CheckOption(*argv, argc, 3); int dither_method = atoi(argv[1]); int nbits = atoi(argv[2]); argv += 3, argc -= 3; if (dither_method == 0) image->RandomDither(nbits); else if (dither_method == 1) image->OrderedDither(nbits); else if (dither_method == 2) image->FloydSteinbergDither(nbits); else { fprintf(stderr, "Invalid dither method: %d\n", dither_method); exit(-1); } } else if (!strcmp(*argv, "-edge")) { argv++, argc--; image->EdgeDetect(); } else if (!strcmp(*argv, "-extract")) { CheckOption(*argv, argc, 2); int channel = atoi(argv[1]); argv += 2, argc -= 2; image->ExtractChannel(channel); } else if (!strcmp(*argv, "-fun")) { image->Fun(sampling_method); argv++, argc--; } else if (!strcmp(*argv, "-gamma")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -= 2; image->ApplyGamma(factor); } else if (!strcmp(*argv, "-median")) { CheckOption(*argv, argc, 2); double sigma = atof(argv[1]); argv += 2, argc -= 2; image->MedianFilter(sigma); } else if (!strcmp(*argv, "-motionblur")) { CheckOption(*argv, argc, 1); int amount = atoi(argv[1]); argv += 2, argc -= 2; image->MotionBlur(amount); } else if (!strcmp(*argv, "-morph")) { int nsegments = 0; R2Segment *source_segments = NULL; R2Segment *target_segments = NULL; CheckOption(*argv, argc, 4); R2Image *target_image = new R2Image(argv[1]); ReadCorrespondences(argv[2], source_segments, target_segments, nsegments); double t = atof(argv[3]); argv += 4, argc -= 4; image->Morph(*target_image, source_segments, target_segments, nsegments, t, sampling_method); delete target_image; } else if (!strcmp(*argv, "-noise")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -= 2; image->AddNoise(factor); } else if (!strcmp(*argv, "-quantize")) { CheckOption(*argv, argc, 2); int nbits = atoi(argv[1]); argv += 2, argc -= 2; image->Quantize(nbits); } else if (!strcmp(*argv, "-rotate")) { CheckOption(*argv, argc, 2); double angle = atof(argv[1]); argv += 2, argc -= 2; image->Rotate(angle, sampling_method); } else if (!strcmp(*argv, "-sampling")) { CheckOption(*argv, argc, 2); sampling_method = atoi(argv[1]); argv += 2, argc -= 2; } else if (!strcmp(*argv, "-saturation")) { CheckOption(*argv, argc, 2); double factor = atof(argv[1]); argv += 2, argc -= 2; image->ChangeSaturation(factor); } else if (!strcmp(*argv, "-scale")) { CheckOption(*argv, argc, 3); double sx = atof(argv[1]); double sy = atof(argv[2]); argv += 3, argc -= 3; image->Scale(sx, sy, sampling_method); } else if (!strcmp(*argv, "-sharpen")) { argv++, argc--; image->Sharpen(); } else { // Unrecognized program argument fprintf(stderr, "image: invalid option: %s\n", *argv); ShowUsage(); } } // Write output image if (!image->Write(output_image_name)) { fprintf(stderr, "Unable to write image to %s\n", output_image_name); exit(-1); } // Delete image delete image; // Return success return EXIT_SUCCESS; }