Modified 3/5 to add a needed #include directive to circles.cpp, update the Makefile to work better with JGrasp, and add some additional advice at the bottom of this page.
This project involves writing a small piece to complete a larger program. There's a good bit of code here, but you don't have to write very much. You are given several files, including two example mains, and are to supply some missing classes to complete the larger programs. These will then need to be compiled from multiple files, the ones given and the ones you write. The grad program creates randomly-generated images that might be suitable for desktop backgrounds and such. Here is one:
When the program is run, it needs the name of the file to write, and the numbers of rows and columns (height and width) in pixels. You can specify these on the command line, or it will ask for these if they are missing. The above picture was created by running grad example1.jpg 100 400.
Grad produces a standard jpg file which you can view in a browser or most any sort of image software.
The files jpge.h and jpge.cpp provide the class jpeg_writer which can write a stream of pixels to a file to form an image. It is based on this code, with a simplified interface. Look at class jpeg_writer to see all of the several methods, but the most relevant ones are:
Another is grad.cpp which is the program mentioned above that generates a random gradient image (after you supply a couple of needed classes). It needs to know a file name, number of rows, and number of columns, which can be given on the command line, or the program will ask for them if not.
Finally, the program circles.cpp generates a picture with random circles. Runing it is similar, except it also asks how many circles to draw. These are all given random colors, sizes, and positions, and written on a randomly-colored background.
The pixel class should be fairly straightforward. It holds three private double values and implements the methods described. The byte values returned by rb, gb, bb are computed by multiplying the component brightness, 0.0 through 1.0 by 255.
To generate a random color value, use the library rand() call. This returns an integer, as the documentation says, in the range 0 to RAND_MAX. So, to create a random number from 0.0 to 1.0, compute rand()/RAND_MAX, with appropriate casting, so you get a floating point division. Your class does not need to call srand.
| 0,0 | 0,1 | 0,2 | 0,3 |
| 1,0 | 1,1 | 1,2 | 1,3 |
| 2,0 | 2,1 | 2,2 | 2,3 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0,0 | 0,1 | 0,2 | 0,3 | 1,0 | 1,1 | 1,2 | 1,3 | 2,0 | 2,1 | 2,2 | 2,3 |
Option 2 is to actually store in two dimensions, using a vector of vectors. If you do this you can reach a pixel directly, as v[1][2]. Since vectors are generally born empty, either solution requires your constructor to fill the vector with the default pixel, either white or the one provided. (You might check out the resize method.) The two-dimensional version will be more complicated to initialize, since you will need to resize both the base vector, then the vector for each row, probably needing a loop.
Your save method will use the jpeg_writer object as described above. Just create the object, then loop through the image data and add each pixel. For option 1 above, just loop through the vector. Option 2 will need a double loop, outer through rows and inner through the contents of the row. Use the unsigned byte values of the colors since that's what that class expects.
I was lazy and put both my pixel and image classes in a single .h file. You may do that, or place each class in its own .h file. You can also split into .h and .cpp files if you have a long method. Your .h file (or files) should use the #ifndef/#define/#endif madness to prevent multiple definition errors, as discussed in class.
If you are using CodeBlocks, you will need t create a project and add all your files to it. Other IDEs may work this way as well.
If you are using an IDE, a fairly smart one should be able to figure out how to build the programs. The commands for grad are given here. If you don't create your own .cpp file, omit mention of yours.cpp and yours.o.
If you download the zip file above, it includes a Makefile that will automate the build on a Unix (or probably Mac) command line. It assumes that you put your class in img.h and did not create an img.cpp. If you do otherwise, edit the names or add the img.cpp as shown in comments. Then say make grad or make circles.
It is very helpful to create stub versions of the two required classes. The two existing programs, grad.cpp and circles.cpp, assume these are together in a file called img.h. (You may change this name by modifying the #include directives in those files, and also any references in the Makefile, if you are using that.)
Making stubs can be useful to get your compiling setup before you have to start thinking about how to make everything work. Just create a file, probably img.h, in which you define the two classes. For each, create a definition of each public method having the correct parameter types and return value, but doing nothing. Void functions will have empty bodies. A function with a real return value will need to have just a return statement sending a constant of the appropriate type. Add this to the other files, and you should be able to compile an executable. Then you can start filling in object data and correct methods so it actually works. Building a stub file is a bit tedious, but not difficult, and will help get yout started.
But, when I tried it on Windows in the lab, this didn't work because JGrasp could not find the make program. (It does actually tell you that make was not found.) It may work fine for you; it depends on where you got your C++ compiler.
The lab computer got its C++ compiler from the installation of CodeBlocks, and the problem is that they install make under a different name. I could not find a way to tell JGrasp to use a different name, so I told the system to do so. CodeBlocks stores its compiler files in the directory C:\Program Files\CodeBlocks\MinGW\bin. The make program is called mingw32-make instead of just make. To fix this, I created a text file under the name C:\Program Files\CodeBlocks\MinGW\bin\make.bat containing the single line mingw32-make %*. This makes a Windows batch file for the make command, that simply runs the actual command under its different name. This fixed the problem. If you got your C++ by installing the mingw compiler directly as described here, then you may have the same problem, except you will need to store the bat file file in C:\MinGW\bin instead of C:\Program Files\CodeBlocks\MinGW\bin.