/* * Generate a gradient picture. Size nrow, ncol given on the command line, * or promted for if absent. */ #include #include #include #include "img.h" using namespace std; // This represents a color delta for a pixel. class pixel_delta { public: pixel_delta(): m_dr(0), m_dg(0), m_db(0) { } // Set an increment at random, choosing a random amount for each // component within the range. void set_rand(double min, double max) { m_dr = randlev(min, max); m_dg = randlev(min, max); m_db = randlev(min, max); } // Construct a random increment. pixel_delta(double min, double max) { set_rand(min,max); } // Apply this increment to a pixel, with reversal. If the pixel // goes below 0, its sign is reversed, and so is the sign of the // increment, so progress reverses direction. Likewise, if the // value exceeds 1.0, each is reversed. void inc_point(pixel &px) { px.r(inclev(px.r(),m_dr)); px.g(inclev(px.g(),m_dg)); px.b(inclev(px.b(),m_db)); } // Change sign of increment. void reverse() { m_dr = -m_dr; m_dg = -m_dg; m_db = -m_db; } private: // Choose a random double in range min to max. double randlev(double min, double max) { return (max - min) * (double)rand() / RAND_MAX + min; } // Increment a component and reverse direction as needed. The inc // is added to the component level (lev), and if the level becomes // too large or small, "bounces" off the edge and the sign of inc // is reversed. While the increment may be negative, lev should be // in the range 0.0 to 1.0. The increment should have absolute // value <= 1.0. double inclev(double lev, double &inc) { // Just increment, then make direction corrections. lev += inc; // Take action when we hit an edge. if(lev < 0.0) { // Too far down. Head up. lev = -lev; inc = -inc; } else if(lev > 1.0) { // Too far up, head down. lev = 2.0 - lev; inc = -inc; } return lev; } double m_dr, m_dg, m_db; }; // Prompt and read a parameter. template Dtype prompt_read(string prompt) { cout << prompt << ": "; Dtype ret; cin >> ret; return ret; } int main(int argc, char **argv) { // Get file name. string fn; if(argc >= 2) fn = argv[1]; else fn = prompt_read("File name to write"); // Get the number of rows. int nrow; if(argc >= 3) nrow = atoi(argv[2]); else nrow = prompt_read("Number of rows"); // Get the number of cols. int ncol; if(argc >= 4) ncol = atoi(argv[3]); else ncol = prompt_read("Number of columns"); if(nrow <= 0 || ncol <= 0) { cerr << "Illegal size image" << endl; exit(2); } // Make random stuff really random. srand(time(0)); // Create the image object. image im(nrow, ncol); // Choose an initial color. pixel color; color.random(); // Choose a left-to-right increment. pixel_delta hinc(-0.007, 0.007); // Choose a top-to-bottom increment. pixel_delta vinc(-0.005, 0.005); // Vertical offset for each colum which keeps the left-right scan // from being exactly left-right. double voffset = (double)(rand() % (2*ncol)) / ncol; // Scan through the rows for color generation. for(int row = 0; row < nrow; ++row) { // Remember to starting color and starting row incr pixel rowstart(color); pixel_delta incstart(hinc); // Fill the row for(int col = 0; col < ncol; ++col) { // perform the offset for this colum. int orow = (int)(row + col*voffset) % nrow; // Set the pixel. im.set(orow, col, rowstart); incstart.inc_point(rowstart); } // Increment for the row. if(row == nrow / 2) { vinc.reverse(); } vinc.inc_point(color); } // Generate the image file. im.save(fn); }