home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <quadtree.h>
-
- #define ColorsAgree(c1,c2) ((c1)?(c2):(!(c2)))
-
- static char BitBuffer;
- static int BitPos;
-
- extern char *malloc();
-
- int QT_Bitmap_Bit(b, x, y)
- QT_Bitmap_t *b;
- int x, y;
- {
- int index, byte, offset;
-
- index = (y + b->y) * b->fullwidth + (x + b->x);
- byte = index / 8;
- offset = index % 8;
- return (b->bits[byte] & (1 << offset));
- }
-
- void QT_Bitmap_SetBit(b, x, y, val)
- QT_Bitmap_t *b;
- int x, y, val;
- {
- int index, byte, offset;
-
- index = (y + b->y) * b->fullwidth + (x + b->x);
- byte = index / 8;
- offset = index % 8;
- if (val)
- b->bits[byte] |= (1 << offset);
- else
- b->bits[byte] &= ~(1 << offset);
- }
-
- int QT_Bitmap_Init(b, x, y, width, height, ref)
- QT_Bitmap_t *b;
- int width, height;
- QT_Bitmap_t *ref;
- {
- b->x = x;
- b->y = y;
- b->width = width;
- b->height = height;
- if (ref) {
- b->x += ref->x;
- b->y += ref->y;
- b->bits = ref->bits;
- b->fullwidth = ref->fullwidth;
- b->fullheight = ref->fullheight;
- return (0);
- }
- b->fullwidth = width;
- b->fullheight = height;
- if (b->bits = malloc(width * height / 8 + 1)) {
- bzero(b->bits, width * height / 8 + 1);
- return (0);
- }
- return (1);
- }
-
- QT_TreeNode_t *QT_TreeNode_New(color, ul, ur, ll, lr)
- int color;
- QT_TreeNode_t *ul, *ur, *ll, *lr;
- {
- QT_TreeNode_t *result = (QT_TreeNode_t *) malloc(sizeof(QT_TreeNode_t));
-
- if (result) {
- result->color = color;
- result->children[0] = ul;
- result->children[1] = ur;
- result->children[2] = ll;
- result->children[3] = lr;
- }
- return (result);
- }
-
- void QT_TreeNode_Destroy(node)
- QT_TreeNode_t *node;
- {
- int i;
- QT_TreeNode_t *child;
-
- for (i = 0; i < 4; ++i) {
- if (child = QT_TreeNode_Child(node, i))
- QT_TreeNode_Destroy(child);
- }
- free(node);
- }
-
- static int TreeAgrees(color, node)
- int color;
- QT_TreeNode_t *node;
- {
- return ((ColorsAgree(color, QT_TreeNode_Color(node)))
- && ((!(QT_TreeNode_Child(node, 0)))
- || TreeAgrees(color, QT_TreeNode_Child(node, 0)))
- && ((!(QT_TreeNode_Child(node, 1)))
- || TreeAgrees(color, QT_TreeNode_Child(node, 1)))
- && ((!(QT_TreeNode_Child(node, 2)))
- || TreeAgrees(color, QT_TreeNode_Child(node, 2)))
- && ((!(QT_TreeNode_Child(node, 3)))
- || TreeAgrees(color,
- QT_TreeNode_Child(node, 3))));
- }
-
- QT_TreeNode_t *QT_BitmapToTree(b)
- QT_Bitmap_t *b;
- {
- QT_Bitmap_t ulbm, urbm, llbm, lrbm;
- QT_TreeNode_t *ulqt, *urqt, *llqt, *lrqt;
- int h = QT_Bitmap_Height(b), w = QT_Bitmap_Width(b), h2, w2;
- int ones = 0, zeroes = 0, color;
-
- switch (w * h) {
- case 0:
- return 0;
- case 1:
- return (QT_TreeNode_New(QT_Bitmap_Bit(b, 0, 0),
- 0, 0, 0, 0));
- }
- /* It's a non-trivial bitmap */
- h2 = h >> 1;
- w2 = w >> 1;
- (void) QT_Bitmap_Init(&ulbm, 0, 0, w2, h2, b);
- (void) QT_Bitmap_Init(&urbm, w2, 0, w - w2, h2, b);
- (void) QT_Bitmap_Init(&llbm, 0, h2, w2, h - h2, b);
- (void) QT_Bitmap_Init(&lrbm, w2, h2, w - w2, h - h2, b);
- ulqt = QT_BitmapToTree(&ulbm);
- urqt = QT_BitmapToTree(&urbm);
- llqt = QT_BitmapToTree(&llbm);
- lrqt = QT_BitmapToTree(&lrbm);
- if (ulqt) {
- if (QT_TreeNode_Color(ulqt))
- ++ones;
- else
- ++zeroes;
- }
- if (urqt) {
- if (QT_TreeNode_Color(urqt))
- ++ones;
- else
- ++zeroes;
- }
- if (llqt) {
- if (QT_TreeNode_Color(llqt))
- ++ones;
- else
- ++zeroes;
- }
- if (lrqt) {
- if (QT_TreeNode_Color(lrqt))
- ++ones;
- else
- ++zeroes;
- }
- color = (ones > zeroes) ? 1 : 0;
- if (ulqt) {
- if (TreeAgrees(color, ulqt)) {
- QT_TreeNode_Destroy(ulqt);
- ulqt = 0;
- }
- }
- if (urqt) {
- if (TreeAgrees(color, urqt)) {
- QT_TreeNode_Destroy(urqt);
- urqt = 0;
- }
- }
- if (llqt) {
- if (TreeAgrees(color, llqt)) {
- QT_TreeNode_Destroy(llqt);
- llqt = 0;
- }
- }
- if (lrqt) {
- if (TreeAgrees(color, lrqt)) {
- QT_TreeNode_Destroy(lrqt);
- lrqt = 0;
- }
- }
- return (QT_TreeNode_New(color, ulqt, urqt, llqt, lrqt));
- }
-
- static void BitWrite(bit, fp)
- int bit;
- FILE *fp;
- {
- if (bit)
- BitBuffer |= (1 << BitPos);
- else
- BitBuffer &= ~(1 << BitPos);
- if ((--BitPos) < 0) {
- BitPos = 7;
- fputc(BitBuffer, fp);
- }
- }
-
- #define BitFlush(fp) (fputc(BitBuffer,(fp)))
-
- static void QT_TreeNode_Write(fp, node, fmt)
- FILE *fp;
- QT_TreeNode_t *node;
- char fmt;
- {
- int i;
- QT_TreeNode_t *child;
-
- switch (fmt) {
- case 0:
- BitWrite(0, fp);
- BitWrite(QT_TreeNode_Color(node), fp);
- for (i = 0; i < 4; ++i) {
- if (child = QT_TreeNode_Child(node, i))
- QT_TreeNode_Write(fp, child, fmt);
- else
- BitWrite(1, fp);
- }
- break;
- case 1:
- BitWrite(0, fp);
- BitWrite(QT_TreeNode_Color(node), fp);
- if (QT_TreeNode_Child(node, 0)
- || QT_TreeNode_Child(node, 1)
- || QT_TreeNode_Child(node, 2)
- || QT_TreeNode_Child(node, 3)) {
- for (i = 0; i < 4; ++i) {
- if (child = QT_TreeNode_Child(node, i))
- QT_TreeNode_Write(fp, child, fmt);
- else {
- BitWrite(1, fp);
- BitWrite(0, fp);
- }
- }
- }
- else {
- BitWrite(1, fp);
- BitWrite(1, fp);
- }
- break;
- }
- }
-
- void QT_Tree_Write(fp, node, fmt, w, h)
- FILE *fp;
- QT_TreeNode_t *node;
- char fmt;
- short w, h;
- {
- BitPos = 7;
- fputc(fmt, fp);
- fputc(w % 256, fp);
- fputc(w / 256, fp);
- fputc(h % 256, fp);
- fputc(h / 256, fp);
- QT_TreeNode_Write(fp, node, fmt);
- BitFlush(fp);
- }
-
- static int BitRead(fp)
- FILE *fp;
- {
- if ((--BitPos) < 0) {
- BitPos = 7;
- BitBuffer = fgetc(fp);
- }
- return (BitBuffer & (1 << BitPos));
- }
-
- static QT_TreeNode_t *QT_TreeNode_Read(fp, fmt, extra)
- FILE *fp;
- char fmt;
- int *extra;
- {
- int bit = BitRead(fp), bit2, nochildren, dummy;
- QT_TreeNode_t *ul, *ur, *ll, *lr;
-
- switch (fmt) {
- case 0:
- if (bit) {
- return (0);
- }
- bit = BitRead(fp);
- ul = QT_TreeNode_Read(fp, fmt, &dummy);
- ur = QT_TreeNode_Read(fp, fmt, &dummy);
- ll = QT_TreeNode_Read(fp, fmt, &dummy);
- lr = QT_TreeNode_Read(fp, fmt, &dummy);
- return (QT_TreeNode_New(bit, ul, ur, ll, lr));
- case 1:
- bit2 = BitRead(fp);
- if (bit) {
- *extra = bit2;
- return (0);
- }
- ul = QT_TreeNode_Read(fp, fmt, &nochildren);
- if ((!ul) && nochildren)
- return (QT_TreeNode_New(bit2, 0, 0, 0, 0));
- ur = QT_TreeNode_Read(fp, fmt, &dummy);
- ll = QT_TreeNode_Read(fp, fmt, &dummy);
- lr = QT_TreeNode_Read(fp, fmt, &dummy);
- return (QT_TreeNode_New(bit2, ul, ur, ll, lr));
- }
- }
-
- QT_TreeNode_t *QT_Tree_Read(fp, w, h)
- FILE *fp;
- short *w, *h;
- {
- char fmt = fgetc(fp);
- int dummy;
-
- BitPos = 0;
- *w = fgetc(fp);
- *w += fgetc(fp) * 256;
- *h = fgetc(fp);
- *h += fgetc(fp) * 256;
- return (QT_TreeNode_Read(fp, fmt, &dummy));
- }
-
- int QT_Bitmap_Read(b, fp) /* B is an *uninitialized* bitmap */
- QT_Bitmap_t *b;
- FILE *fp;
- {
- int x, y, c;
- char buf[4];
- long w, h;
-
- fread(buf, 4, 1, fp);
- fread(&w, 4, 1, fp);
- fread(&h, 4, 1, fp);
- fread(buf, 2, 1, fp);
- if (QT_Bitmap_Init(b, 0, 0, (int) w, (int) h, 0))
- return (1);
- BitPos = -1;
- for (y = 0; y < h; ++y) {
- for (x = 0; x < w; ++x) {
- c = BitRead(fp);
- QT_Bitmap_SetBit(b, x, y, !c);
- }
- BitPos = -1;
- }
- return (0);
- }
-