/* * disting - distinguishing Apples and Bananas * * usage: * disting [-d] tiff_file * * -d TIFF B&W image was dithered from color, not saturated * tiff_file B&W TIFF image 413 by 413 pixels * * We could actually parse the TIFF format and extract the image, * but for purposes of this demonstration we will simply assume that * all camera images are of the same size. We will skip the first * 128 bytes of the image and read/scan the next 21322 bytes. * * We process 21322 bytes because it is 170576 bytes and is 7 bits * more than 413 * 413 bits. And while this is not strictly the * correct tiff location, for purposes of this demo it is sufficent * in that the vast majority of the image is within that zone, * that the amount of data processed is similar to an ideal parsing. * * Instead of being a resident program that is triggered by an * image download, we will simply run once on a disk file and * performing the same bit counting tasks. * * The original images were 8 bit color TIFF files. Conversion into * B&W was done by the XV TIFF dithering converstion process or * by triggering on a saturation level set low enough to not pick * up much of the background. * * By: chongo /\oo/\ * Tue Feb 9 03:59:55 PST 1999 * http://reality.sgi.com/chongo/misc/algorithm/apple-banana.html * * Share and Enjoy! :-) */ #include #include #include #define OFFSET 128 /* TIFF header bytes to skip */ #define IMAGE 21322 /* bytes, after image to scan for the image */ /* * midpoints between max apples and min bananas */ #define DITHER_LIMIT ((5699+4456)/2) #define SAT_LIMIT ((18603+11997)/2) /* * static declatations */ /* popcnt[x] number of 1 bits in 0 <= x < 256 */ static char popcnt[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; static char *program; /* our name */ static char *usage = "usage: %s -d tiff_file\n"; /* usage string */ int main(int argc, char *argv[]) { char *tiffname; /* tiff filename to open */ int fd; /* tiff file descriptor */ unsigned char buf[IMAGE]; /* image buffer */ int setcnt; /* number of bits set */ int dither; /* 1 => image is dithered (-d flag) */ int i; /* * parse args */ program = argv[0]; switch (argc) { case 2: dither = 0; /* saturated image */ tiffname = argv[1]; break; case 3: if (strcmp(argv[1], "-d") == 0) { dither = 1; /* dithered image */ tiffname = argv[2]; } else { fprintf(stderr, usage, program); exit(1); } break; default: fprintf(stderr, usage, program); exit(1); } /* * open the file */ fd = open(tiffname, O_RDONLY); if (fd < 0) { perror("open"); exit(2); } /* * read the image into memory */ if (lseek(fd, OFFSET, SEEK_SET) < 0) { perror("seek"); exit(3); } if (read(fd, buf, IMAGE) != IMAGE) { perror("read"); exit(4); } /* * count the set bits in the image */ for (setcnt=0, i=0; i < IMAGE; ++i) { setcnt += popcnt[buf[i]]; } /* * report the results */ printf("%d out of %d bits are set (%.3f%%), so it must be an %s\n", setcnt, IMAGE*8, 100.0*(double)setcnt/(IMAGE*8.0), (dither ? ((setcnt > DITHER_LIMIT) ? "banana" : "apple") : ((setcnt > SAT_LIMIT) ? "banana" : "apple"))); return 0; }