Permalink
Browse files

I made it better.

  • Loading branch information...
1 parent 5ff4be1 commit 98d982f0a39c88deae0be15e73d7a19d42f5b481 @hoehrmann committed May 7, 2012
Showing with 89 additions and 54 deletions.
  1. +89 −54 glyphcmp.cxx
View
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <memory.h>
+#include <assert.h>
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define MAX(X, Y) ((X) < (Y) ? (Y) : (X))
@@ -30,8 +31,6 @@
typedef struct {
size_t real_width;
size_t real_height;
- size_t virt_width;
- size_t virt_height;
uint8_t* p;
} image_data;
@@ -41,63 +40,122 @@ debug_write_pgm(image_data* image, char* path) {
if (NULL == f) {
// fopen failed
}
- fprintf(f, "P5\n%u %u\n%u\n", image->virt_width,
- image->virt_height, 255);
- fwrite(image->p, image->virt_width * image->virt_height, 1, f);
+ fprintf(f, "P5\n%u %u\n%u\n", image->real_width,
+ image->real_height, 255);
+ fwrite(image->p, image->real_width * image->real_height, 1, f);
fclose(f);
}
double
create_difference(image_data* left, image_data* right) {
+
+ // TODO: Now that the comments refer to left and right in the spatial
+ // sense, the variables should probably be renamed into A and B or so.
+
+ double area;
+ double result;
+ size_t sum = 0;
image_data* d = (image_data*)malloc(sizeof(image_data));
if (NULL == d) {
// malloc failed
}
- d->real_width = d->virt_width = 2
- + MAX(left->real_width, right->real_width);
- d->real_height = d->virt_height = 2
- + MAX(left->real_height, right->real_height);
+ size_t max_real_width = MAX( left->real_width, right->real_width );
+ size_t min_real_width = MIN( left->real_width, right->real_width );
+ size_t min_real_height = MIN( left->real_height, right->real_height );
+ size_t max_real_height = MAX( left->real_height, right->real_height );
+
+ d->real_width = 2 + max_real_width;
+ d->real_height = 2 + max_real_height;
size_t image_data_byte_count =
- sizeof(*(d->p)) * d->virt_width * d->virt_height;
+ sizeof(*(d->p)) * d->real_width * d->real_height;
d->p = (uint8_t*)malloc(image_data_byte_count);
if (NULL == d->p) {
// malloc failed
}
- memset(d->p, 0xff, image_data_byte_count);
+ // white border left and right
+ for (size_t y = 0; y < d->real_height; ++y) {
+ d->p[y * d->real_width + 0] = 0xFF;
+ d->p[y * d->real_width + d->real_width - 1] = 0xFF;
+ }
- size_t sum = 0;
+ // white border top and bottom
+ for (size_t x = 0; x < d->real_width; ++x) {
+ d->p[0 * d->real_width + x] = 0xFF;
+ d->p[(d->real_height - 1) * d->real_width + x] = 0xFF;
+ }
+
+ // The bottom right part covered by neither `left` nor `right`
+ // unless one image fully contains the other in which case the
+ // later loops will override the value again...
+ for (size_t y = min_real_height; y < max_real_height; ++y) {
+ for (size_t x = min_real_width; x < max_real_width; ++x) {
+ d->p[(y + 1) * d->real_width + (x + 1)] = 0;
+ }
+ }
+
+ // The right part of `left` that does not intersect `right`
+ for (size_t y = 0; y < left->real_height; ++y) {
+ for (size_t x = right->real_width; x < left->real_width; ++x) {
+ d->p[(y + 1) * d->real_width + (x + 1)] =
+ left->p[y * left->real_width + x] ^ 0xff;
+ }
+ }
+
+ // The right part of `right` that does not intersect `left`
+ for (size_t y = 0; y < right->real_height; ++y) {
+ for (size_t x = left->real_width; x < right->real_width; ++x) {
+ d->p[(y + 1) * d->real_width + (x + 1)] =
+ right->p[y * right->real_width + x] ^ 0xff;
+ }
+ }
+
+ // The bottom part of `right` that does not intersect `left`
+ for (size_t y = left->real_height; y < right->real_height; ++y) {
+ for (size_t x = 0; x < right->real_width; ++x) {
+ d->p[(y + 1) * d->real_width + (x + 1)] =
+ right->p[y * right->real_width + x] ^ 0xff;
+ }
+ }
+
+ // The bottom part of `left` that does not intersect `right`
+ for (size_t y = right->real_height; y < left->real_height; ++y) {
+ for (size_t x = 0; x < left->real_width; ++x) {
+ d->p[(y + 1) * d->real_width + (x + 1)] =
+ left->p[y * left->real_width + x] ^ 0xff;
+ }
+ }
- for (size_t y = 0; y < d->real_height - 1; ++y) {
- for (size_t x = 0; x < d->real_width - 1; ++x) {
- // This could use XOR instead
+ // The intersection of `left` and `right`
+ for (size_t y = 0; y < min_real_height; ++y) {
+ for (size_t x = 0; x < min_real_width; ++x) {
d->p[(y + 1) * d->real_width + (x + 1)] =
- abs(left->p[y * left->virt_width + x] -
- right->p[y * right->virt_width + x]);
+ (left->p[y * left->real_width + x] ^
+ right->p[y * right->real_width + x]);
}
}
// debug_write_pgm(d, "debug.pgm");
for (size_t y = 1; y < d->real_height - 1; ++y) {
for (size_t x = 1; x < d->real_width - 1; ++x) {
- bool has_black_neighbour =
- !d->p[(y - 1) * d->real_width + (x + 0)] ||
- !d->p[(y + 1) * d->real_width + (x + 0)] ||
- !d->p[(y + 0) * d->real_width + (x - 1)] ||
- !d->p[(y + 0) * d->real_width + (x + 1)];
+ int has_black_neighbour =
+ !d->p[(y - 1) * d->real_width + (x + 0)] || // above
+ !d->p[(y + 1) * d->real_width + (x + 0)] || // below
+ !d->p[(y + 0) * d->real_width + (x - 1)] || // left
+ !d->p[(y + 0) * d->real_width + (x + 1)]; // right
if (!d->p[(y) * d->real_width + (x)] || has_black_neighbour)
sum++;
}
}
- double area = (d->real_width - 2) * (d->real_height - 2);
- double result = (double)sum/area;
+ area = (d->real_width - 2) * (d->real_height - 2);
+ result = (double)sum/area;
free(d->p);
free(d);
return result;
@@ -111,14 +169,14 @@ main(int argc, char *argv[]) {
image_data* images;
size_t image_count = 0;
size_t image_alloc = 20000;
+ char* file_path;
if (argc != 2) {
fprintf(stderr, "Usage: %s /path/to/file.pgm (P5 portable graymap)\n", argv[0]);
exit(0);
}
- char* file_path = argv[1];
-
+ file_path = argv[1];
f = fopen(file_path, "rb");
if (NULL == f) {
@@ -133,6 +191,7 @@ main(int argc, char *argv[]) {
size_t height;
size_t maxval;
uint8_t byte;
+ uint8_t* pixels;
// This assumes fscanf consider the right set of bytes
// to be kind of white space allowed between elements.
@@ -162,7 +221,7 @@ main(int argc, char *argv[]) {
break;
}
- uint8_t* pixels = (uint8_t*)
+ pixels = (uint8_t*)
malloc(width * height * sizeof(*pixels));
if (NULL == pixels) {
@@ -175,6 +234,8 @@ main(int argc, char *argv[]) {
break;
}
+ //
+
if (image_count + 1 > image_alloc) {
image_alloc *= 2;
image_data* temp = (image_data*)
@@ -185,39 +246,13 @@ main(int argc, char *argv[]) {
}
images = temp;
}
+
images[image_count].p = pixels;
images[image_count].real_width = width;
- images[image_count].virt_width = width;
images[image_count].real_height = height;
- images[image_count].virt_height = height;
image_count++;
}
- // This changes the pixel buffer for all images so they have the
- // same virtual dimensions, which makes some algorithms simpler.
- for (size_t ix = 0; ix < image_count; ++ix) {
- uint8_t* temp = (uint8_t*)
- malloc(sizeof(*temp) * max_width * max_height);
-
- if (NULL == temp) {
- // malloc failed
- }
-
- // Assume a white background!
- memset(temp, 0xff, sizeof(*temp) * max_width * max_height);
-
- images[ix].virt_width = max_width;
- images[ix].virt_height = max_height;
- for (size_t y = 0; y < images[ix].real_height; ++y) {
- for (size_t x = 0; x < images[ix].real_width; ++x) {
- temp[y * images[ix].virt_width + x] =
- images[ix].p[y * images[ix].real_width + x];
- }
- }
- free(images[ix].p);
- images[ix].p = temp;
- }
-
for (size_t left = 0; left < image_count; ++left) {
for (size_t right = left + 1; right < image_count; ++right) {
double diff = create_difference(&images[left], &images[right]);

0 comments on commit 98d982f

Please sign in to comment.