reactos/rosapps/dflat32/huffc.c

119 lines
2.6 KiB
C
Raw Normal View History

/* ------------------- huffc.c -------------------- */
#include "dflat.h"
#include "htree.h"
extern struct htree *ht;
extern int root;
extern int treect;
static int lastchar = '\n';
static void compress(FILE *, int, int);
static void outbit(FILE *fo, int bit);
static int fgetcx(FILE *fi)
{
int c;
/* ------- bypass comments ------- */
if ((c = fgetc(fi)) == ';' && lastchar == '\n')
do {
while (c != '\n' && c != EOF)
c = fgetc(fi);
} while (c == ';');
lastchar = c;
return c;
}
void main(int argc, char *argv[])
{
FILE *fi, *fo;
int c;
BYTECOUNTER bytectr = 0;
if (argc < 3) {
printf("\nusage: huffc infile outfile");
exit(1);
}
if ((fi = fopen(argv[1], "rb")) == NULL) {
printf("\nCannot open %s", argv[1]);
exit(1);
}
if ((fo = fopen(argv[2], "wb")) == NULL) {
printf("\nCannot open %s", argv[2]);
fclose(fi);
exit(1);
}
ht = calloc(256, sizeof(struct htree));
/* - read the input file and count character frequency - */
while ((c = fgetcx(fi)) != EOF) {
c &= 255;
ht[c].cnt++;
bytectr++;
}
/* ---- build the huffman tree ---- */
buildtree();
/* --- write the byte count to the output file --- */
fwrite(&bytectr, sizeof bytectr, 1, fo);
/* --- write the tree count to the output file --- */
fwrite(&treect, sizeof treect, 1, fo);
/* --- write the root offset to the output file --- */
fwrite(&root, sizeof root, 1, fo);
/* -- write the tree to the output file -- */
for (c = 256; c < treect; c++) {
int lf = ht[c].left;
int rt = ht[c].right;
fwrite(&lf, sizeof lf, 1, fo);
fwrite(&rt, sizeof rt, 1, fo);
}
/* ------ compress the file ------ */
fseek(fi, 0L, 0);
while ((c = fgetcx(fi)) != EOF)
compress(fo, (c & 255), 0);
outbit(fo, -1);
fclose(fi);
fclose(fo);
free(ht);
exit(0);
}
/* ---- compress a character value into a bit stream ---- */
static void compress(FILE *fo, int h, int child)
{
if (ht[h].parent != -1)
compress(fo, ht[h].parent, h);
if (child) {
if (child == ht[h].right)
outbit(fo, 0);
else if (child == ht[h].left)
outbit(fo, 1);
}
}
static char out8;
static int ct8;
/* -- collect and write bits to the compressed output file -- */
static void outbit(FILE *fo, int bit)
{
if (ct8 == 8 || bit == -1) {
while (ct8 < 8) {
out8 <<= 1;
ct8++;
}
fputc(out8, fo);
ct8 = 0;
}
out8 = (out8 << 1) | bit;
ct8++;
}