⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffman.cpp

📁 Huffman/RLE archivator
💻 CPP
字号:
#include "stdafx.h"
#include <fcntl.h>
#include <io.h>
#include "compressing.h"


void CompressHuffman(CString fileName, CString archName)
{
	SymbolInfo symbols[256];
	FILE *in = _wfopen(fileName, L"rb"); 
	FILE *out = _wfopen(archName, L"wb");

	int speciesCount = 0;
	unsigned char temp1;

	// Array of species initialization
	for (int i = 0; i < 256; i++)
	{
		symbols[i].length = 0;
		symbols[i].mask = 0;
		symbols[i].rate = 0;
	}

	//Reading symbols to array
	while (fread(&temp1, 1, 1, in) > 0)
	{
		symbols[temp1].rate++;
	}
	
	// Queue for tree forming
	TQueue myQueue;
	InitQueue(&myQueue, symbols, &speciesCount);

	if (speciesCount!=0)
	{
		// forming tree
		TreeForm(&myQueue);

		TNode *tree;
		if (myQueue.size() == 1)
		{
			tree = myQueue.top();
			myQueue.pop();
		}

		TreeRun(symbols, tree, 0, 0);

		if (tree->real == true)
			symbols[tree->name].length = 1;

		// Writing to file
		WriteRatesToFile(out, symbols, speciesCount);
		WriteBytesToFile(in, out, symbols);

	}
	fclose(in);
	fclose(out);
}

//////////////////////////////////////////////////////////////////////////

void DecompressHuffman(CString archName, CString fileName)
{
	SymbolInfo symbols[256];
	FILE *in = _wfopen(archName, L"rb");
	FILE *out = _wfopen(fileName, L"wb");

	int speciesCount=0;

	for (int i = 0; i < 256; i++)
	{
		symbols[i].length = 0;
		symbols[i].mask = 0;
		symbols[i].rate = 0;
	}

	ReadRatesFromArch(in, symbols);

	TQueue myQueue;

	InitQueue(&myQueue, symbols, &speciesCount);
	
	if (speciesCount != 0)
	{
		// forming tree
		TreeForm(&myQueue);

		TNode *tree;
		if (myQueue.size() == 1)
		{
			tree = myQueue.top();
			myQueue.pop();
		}

		unsigned long long totalBytes = 0;
		for (int i=0; i<256; i++)
		{
			if (symbols[i].rate !=0 )
			{
				totalBytes += symbols[i].rate;
			}
		}

		ReadBytesFromArch(in, out, tree, totalBytes);
	}
	fclose(in);
	fclose(out);
	
}

void InitQueue(TQueue *myQueue, SymbolInfo symbols[256], int *speciesCount)
{
	for (int i = 0; i < 256; i++)
	{
		if (symbols[i].rate != 0)
		{
			TNode *newNode = new TNode;
			InitNode(newNode, i, symbols[i].rate, NULL, NULL, NULL);
			newNode->real = true;
			myQueue->push(newNode);
			(*speciesCount)++;
		}
	}
}

void InitNode(TNode* newNode, unsigned char name, unsigned int rate, 
			  TNode *parent, TNode *left, TNode *right)
{
	newNode->left = left;
	newNode->right = right;
	newNode->parent = parent;
	newNode->name = name;
	newNode->rate = rate;
	newNode->real = false;
}

void TreeForm(TQueue *myQueue)
{
	while (myQueue->size() > 1)
	{
		TNode *node1 = myQueue->top();
		myQueue->pop();
		TNode *node2 = myQueue->top();
		myQueue->pop();
		TNode *newNode = new TNode;
		InitNode(newNode, 0, node1->rate + node2->rate, NULL, node1, node2);
		node1->parent = newNode;
		node2->parent = newNode;
		myQueue->push(newNode);
	}
}

void TreeRun(SymbolInfo symbols[256], TNode *curNode, unsigned long long mask, int length)
{
	if (curNode != NULL)
	{
		if (curNode->real)
		{
			symbols[curNode->name].mask = mask;
			symbols[curNode->name].length = length;
		}
		TreeRun(symbols, curNode->left, mask<<1, length+1);
		TreeRun(symbols, curNode->right, mask<<1 | 1, length+1);
	}
}

void WriteRatesToFile(FILE *file, SymbolInfo symbols[256], int count)
{
	if (count == 0)
		return;
	unsigned char temp1;
	unsigned char temp2 = count-1;
	fwrite(&temp2, 1, 1, file);
	for (int i=0 ; i < 256; i++)
	{
		if (symbols[i].rate != 0)
		{
			temp1 = i;
			fwrite(&temp1, 1, 1, file);
			fwrite(&(symbols[i].rate), 4, 1, file);
		}
	}
}

void WriteBytesToFile(FILE *in, FILE *out, SymbolInfo symbols[256])
{
	fseek(in, 0, SEEK_SET);
	unsigned long long currCode=0;
	int lengthCur = 0;
	unsigned char writtenChar;
	unsigned char temp1;

	while (fread(&temp1, 1, 1, in) > 0)
	{
		currCode = currCode | ((symbols[temp1].mask) << (64 - lengthCur - symbols[temp1].length));

		lengthCur += symbols[temp1].length;
		while (lengthCur >= 8)
		{
			writtenChar = currCode >> 56;
			currCode <<= 8;
			lengthCur -= 8;
			fwrite( &writtenChar, 1, 1, out);
		}
	}
	if (lengthCur > 0)
	{
		writtenChar = currCode >> 56;
		currCode >>= 8;
		fwrite( &writtenChar, 1, 1, out);
	}
}

void ReadRatesFromArch(FILE *file, SymbolInfo symbols[256])
{
	unsigned char temp1;
	unsigned int temp2;
	int count;
	if (fread(&temp1, 1, 1, file) >0)
	{
		count = temp1 + 1;
		for (int i = 0; i < count; i++)
		{
			fread(&temp1, 1, 1, file);
			fread(&temp2, 4, 1, file);
			symbols[temp1].rate = temp2;
		}
	}
}

void ReadBytesFromArch(FILE *in, FILE *out, TNode *tree ,unsigned long long totalBytes)
{
	int flag;
	int counter = 8;
	unsigned char mask;
	unsigned char temp1;
	unsigned long long bytes = 0;

	TNode *curNode = tree;
	do
	{
		flag = fread(&temp1, 1, 1, in);
		mask = (unsigned char) 1 << 7;

		for(int i=0; i<counter; i++)
		{
			if (curNode->real)
			{
				fwrite(&curNode->name, 1, 1, out);
				curNode = tree;
				if (++bytes == totalBytes)
				{	
					flag = -1;
					break;
				}
			}
			if (mask & temp1)
				curNode = curNode->right;
			else if (curNode->left != NULL)
				curNode = curNode->left;
			mask >>= 1;
		}
	} while ( flag > 0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -