home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
datafiles
/
text
/
drdobb
/
unpacked
/
huff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
2KB
|
132 lines
/* HUFFMAN ENCODING PROG */
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int BYTECOUNTER;
struct htree {
BYTECOUNTER cnt;
struct htree *parent;
struct htree *right;
struct htree *left;
};
struct htree ht[512];
struct htree *root;
void buildtree(void)
{
int treect = 256;
int i;
while (1) {
struct htree *h1 = NULL, *h2 = NULL;
for (i=0; i<treect; i++) {
if (ht+i != h1) {
if (ht[i].cnt>0 && ht[i].parent == NULL) {
if (h1==NULL || ht[i].cnt<h1->cnt) {
if (h2==NULL || h1->cnt<h2->cnt)
h2 = h1;
h1 = ht+i;
}
else if (h2==NULL || ht[i].cnt <h2->cnt)
h2 = ht+i;
}
}
}
if (h2==NULL) {
root = h1;
break;
}
h1->parent = ht+treect;
h2->parent = ht+treect;
ht[treect].cnt = h1->cnt + h2->cnt;
ht[treect].right = h1;
ht[treect].left = h2;
treect++;
}
}
static void compress(FILE *fo, struct htree *h, struct htree *child);
static void outbit(FILE *fo, int bit);
void main(int argc, char *argv[])
{
FILE *fi,*fo;
int c;
BYTECOUNTER bytectr = 0;
int maxx = 0;
if (argc<3) {
printf("usage : huffc infile outfile\n");
exit(1);
}
if ((fi=fopen(argv[1],"rb"))==NULL) {
printf("Cannot open input file %s\n",argv[1]);
exit(1);
}
if ((fo=fopen(argv[2],"wb"))==NULL) {
printf("Cannot open output file %s\n",argv[2]);
exit(1);
}
while ((c=fgetc(fi)) != EOF) {
c &= 255;
ht[c].cnt++;
bytectr++;
}
fwrite (&bytectr,sizeof bytectr,1,fo);
for (c=0;c<256;c++)
if (ht[c].cnt>maxx) maxx=ht[c].cnt;
for (c=0;c<256;c++) {
if (ht[c].cnt>0)
ht[c].cnt=((ht[c].cnt*254)/maxx)+1;
fputc((unsigned char)ht[c].cnt,fo);
#ifdef DEBUG
fprintf(stderr," %3u",ht[c].cnt);
#endif
}
buildtree();
fseek(fi,0L,0);
while ((c=fgetc(fi)) != EOF)
compress(fo,ht+(c&255),NULL);
for (c=0;c<8;c++) outbit(fo,0);
fclose(fi);
fclose(fo);
}
static void compress(FILE *fo,struct htree *h,struct htree *child)
{
if (h->parent != NULL)
compress(fo,h->parent,h);
if (child) {
if (child==h->right)
outbit(fo,0);
else if (child == h->left)
outbit(fo,1);
}
}
static char out8;
static int ct8;
static void outbit(FILE *fo, int bit)
{
if (ct8==8) {
fputc(out8,fo);
ct8=0;
}
out8=(out8<<1) | bit;
ct8++;
}