Asg 3: Color to greyscale image conversion

Objective

Implement a basic color-to-greyscale image converter. A popular approach is to use the luminosity method, where each greyscale pixel is computed as a weighted average of the three R, G, B color pixels, i.e., 0.21 R + 0.72 G + 0.07 B (see this page for an example, and a couple of alternatives), where each of the R, G, B values is a float in range [0,1].

Assignment

  1. Create two modules, ppm.cpp and pgm.cpp, each implementation file with its own header, defining two classes, ppm_t and pgm_t, respectively.
  2. Note that ppm_t is a subclass of and derived from pgm_t, since it extends the latter.
  3. The pgm class should take care of converting the color image to a greyscale image.
  4. The main.cpp code driver tests the modules by:
    1. calling ppm_t(...) constructor to read in the PPM image
    2. calling pgm_t(...) copy constructor to convert the PPM image
    3. calling std::ofstream << to write out the PGM image
    4. both class destructors are implicitly called at program end

Further Suggestions

  1. Using a copy constructor for pgm_t with a const ppm_t& as argument will require forward declaration of the class.
  2. You will likely need to write a rename() member function to rename the newly created pgm_t image.
  3. You should develop this project incrementally where you first write code for the pgm_t image, test it by reading and writing (e.g., copying) a pgm_t image class—if you can copy an image without distorting it in any way, your I/O routines are working. Repeat the process for the ppm_t class to make sure you can copy a PPM image without distorting it.
  4. After you have the pgm_t image code working, subclass it to create a mostly empty ppm_t class, save for two additional data members: float *rpix; and float *bpix; which hold the red and blue pixel values, respectively (the float *gpix; holding the green pixel values is inherited from the pgm_t base class).

Example Program Input


(right-click to Save As mandrill.ppm)

Example Program Output

Supplemental

  1. If you call your source code file main.c here is a Makefile that you can use to try to compile the project:
    CC = g++
    
    INCLUDE = -I.
    
    CFLAGS = -g
    
    LDFLAGS = -L. -L/usr/lib
    
    LDLIBS = -lc -lm
    
    .cpp.o:
    	$(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $<
    
    OBJS = \
    ppm.o \
    pgm.o
    
    all: main
    
    main: main.o main.cpp $(OBJS)
    	$(CC) $(CFLAGS) -o $@ $@.o $(OBJS) $(LDFLAGS) $(LDLIBS)
    
    main.o: main.cpp
    pgm.o: pgm.cpp
    ppm.o: ppm.cpp
    
    clean:
    	rm -f *.o
    	rm -rf main
    	
    Note that each line underneath the targets is indented by a tab, not just spaces, this is important!

Turn in

Turn in all of your code, in one tar.gz archive of your asg##/ directory, including:
  1. A README file containing
    1. Course id--section no
    2. Name
    3. Brief solution description (e.g., program design, description of algorithm, etc., however appropriate).
    4. Lessons learned, identified interesting features of your program
    5. Any special usage instructions
  2. Makefile
  3. source code (.h headers and .c source)
  4. object code (do a make clean before tar)

How to hand in

See handin notes

Grading scheme