Asg 4: Color to greyscale image conversion

Objectives

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).

Assignment

  1. Create two modules, ppm.c and pgm.c, each implementation file with its own header.
  2. The ppm image module should take care of converting the color image to a greyscale image.
  3. The main.c code driver tests the modules by:
    1. calling ppm_read(...) to read in the PPM image
    2. calling ppm_togrey(...) to convert the PPM image
    3. calling pgm_write(...) to output the PGM image
    4. calling ppm_free(...) to free PPM image memory
    5. calling pgm_free(...) to free PGM image memory

Details

  1. The bulk of the code for this project sits in the I/O functions for reading and writing PPM and PGM image files.
  2. You should develop this project incrementally where you first write code for the PGM image, test it by reading and writing (e.g., copying) a PGM image–if you can copy an image without distorting it in any way, your I/O routines are working.
  3. After you have the PGM image code working, you basically just copy it to ppm.c and use three (1D) arrays for the R, G, B channels.
  4. The tricky part of this project is proper use of header files.
  5. Here is a working pgm.h header:
    #ifndef PGM_H
    #define PGM_H
    
    typedef struct {
            char            *name;  // filename
            int             cols;   // width
            int             rows;   // height
            int             maxc;   // max color (usually 255)
            char            *magic; // magic number (expect 'P5')
            float           *data;  // the pixels, stored as 1D array
    } PGM;
    
    PGM     *pgm_alloc(int r, int c);
    void     pgm_free(PGM **img);
    int      pgm_read(const char *file);
    int      pgm_write(PGM *img, const char *file);
    void     pgm_white(PGM *img);
    #endif
    	

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 = gcc
    
    INCLUDE = -I.
    
    CFLAGS = -g
    
    LDFLAGS = -L. -L/usr/lib
    
    LDLIBS = -lc -lm
    
    .c.o:
    	$(CC) $(INCLUDE) $(CFLAGS) -c -o $@ $<
    
    all: main
    
    main: pgm.o ppm.o main.o
    	$(CC) -o $@ $@.o pgm.o ppm.o $(LDFLAGS) $(LDLIBS)
    
    main.o: main.c
    
    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