The unified diff between revisions [45197df6..] and [0612e061..] is displayed below. It can also be downloaded as a raw diff.

#
#
# patch "aca319/lab8q1.c"
#  from [7a174ce6c938185e31421514b55073736fae82fe]
#    to [f391acba5e0138fd0d949368633dcaef74671351]
#
============================================================
--- aca319/lab8q1.c	7a174ce6c938185e31421514b55073736fae82fe
+++ aca319/lab8q1.c	f391acba5e0138fd0d949368633dcaef74671351
@@ -3,11 +3,12 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
+#include <math.h>

-#define POINTER(img,x,y)		(img+(3 * (((x)*width)+(y))) )
+#define POINTER(img,x,y)		(img+(((x)*width)+(y)))

 unsigned char *
-load_ppm(const unsigned char *filename, int *width, int *height)
+load_pgm(const unsigned char *filename, int *width, int *height)
 {
 	FILE *f = fopen(filename, "r");
 	int v, mv;
@@ -17,7 +18,7 @@ load_ppm(const unsigned char *filename,
 		fprintf(stderr, "Unable to load input file: %s\n", filename);
 		return NULL;
 	}
-	if ((fscanf(f, "P%d\n", &v) == EOF) || (v != 6)) {
+	if ((fscanf(f, "P%d\n", &v) == EOF) || (v != 5)) {
 		fprintf(stderr, "Wrong file version.\n");
 		return NULL;
 	}
@@ -34,12 +35,12 @@ load_ppm(const unsigned char *filename,
 		fprintf(stderr, "Unable to allocate image buffer\n");
 		return NULL;
 	}
-	fread(rv, sizeof(unsigned char), *height * *width * 3, f);
+	fread(rv, sizeof(unsigned char), *height * *width, f);
 	return rv;
 }

 void
-write_ppm(const unsigned char *filename, int width, int height, const unsigned char *data)
+write_pgm(const unsigned char *filename, int width, int height, const unsigned char *data)
 {
 	FILE *out;

@@ -48,49 +49,49 @@ write_ppm(const unsigned char *filename,
 		fprintf(stderr, "Unable to open output file.\n");
 		return;
 	}
-	fprintf(out, "P6\n%d %d\n255\n", width, height);
-	fwrite(data, sizeof(unsigned char), width*height*3, out);
+	fprintf(out, "P5\n%d %d\n255\n", width, height);
+	fwrite(data, sizeof(unsigned char), width*height, out);
 	fclose(out);
 }

-void
-minimum(const unsigned char **pixels, int count, char *result)
+unsigned char
+minimum(const unsigned char **pixels, int count)
 {
-	int i, p;
-	for (p=0;p<3;p++) {
-		result[p] = *(pixels[0] + p);
-		for (i=0;i<count;i++) {
-			if (*(pixels[i] + p) < result[p])
-				result[p] = *(pixels[i] + p);
-		}
+	int i;
+	unsigned char rv;
+
+	rv = *(pixels[0]);
+	for (i=1;i<count;i++) {
+		if (*(pixels[i]) < rv)
+			rv = *(pixels[i]);
 	}
+	return rv;
 }

-void
-maximum(const unsigned char **pixels, int count, char *result)
+unsigned char
+maximum(const unsigned char **pixels, int count)
 {
-	int i, p;
-	for (p=0;p<3;p++) {
-		result[p] = *(pixels[0] + p);
-		for (i=0;i<count;i++) {
-			if (*(pixels[i] + p) > result[p])
-				result[p] = *(pixels[i] + p);
-		}
+	int i;
+	unsigned char rv;
+
+	rv = *(pixels[0]);
+	for (i=1;i<count;i++) {
+		if (*(pixels[i]) > rv)
+			rv = *(pixels[i]);
 	}
+	return rv;
 }

-void
-average(const unsigned char **pixels, int count, char *result)
+unsigned char
+average(const unsigned char **pixels, int count)
 {
-	int i, p;
+	int i;
+	int total = 0;

-	for (p=0;p<3;p++) {
-		int total = 0;
-		for (i=0;i<count;i++) {
-			total += *(pixels[i] + p);
-		}
-		result[p] = total / count;
+	for (i=0;i<count;i++) {
+		total += *(pixels[i]);
 	}
+	return total / count;
 }

 int
@@ -101,10 +102,10 @@ char_compare(const void *a, const void *
 	return c - d;
 }

-void
-median(const unsigned char **pixels, int count, char *result)
+unsigned char
+median(const unsigned char **pixels, int count)
 {
-	int i, p;
+	int i;
 	int median;

 	unsigned char *s = calloc(count, sizeof(unsigned char));
@@ -112,47 +113,45 @@ median(const unsigned char **pixels, int
 		fprintf(stderr, "Out of memory in median()\n");
 	}

-	for (p=0;p<3;p++) {
-		for (i=0;i<count;i++) {
-			s[i] = *(pixels[i] + p);
-		}
-		qsort(s, count, sizeof(unsigned char), char_compare);
-		if (count % 2) {
-			/* average the two middle values to get median */
-			median = (s[count/2] + s[(count/2)+1]) / 2;
-		} else {
-			median = s[count/2];
-		}
-		result[p] = median;
+	for (i=0;i<count;i++) {
+		s[i] = *(pixels[i]);
 	}
+	qsort(s, count, sizeof(unsigned char), char_compare);
+	if (count % 2) {
+		/* average the two middle values to get median */
+		median = (s[count/2] + s[(count/2)+1]) / 2;
+	} else {
+		median = s[count/2];
+	}
 	free(s);
+	return median;
 }

 unsigned char *
 run_filter(const unsigned char *clean_image, const unsigned char *dirty_image,
 		int width, int height,
-		void (*filter_function)(const unsigned char **, int, char *),
+		unsigned char (*filter_function)(const unsigned char **, int),
 		double *error)
 {
 	unsigned char *rv;
 	int i, j;
 	const unsigned char *cells[9];
+	unsigned long long error_count=0;

 	assert(clean_image != NULL);
 	assert(dirty_image != NULL);
 	assert(error != NULL);

-	rv = calloc(sizeof(unsigned char), height * width * 3);
+	rv = calloc(sizeof(unsigned char), height * width);
 	if (!rv) {
 		fprintf(stderr, "Out of memory in run_filter\n");
 		return NULL;
 	}

-	fprintf(stderr, "Applying filter to image of size %dx%d\n", width, height);
-
 	for (i=0;i<height;i++) {
 		for (j=0;j<width;j++) {
 			const unsigned char *clean, *unfiltered;
+			unsigned char filtered;
 			int count;

 			clean = POINTER(clean_image, i, j);
@@ -197,11 +196,14 @@ run_filter(const unsigned char *clean_im
 				cells[count] = POINTER(dirty_image, i+1, j+1);
 				count++;
 			}
-
-			filter_function(cells, count, rv + (3 * ((i*width) + j)));
+			filtered = filter_function(cells, count);
+			*POINTER(rv, i, j) = filtered;
+			error_count += ((unsigned int)*clean - (unsigned int)filtered) * ((unsigned int)*clean - (unsigned int)filtered);
 		}
 	}

+	*error = error_count / (width * height);
+
 	return rv;
 }

@@ -213,24 +215,28 @@ main(int argc, char *argv[])
 	unsigned char *clean, *noisy;
 	unsigned char *result;

-	clean = load_ppm("ViGIR.ppm", &width, &height);
-	noisy = load_ppm("ViGIRnoisy.ppm", &width, &height);
+	clean = load_pgm("ViGIR.pgm", &width, &height);
+	noisy = load_pgm("ViGIRnoisy.pgm", &width, &height);

-//	write_ppm("bypass.ppm", width, height, noisy);
+//	write_pgm("bypass.pgm", width, height, noisy);
 	result = run_filter(clean, noisy, width, height, minimum, &error);
-	write_ppm("minimum.ppm", width, height, result);
+	printf("Minimum: error is %f\n", error);
+	write_pgm("minimum.pgm", width, height, result);
 	free(result);

 	result = run_filter(clean, noisy, width, height, maximum, &error);
-	write_ppm("maximum.ppm", width, height, result);
+	printf("Maximum: error is %f\n", error);
+	write_pgm("maximum.pgm", width, height, result);
 	free(result);

 	result = run_filter(clean, noisy, width, height, average, &error);
-	write_ppm("average.ppm", width, height, result);
+	printf("Average: error is %f\n", error);
+	write_pgm("average.pgm", width, height, result);
 	free(result);

 	result = run_filter(clean, noisy, width, height, median, &error);
-	write_ppm("median.ppm", width, height, result);
+	printf("Median: error is %f\n", error);
+	write_pgm("median.pgm", width, height, result);
 	free(result);

 	free(clean);