These solutions are for the exclusive use of students enrolled in SI 204 at USNA in Spring 2017. Any other copying or distribution is a violation of the honor concept.
/* SI204 Spring 2017
* Lab 6: Green screening
* SAMPLE SOLUTIONS by Dr. Roche
*/
#include <stdio.h>
#include <assert.h>
typedef char cstring[128];
/****************************************************************
* FUNCTION PROTOTYPES
****************************************************************/
int fread_int(FILE* in);
int fread_byte(FILE* in);
void fwrite_int(int data, FILE* out);
void fwrite_byte(unsigned char data, FILE* out);
void read_bmp_head(int* wptr, int* hptr, FILE* in);
void write_bmp_head(int width, int height, FILE* out);
void read_color(int* rptr, int* gptr, int* bptr, FILE* in);
void write_color(int red, int green, int blue, FILE* out);
/****************************************************************
* MAIN FUNCTION
****************************************************************/
int main() {
int check;
// read input filename
cstring infile;
printf("Input file: ");
fflush(stdout);
check = scanf(" %s", infile);
assert (check == 1);
FILE* fin = fopen(infile, "rb");
if (! fin) {
printf("ERROR: file not found\n");
return 1;
}
// read output filename
cstring outfile;
printf("Output file: ");
fflush(stdout);
check = scanf(" %s", outfile);
assert (check == 1);
FILE* fout = fopen(outfile, "wb");
// read color replacement
int rered;
int regreen;
int reblue;
printf("Replacement color values (RGB): ");
fflush(stdout);
check = scanf(" %d %d %d", &rered, ®reen, &reblue);
assert (check == 3);
// compute image parameters from input file
int width;
int height;
read_bmp_head(&width, &height, fin);
// start output file
write_bmp_head(width, height, fout);
// read and write pixel data
for (int ycoord=0; ycoord < height; ++ycoord) {
for (int xcoord=0; xcoord < width; ++xcoord) {
int r, g, b;
read_color(&r, &g, &b, fin);
if (r == 0 && g == 255 && b == 0) {
// replace green pixels
write_color(rered, regreen, reblue, fout);
} else {
// non-green; write out original again
write_color(r, g, b, fout);
}
}
}
// all done!
fclose(fin);
fclose(fout);
printf("Image saved to %s\n", outfile);
return 0;
}
/****************************************************************
* FUNCTION DEFINITIONS
****************************************************************/
int fread_int(FILE* in) {
int ans;
int check = fread(&ans, sizeof(int), 1, in);
assert (check == 1);
return ans;
}
int fread_byte(FILE* in) {
unsigned char ans;
int check = fread(&ans, sizeof(char), 1, in);
assert (check == 1);
return ans;
};
void fwrite_int(int data, FILE* out) {
fwrite(&data, sizeof(int), 1, out);
}
void fwrite_byte(unsigned char data, FILE* out) {
fwrite(&data, sizeof(char), 1, out);
}
void read_bmp_head(int* wptr, int* hptr, FILE* in) {
// variables for important image parameters
int fhlen = 14;
int ihlen = 40;
int fsize;
int temp;
// read file header
temp = fread_byte(in); // magic number part 1
assert (temp == 'B');
temp = fread_byte(in); // magic number part 2
assert (temp == 'M');
fsize = fread_int(in); // file size
fread_int(in); // unused 4 bytes
temp = fread_int(in); // pixels offset
assert (temp == fhlen + ihlen);
// read image header
temp = fread_int(in); // image header length
assert (temp == ihlen);
*wptr = fread_int(in); // image width
*hptr = fread_int(in); // image height
temp = fread_int(in); // 1 image plane, 24 bits per pixel
assert (temp == 1 + (24 << 16));
temp = fread_int(in); // compression type
assert (temp == 0);
fread_int(in); // image size (ignored)
fread_int(in); // horiz resolution (ignored)
fread_int(in); // vertical resolution (ignored)
temp = fread_int(in); // color map entries used
assert (temp == 0);
fread_int(in); // # of "important" colors (ignored)
// check file size
int rowlen = *wptr * 3;
int pixlen = *hptr * rowlen;
assert (fsize == fhlen + ihlen + pixlen);
}
void write_bmp_head(int width, int height, FILE* out) {
// compute image parameters
int fhlen = 14;
int ihlen = 40;
int rowlen = width * 3;
int pixlen = height * rowlen;
// file header
fwrite_byte('B', out); // magic number part 1
fwrite_byte('M', out); // magic number part 2
fwrite_int(fhlen + ihlen + pixlen, out); // file size
fwrite_int(0, out); // unused 4 bytes
fwrite_int(fhlen + ihlen, out); // pixels offset
// image header
fwrite_int(ihlen, out); // image header length
fwrite_int(width, out); // image width
fwrite_int(height, out); // image height
fwrite_int(1 + (24 << 16), out); // 1 image plane, 24 bits per pixel
fwrite_int(0, out); // compression type
fwrite_int(0, out); // image size (0 for uncompressed)
fwrite_int(0, out); // horiz resolution (0 for default)
fwrite_int(0, out); // vertical resolution (0 for default)
fwrite_int(0, out); // color map entries used
fwrite_int(0, out); // # of "important" colors (0 means all)
}
void read_color(int* rptr, int* gptr, int* bptr, FILE* in) {
// note: pixels are in reverse order BGR
*bptr = fread_byte(in);
*gptr = fread_byte(in);
*rptr = fread_byte(in);
}
void write_color(int red, int green, int blue, FILE* out) {
// note: pixels are in reverse order BGR
fwrite_byte(blue, out);
fwrite_byte(green, out);
fwrite_byte(red, out);
}