/** * Tests the collage code with the appropriate algorithm. */ void testCollage(DrawAlgorithm algorithm) { cout << "Testing collage:" << endl; vector<PNG> layers = setupImages(); vector<Point> coords = setupPoints(); Collage collage(layers, coords); double startTime = omp_get_wtime(); PNG* result = collage.draw(algorithm, true); double endTime = omp_get_wtime(); double parallelTime = endTime - startTime; cout << " - saving image" << endl; result->writeToFile("collage.png"); cout << "Elapsed collage time: " << parallelTime << endl; cout << "Checking correctness: "; bool correct = collage.checkCorrectness(*result); cout << (correct ? makeGreen("PASS") : makeRed("FAIL") + " (the images are different)") << endl; delete result; startTime = omp_get_wtime(); result = collage.draw(algorithm, false); endTime = omp_get_wtime(); cout << "Speedup: " << (endTime - startTime) / parallelTime << endl; delete result; }
void testWaterfall() { cout << "[main]: " << __func__ << "()" << endl; PNG in("in_05.png"); List<RGBAPixel> list = imageToList(in); list.waterfall(); PNG out = listToImage(list, in.width(), in.height()); out.writeToFile("waterfall_01.png"); checkSoln(__func__, out, "soln_waterfall_01.png"); in.readFromFile("in_06.png"); list = imageToList(in); list.waterfall(); out = listToImage(list, in.width(), in.height()); out.writeToFile("waterfall_02.png"); checkSoln(__func__, out, "soln_waterfall_02.png"); List<int> list3; for (int i = 1; i <= 8; i++) list3.insertBack(i); list3.waterfall(); //cout << "[waterfall custom]: " << list3 << endl; }
bool rx_save_png(Image& img, std::string filename, bool datapath) { PNG png; png_uint_32 type; if(img.getPixelFormat() == RX_FMT_GRAY8) { type = PNG_COLOR_TYPE_GRAY; } else if(img.getPixelFormat() == RX_FMT_RGB24) { type = PNG_COLOR_TYPE_RGB; } else if(img.getPixelFormat() == RX_FMT_RGBA32) { type = PNG_COLOR_TYPE_RGB_ALPHA; } else { RX_ERROR(ERR_IMG_UNSUPPORTED_FORMAT); return false; } png.setPixels(img.getPixels(), img.getWidth(), img.getHeight(), type); png.save(filename, datapath); return true; }
/** * Tests the image flipping code. */ void testFlip() { PNG image; cout << "Testing in-place image flipper:" << endl; image.readFromFile("images/03_2560x1680.png"); cout << " - flipping image" << endl; double startTime = omp_get_wtime(); Flipper::flipParallel(image); double endTime = omp_get_wtime(); double parallelTime = endTime - startTime; cout << " - saving image" << endl; image.writeToFile("flipped.png"); cout << "Elapsed flip time: " << parallelTime << endl; cout << "Checking correctness: "; bool correct = Flipper::checkCorrectness(image); cout << (correct ? makeGreen("PASS") : makeRed("FAIL") + " (the images are different)") << endl; startTime = omp_get_wtime(); Flipper::flipSerial(image); endTime = omp_get_wtime(); cout << "Speedup: " << (endTime - startTime) / parallelTime << endl; }
int main() { SquareMaze m; m.makeMaze(TEST,TEST); std::cout << "MakeMaze complete" << std::endl; /* for ( int i = 0; i < TEST; i++) { for ( int j = 0; j < TEST ; j++) { cout <<"RIGHT: "<< m.canTravel(i,j,RIGHT)<< " x: "<<i<<" y: "<<j<<endl; cout <<"BOTTOM: "<< m.canTravel(i,j,BOTTOM)<< " x: "<<i<<" y: "<<j<<endl; } } */ PNG* unsolved = m.drawMaze(); unsolved->writeToFile("unsolved.png"); delete unsolved; std::cout << "drawMaze complete" << std::endl; vector<int> sol = m.solveMaze(); std::cout << "solveMaze complete" << std::endl; PNG* solved = m.drawMazeWithSolution(); solved->writeToFile("solved.png"); delete solved; std::cout << "drawMazeWithSolution complete" << std::endl; return 0; }
/** * Tests the image shifting code */ void testShift() { // remove old frames system("rm -rf frames 2> /dev/null"); PNG image; cout << "Testing image shifter:" << endl; image.readFromFile("images/08_1024x768.png"); cout << " - shifting image" << endl; double startTime = omp_get_wtime(); animation anim = Shifter::shiftParallel(image); double endTime = omp_get_wtime(); double parallelTime = endTime - startTime; cout << " - saving image" << endl; anim.write("shifted.gif"); cout << "Elapsed shifting time: " << parallelTime << endl; cout << "Checking correctness: "; bool correct = Shifter::checkCorrectness(); cout << (correct ? makeGreen("PASS") : makeRed("FAIL") + " (the images are different)") << endl; // remove old frames system("rm -rf frames 2> /dev/null"); // calculate speedup startTime = omp_get_wtime(); anim = Shifter::shiftSerial(image); endTime = omp_get_wtime(); cout << "Speedup: " << (endTime - startTime) / parallelTime << endl; }
void Terrain::loadHeightMap(string filename, int res_x, int res_y) { PNG inputFile; inputFile.load(filename); dim_x = inputFile.width; dim_y = inputFile.height; unsigned char * data = inputFile.getData(); int size = dim_x*dim_y; float * originalHeightMap = new float[size]; int i,x,y; for (i=0; i<size; i++){ originalHeightMap[i] = 256*data[2*i]+data[2*i + 1]; } // recalculate to the given resolution (use linear interpolation...) size = res_x*res_y; heightMap = new float[size]; float step_x = float(dim_x)/float(res_x); float step_y = float(dim_y)/float(res_y); for(x=0; x<res_x; x++) { for(y=0; y<res_y; y++) { heightMap[x*res_y + y] = getHeightAt(originalHeightMap, dim_x, dim_y, float(x*step_x), float(y*step_y)); } } SAFE_DELETE_ARRAY_PTR(originalHeightMap); }
void testReverseNth() { cout << "[main]: " << __func__ << "()" << endl; PNG in("in_03.png"); /* List<int> test; for (int i = 1; i <= 11; i++) { test.insertBack(i); } cout<<test<<endl; test.reverseNth(3); cout<<test<<endl; */ List<RGBAPixel> list = imageToList(in); list.reverseNth(in.height() * 20); PNG out = listToImage(list, in.width(), in.height()); out.writeToFile("reverseNth_01.png"); checkSoln(__func__, out, "soln_reverseNth_01.png"); in.readFromFile("in_04.png"); list = imageToList(in); list.reverseNth(in.height() * 61); out = listToImage(list, in.width(), in.height()); out.writeToFile("reverseNth_02.png"); checkSoln(__func__, out, "soln_reverseNth_02.png"); }
void testWaterfall() { List<double> li; cout<<li<<endl; li.waterfall(); cout<<li<<endl; cout << "[main]: " << __func__ << "()" << endl; PNG in("in_05.png"); List<RGBAPixel> list = imageToList(in); list.waterfall(); PNG out = listToImage(list, in.width(), in.height()); out.writeToFile("waterfall_01.png"); checkSoln(__func__, out, "soln_waterfall_01.png"); in.readFromFile("in_06.png"); list = imageToList(in); list.waterfall(); out = listToImage(list, in.width(), in.height()); out.writeToFile("waterfall_02.png"); checkSoln(__func__, out, "soln_waterfall_02.png"); }
int main(int argc, char* argv[]) { const int canvas_width = 128; const int canvas_height = 128; PNG canvas; canvas.resize(canvas_width, canvas_height); const RGBAPixel triangle_color = color::ORANGE; Shape* triangle = new Triangle(triangle_color, Vector2(32, 32), Vector2(64, 64), Vector2(32, 64)); triangle->draw(&canvas); canvas.writeToFile("test_destructor.png"); /* TODO: Why is this leaking memory? Triangle does have a valid destructor!? * Can you stop it from leaking WITHOUT changing triangle's type from a * Shape pointer to a Triangle pointer type? */ delete triangle; triangle = NULL; return 0; }
/** * This function brightens a rectangle of a PNG, increasing the components * (red, green, blue) of each pixel by the given amount. You must account * for potential overflow issues (color components can only store numbers * between 0 and 255). If you attempt to store a value greater than 255 * into a color component, the result will wrap around (and you won't be * able to check if it was greater than 255). * * @param original A PNG object which holds the image data to be modified. * @param amount The integer amount by which to increase each pixel's * components. * * @return The brightened image. */ PNG brighten(PNG original, int amount) { /// You can assume amount is positive. for (size_t yi = 0; yi < original.height(); yi++) { for (size_t xi = 0; xi < original.width(); xi++) { /// Your code here! int blue = original(xi, yi)->blue; int green = original(xi, yi)->green; int red = original(xi, yi)->red; if(red+amount<255) original(xi,yi)->red= red+amount; else original(xi,yi)->red= 255; if(blue+amount<255) original(xi,yi)->blue= blue+amount; else original(xi,yi)->blue= 255; if(green+amount<255) original(xi,yi)->green= green+amount; else original(xi,yi)->green= 255; } } return original; }
/** * Removes an RGB color component from the PNG. * THIS FUNCTION IS GRADED. * @todo - parallelize removeColor() * @param source - the original PNG * @param color - the color to remove * @return - a PNG object with an RGB component taken out * of each pixel (if color parameter is valid) */ PNG ImageTools::removeColor(const PNG & source, const Color & color) { int width = source.width(); int height = source.height(); PNG output(width, height); #pragma omp parallel for for(int i = 0; i < width; ++i) { for(int j = 0; j < height; ++j) { *output(i, j) = *source(i, j); switch(color) { case RED: output(i,j)->red=0; break; case GREEN: output(i,j)->green=0; break; case BLUE: output(i,j)->blue=0; break; } } } return output; }
/** * Makes an animation of an image shifting to the left * @param toShift - the image to be shifted * @return - an animation of the image being shifted */ animation Shifter::shiftParallel(const PNG & toShift) { PNG image = toShift; animation anim; int width = image.width(); int height = image.height(); int shiftAmount = 32; // shift image to the left by 32 pixels each iteration for(int destCol = 0; destCol < width; destCol += 32) { for(int x = 0; x < width - 32; ++x) { #pragma omp parallel for for(int y = 0; y < height; ++y) { *image(x, y) = *image(x + 32, y); } } if(destCol % shiftAmount == 0) { anim.addFrame(image); } } return anim; }
void makePhotoMosaic(const string & inFile, const string & tileDir, int numTiles, int pixelsPerTile, const string & outFile) { PNG inImage(inFile); SourceImage source(inImage, numTiles); vector<TileImage> tiles = getTiles(tileDir); if (tiles.empty()) { cerr << "ERROR: No tile images found in " << tileDir << endl; exit(2); } MosaicCanvas::enableOutput = true; MosaicCanvas * mosaic = mapTiles(source, tiles); cerr << endl; if (mosaic == NULL) { cerr << "ERROR: Mosaic generation failed" << endl; exit(3); } PNG result = mosaic->drawMosaic(pixelsPerTile); cerr << "Saving Output Image... "; result.writeToFile(outFile); cerr << "Done" << endl; delete mosaic; }
/** * This function brightens a rectangle of a PNG, increasing the components * (red, green, blue) of each pixel by the given amount. You must account * for potential overflow issues (color components can only store numbers * between 0 and 255). If you attempt to store a value greater than 255 * into a color component, the result will wrap around (and you won't be * able to check if it was greater than 255). * * @param original A PNG object which holds the image data to be modified. * @param amount The integer amount by which to increase each pixel's * components. * * @return The brightened image. */ PNG brighten(PNG original, int amount) { /// You can assume amount is positive. for (size_t yi = 0; yi < original.height(); yi++) { for (size_t xi = 0; xi < original.width(); xi++) { size_t r = original(xi, yi) -> red; size_t g = original(xi, yi) -> green; size_t b = original(xi, yi) -> blue; r = r + amount; g = g + amount; b = b + amount; if(r > 255){ r = 255; } if(g > 255){ g = 255; } if(b > 255){ b = 255; } original(xi, yi) ->red = r; original(xi, yi) ->green = g; original(xi, yi) ->blue = b; /// Your code here! } } return original; }
void checkSoln(string test, PNG out, string soln_file) { PNG soln; soln.readFromFile(soln_file.c_str()); if (!(soln == out)) cerr << "[" << test << "]: Image does not match " << soln_file << endl; }
int main(int argc, char* argv[]) { const int canvas_width = 128; const int canvas_height = 128; PNG canvas; canvas.resize(canvas_width, canvas_height); Vector2 rectangle_center(canvas_width / 2, canvas_height / 2); const int rectangle_width = canvas_width / 4; const int rectangle_height = canvas_height / 4; Rectangle* rectangle = new Rectangle(rectangle_center, color::BLUE, rectangle_width, rectangle_height); rectangle->draw(&canvas); const int rectangle_perimeter = rectangle->perimeter(); cout << "Rectangle's Perimeter = " << rectangle_perimeter << endl; const int rectangle_area = rectangle->area(); cout << "Rectangle's Area = " << rectangle_area << endl; /* But we can treat a Rectangle just like a Shape using a Shape pointer */ Shape* shape = rectangle; const int shape_perimeter = shape->perimeter(); cout << "Shape's Perimeter = " << shape_perimeter << endl; const int shape_area = shape->area(); cout << "Shape' Area = " << shape_area << endl; /* TODO: For some reason the shape's area and perimeter is different from * triangle's area and perimeter even though they are pointing to the same * object! Can you this this so they are the same WITHOUT changing the * shape's type from a Shape pointer to a Triangle pointer? */ if (rectangle_perimeter == shape_perimeter) { cout << "The Perimeters are the same!" << endl; } else { cout << "The Perimeters are NOT the same." << endl; } if (rectangle_area == shape_area) { cout << "The Areas are the same!" << endl; } else { cout << "The Areas are NOT the same." << endl; } canvas.writeToFile("test_virtual.png"); delete rectangle; return 0; }
bool CTdata::loadFromFiles(const char * filename, int cnt, int scaleX, int scaleY, int scaleZ){ int divide = 2; int chars = 0; scX = scaleX; scY = scaleY; scZ = scaleZ/divide; char filen [50]; unsigned char * rawData; PNG ctfile; int width=0, height=0, width2, height2; int x,y,z; float val; for(z=0; z<cnt; z++){ sprintf(filen, filename, z+1); ctfile.clear(); if (!ctfile.load(filen)){ return false; } rawData = ctfile.getData(); height = ctfile.height; width = ctfile.width; width2 = width/float(divide); height2 = height/float(divide); if (data==NULL){ data = new float[cnt*width2*height2]; //data = new float[cnt*width*height]; } for (y=0; y<height2; y++){ //height for (x=0; x<width2; x++){ //width // 2x 8-bit to 1x 16-bit val = 256*rawData[(2*y*width + 2*x)*divide]+rawData[(2*y*width + 2*x)*divide + 1]; //val = 256*rawData[2*y*width + 2*x]+rawData[2*y*width + 2*x + 1]; // save in array data[z*height2*width2 + y*width2 +(width2-1-x)] = val; //data[z*width*height + y*width +x] = val; } } BACKSPACE(chars); chars = printf("LOADING CT images: %03i %%",((z+1)*100)/cnt); } dimX = width2; dimY = height2; dimZ = cnt; szX = dimX * scX; szY = dimY * scY; szZ = dimZ * scZ; center.x = szX/2.0; center.y = szY/2.0; center.z = szZ/2.0; // backspace... BACKSPACE(chars); printf("LOADING CT images (%i) DONE\n", cnt); return true; }
int main() { PNG oldImage; oldImage.readFromFile("in.png"); size_t vertical = oldImage.height(); size_t horizontal = oldImage.width(); /* * have initialized newImage just so that the pixels are accessable */ PNG newImage; newImage.readFromFile("in.png"); /* * we will flip the image horizontally and vertically to rotate it by 180 degrees */ for (size_t x = 0; x < oldImage.width(); x++) { for (size_t y = 0; y < oldImage.height(); y++) { newImage(horizontal-x-1, vertical-y-1)->red = oldImage(x,y)->red; newImage(horizontal-x-1, vertical-y-1)->green = oldImage(x,y)->green; newImage(horizontal-x-1, vertical-y-1)->blue = oldImage(x,y)->blue; } } newImage.writeToFile("out.png"); }
GLuint OpenGLInterface::LoadTextureFromPNG( const char* fileName, unsigned int tex ) { PNG pngFile; if( pngFile.Load( fileName ) ) { tex = CreateTextureFromImageData( pngFile.GetData(), pngFile.GetWidth(), pngFile.GetHeight(), pngFile.GetHasAlpha(), tex ); } return tex; }
void testReverse() { cout << "[main]: " << __func__ << "()" << endl; PNG in("in_02.png"); List<RGBAPixel> list = imageToList(in); list.reverse(); PNG out = listToImage(list, in.width(), in.height()); out.writeToFile("reverse.png"); checkSoln(__func__, out, "soln_reverse.png"); }
List<RGBAPixel> imageToList(PNG const & img) { List<RGBAPixel> list; for (int i = 0; i < img.width(); i++) { for (int j = 0; j < img.height(); j++) { list.insertFront(*img(i,j)); } } return list; }
/** * This function accepts a PNG object, two integer coordinates and a color, and * proceeds to draw a horizontal line across the image at the y coordinate and * a vertical line down the image at the x coordinage using the given color. * The modified PNG is then returned. * * @param original A PNG object which holds the image data to be modified. * @param centerX The center x coordinate of the crosshair which is to be drawn. * @param centerY The center y coordinate of the crosshair which is to be drawn. * @param color The color of the lines to be drawn. * * @return The image on which a crosshair has been drawn. */ PNG drawCrosshairs(PNG original, int centerX, int centerY, RGBAPixel color) { /// This function is already written for you so you can see how to /// interact with our PNG class. for (size_t x = 0; x < original.width(); x++) *original(x, centerY) = color; for (size_t y = 0; y < original.height(); y++) *original(centerX, y) = color; return original; }
void testSolidFill( const Filler & filler, const string & outputFile ) { PNG img; img.readFromFile( SOLIDTESTIMAGE ); RGBAPixel px( 70, 50, 13 ); animation anim; if( filler == DFS ) anim = filler::dfs::fillSolid( img, SOLIDX, SOLIDY, px, SOLIDTOLERANCE, SOLIDFRAMEFREQ ); else anim = filler::bfs::fillSolid( img, SOLIDX, SOLIDY, px, SOLIDTOLERANCE, SOLIDFRAMEFREQ ); anim.write( outputFile ); cout << "\tWrote " << outputFile << endl; }
void testGridFill( const Filler & filler, const string & outputFile ) { PNG img; img.readFromFile( GRIDTESTIMAGE ); RGBAPixel px( 70, 25, 70 ); animation anim; if( filler == DFS ) anim = filler::dfs::fillGrid( img, GRIDX, GRIDY, px, GRIDGRIDSPACING, GRIDTOLERANCE, GRIDFRAMEFREQ ); else anim = filler::bfs::fillGrid( img, GRIDX, GRIDY, px, GRIDGRIDSPACING, GRIDTOLERANCE, GRIDFRAMEFREQ ); anim.write( outputFile ); cout << "\tWrote " << outputFile << endl; }
/** * This function blends, or averages, two PNGs together. That is, each pixel in * the returned image consists of the averaged components (red, green, blue) of * the two input images. * * @param firstImage The first of the two PNGs to be averaged together. * @param secondImage The second of the two PNGs to be averaged together. * * @return The averaged image. */ PNG blendImages(PNG firstImage, PNG secondImage) { for (size_t yi = 0; yi < firstImage.height(); yi++) { for (size_t xi = 0; xi < firstImage.width(); xi++) { firstImage(xi, yi)->green =(firstImage(xi, yi)->green+secondImage(xi, yi)->green)/2; firstImage(xi, yi)->red =(firstImage(xi, yi)->red+secondImage(xi, yi)->red)/2; firstImage(xi, yi)->blue =(firstImage(xi, yi)->blue+secondImage(xi, yi)->blue)/2; } } return firstImage; }
/** * Simply parses the command line args and runs the appropriate functions. */ int main(int argc, char* argv[]){ if(argc != 5) { cerr << endl; cerr << "Please run as " << argv[0] << " numThreads operation imageName saveFile" << endl; cerr << " numThreads number of threads to use (if #pragma omp... is encountered)" << endl; cerr << " operation \"flip\" or \"remove\"" << endl; cerr << " imageName for example, \"images/01_8182x4096.png\"" << endl; cerr << " saveFile \"yes\" (if you want to save output), \"no\" otherwise" << endl; cerr << endl; return 1; } // set the number of thread for the program to use (the first argument) omp_set_num_threads(atoi(argv[1])); // read the parameter PNG from file string filename(argv[3]); PNG img(filename); PNG output; cout << "Performing operation..." << endl; double start = omp_get_wtime(); double end; if(argv[2][0] == 'f') { output = ImageTools::verticalFlip(img); end = omp_get_wtime(); if(argv[4][0] == 'y') { cout << "Saving image..." << endl; output.writeToFile("flipped.png"); } } else { Color color = GREEN; output = ImageTools::removeColor(img, color); end = omp_get_wtime(); if(argv[4][0] == 'y') { cout << "Saving image..." << endl; output.writeToFile("removed.png"); } } cout << "Total processed pixels: " << img.height() * img.width() << endl; cout << "Time: " << end - start << " seconds" << endl; return 0; }
int main() { // Load in.png PNG * original = new PNG; original -> readFromFile("in.png"); int width = original->width(); int height = original->height(); cout << "width=" << width << " height=" << height << endl; // Create out.png PNG * output; output = setupOutput(width, height); // Loud our favorite color to color the outline RGBAPixel * myPixel = myFavoriteColor(192); // Go over the whole image, and if a pixel differs from that to its upper // left, color it my favorite color in the output for (int y = 1; y < height; y++) { for (int x = 1; x < width; x++) { // Calculate the pixel difference RGBAPixel * prev = (*original)(x - 1, y - 1); RGBAPixel * curr = (*original)(x, y); int diff = abs(curr->red - prev->red ) + abs(curr->green - prev->green) + abs(curr->blue - prev->blue ); // If the pixel is an edge pixel, // color the output pixel with my favorite color RGBAPixel * currOutPixel = (*output)(x,y); if (diff > 100) { currOutPixel->blue = myPixel->blue; currOutPixel->red = myPixel->red; currOutPixel->green = myPixel->green; } } } // Save the output file output->writeToFile("out.png"); // Clean up memory delete myPixel; delete output; delete original; return 0; }
/** * This function brightens a rectangle of a PNG, increasing the components * (red, green, blue) of each pixel by the given amount. You must account * for potential overflow issues (color components can only store numbers * between 0 and 255). If you attempt to store a value greater than 255 * into a color component, the result will wrap around (and you won't be * able to check if it was greater than 255). * * @param original A PNG object which holds the image data to be modified. * @param amount The integer amount by which to increase each pixel's * components. * * @return The brightened image. */ PNG brighten(PNG original, int amount) { /// You can assume amount is positive. for (size_t yi = 0; yi < original.height(); yi++) { for (size_t xi = 0; xi < original.width(); xi++) { /// Your code here! //original(xi,yi)->red = 0; //original(xi,yi)->blue = 0; } } return original; }
bool rx_load_png(Image& img, std::string filename, bool datapath) { PNG png; if(!png.load(filename, datapath)) { return false; } switch(png.getColorType()) { case PNG_COLOR_TYPE_GRAY: { img.setPixelFormat(RX_FMT_GRAY8); break; } case PNG_COLOR_TYPE_RGB: { img.setPixelFormat(RX_FMT_RGB24); break; } case PNG_COLOR_TYPE_RGB_ALPHA: { img.setPixelFormat(RX_FMT_RGBA32); break; } default: { RX_ERROR(PNG_ERR_UNSUPPORTED_FORMAT); return false; } } img.setWidth(png.getWidth()); img.setHeight(png.getHeight()); return img.copyPixels(png.getPixels(), png.getWidth(), png.getHeight(), img.getPixelFormat()); }