哈夫曼编码,压缩,opencv画图

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>  
#include<string.h>  
#include<opencv.hpp>
#include<ctype.h>
using namespace std;
using namespace cv;
int Pretreat();
char str[100] = {0};
struct  {
	char c;
	int count;
}kind[100];
typedef struct nn{
	char character;
	int weight;
	int flag;
	int parent;
	int lchild;
	int rchild;
}HaffNode;
typedef struct {
	int bit[255];
	int start;
	int weight;
}Code;
void Haffman(int n, HaffNode *hafftree);
void HaffmanCode(HaffNode *hafftree, int n, Code *haffCode);
void preorder(HaffNode *hafftree, int n,int x,int y,int lenth);
void draw(int b, int g, int r, int flag, int x, int y,int lenth);
void Compression(Code *haffcode, int n);
void Translation();
Mat image(1000, 1000, CV_8UC3);
int main()
{
	namedWindow("tree");
	int i = 0, j;
	int len = Pretreat();
	HaffNode *haffman = (HaffNode *)malloc(sizeof(HaffNode)*(2*len-1));
	Code *haffcode = (Code *)malloc(sizeof(Code)*len);
	Haffman(len, haffman);
	haffman;
	HaffmanCode(haffman, len,haffcode);
	FILE *fp = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Codebook.txt", "w");
	for (i = 0; i < len; i++)
	{
		fprintf(fp, "%c:	", haffman[i].character);
		for (j = haffcode[i].start + 1; j < len; j++)
		{
			fprintf(fp,"%d", haffcode[i].bit[j]);
		}
		fprintf(fp,"\n");
	}
	fclose(fp);
	draw(255, 255, 0, 2, 500, 50,150);
	preorder(haffman, 2 * len - 2,500,50,150);
	Compression(haffcode, len);
	Translation();
}
int Pretreat()
{
	int k = 0;
	FILE *fp; int i, j,count,q,flag=0;
	if ((fp = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Input.txt", "r")) == NULL)
		printf("failed to open file\n");
	fgets(str, 200, fp);//读取到str中
	for (i=0; i < strlen(str); i++)
	{
		count = 1; flag = 1;
		for (j = i+1; j < strlen(str); j++)
		{
			if (str[i] == str[j])count++;
		}
		for (q = 0; q < 100; q++)
		{
			if (str[i] == kind[q].c) {
				flag = 0;
				break;
			}
		}
		if (flag)
		{
			kind[k].c = str[i];
			kind[k++].count = count;
		}
	}
	return k;
}//生成kind 每个字符所对应的权值
void Haffman(int n, HaffNode *hafftree)
{
	int i, j, m1, m2, x1, x2;
	//初始化
	for (i = 0; i < 2 * n - 1; i++)
	{
		if (i < n)
		{
			hafftree[i].character = kind[i].c;
			hafftree[i].weight = kind[i].count;
		}
		else
			hafftree[i].weight = 0;
		hafftree[i].parent = 0; hafftree[i].flag = 0; hafftree[i].lchild = -1; hafftree[i].rchild = -1;
	}

	//构造非叶子节点
	for (i = 0; i < n - 1; i++)
	{
		m1 = m2 = 1000;
		x1 = x2 = 0;
		for (j = 0; j < n + i; j++)
		{
			if (hafftree[j].weight < m1&&hafftree[j].flag == 0)
			{
				m2 = m1;
				x2 = x1;//记录上次的
				m1 = hafftree[j].weight;
				x1 = j;//更新这次的
			}
			else if (hafftree[j].weight < m2&&hafftree[j].flag == 0)
			{
				m2 = hafftree[j].weight;
				x2 = j;
			}
		}
		//将找出的两颗最小书合并
		hafftree[x1].parent = n + i;
		hafftree[x2].parent = n + i;
		hafftree[x1].flag = 1;
		hafftree[x2].flag = 1;
		hafftree[n + i].weight = hafftree[x1].weight + hafftree[x2].weight;
		hafftree[n + i].lchild = x1;
		hafftree[n + i].rchild = x2;
	}
}
void HaffmanCode(HaffNode *hafftree, int n, Code *haffCode)//从叶子到到根节点的编码
{
	int i, j, child, parent;
	Code *temp=(Code *)malloc(sizeof(Code));
	for (i = 0; i < n; i++)
	{
		temp->start = n - 1;
		temp->weight = hafftree[i].weight;
		child = i;
		parent = hafftree[child].parent;
		while (parent != 0)
		{
			if (hafftree[parent].lchild == child)
				temp->bit[temp->start] = 0;//左0右1
			else
				temp->bit[temp->start] = 1;
			temp->start--;
			child = parent;
			parent = hafftree[child].parent;
		}
		for (j = temp->start + 1; j < n; j++)
			haffCode[i].bit[j] = temp->bit[j];

		haffCode[i].start = temp->start;
		haffCode[i].weight = temp->weight;
	}
}
void preorder(HaffNode *hafftree,int n,int x,int y,int lenth)
{
	if (hafftree[n].lchild != -1)
	{
		if (hafftree[hafftree[n].lchild].lchild == -1)
		{
			char te[2]; te[0] = hafftree[hafftree[n].lchild].character; te[1] = '\0';
			draw(255, 0, 255, 1, x, y, lenth);
			putText(image, te, Point(x - lenth, y + lenth), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 255, 255), 2, 8);

		}
		else 
			draw(255, 255, 0, 1, x, y,lenth);
		imshow("tree", image);
		waitKey(0);
	}
	if (hafftree[n].rchild != -1)
	{
		if (hafftree[hafftree[n].rchild].rchild == -1)
		{
			char te[2]; te[0] = hafftree[hafftree[n].rchild].character; te[1] = '\0';
			draw(255, 0, 255, 0, x, y, lenth);
			putText(image, te, Point(x + lenth, y + lenth), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 255, 255), 2, 8);

		}
		else
			draw(255, 0, 0, 0, x, y,lenth);
		imshow("tree", image);
		waitKey(0);		
	}
	if (hafftree[n].lchild != -1 || hafftree[n].rchild != -1)
	{
		lenth = lenth - 30;
	}
	if(hafftree[n].lchild!=-1)
		preorder(hafftree, hafftree[n].lchild, x - lenth-30, y + lenth+30,lenth);
	if(hafftree[n].rchild!=-1)
		preorder(hafftree, hafftree[n].rchild, x + lenth +30, y + lenth+30,lenth);
}
void Compression(Code *haffcode, int n)
{
	char c, character[100];
	char tstr[20], code[30][10], str3[1000] = { 0 };
	int ccount = 0;
	int k = 0, i = 0, j = 0, count = 0;
	int str[1000]; char instr[100];
	int bit[7];
	memset(str, -1, sizeof(int) * 1000);
	FILE *fp1=fopen("C:\\Users\\chenh\\Desktop\\ctest\\Input.txt", "r");
	FILE *fp2=fopen("C:\\Users\\chenh\\Desktop\\ctest\\Compression.txt", "w+");
	FILE *fp3 = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Codebook.txt", "r");
	while (fscanf(fp3, "%c:\t%s\n", &c, tstr) != EOF)
	{
		character[ccount] = c;
		strcpy(code[ccount++], tstr);
	}
	fgets(instr, 100, fp1);
	for (i = 0; i < strlen(instr); i++)
	{
		for (j = 0; j < ccount; j++)
		{
			if (character[j] == instr[i])
			{
				strcat(str3, code[j]);
			}
		}
	}

	for (i = 0; i < strlen(str3); i++)
	{
		str[i] = str3[i] - '0';
		printf("%d", str[i]);
	}
	count = i;
	if(count%7!=0)
		count = count + 7-count % 7;
	for (j = i ; j < count; j++)
	{
		str[j] = 0;
	}
	for (i = 0; i < count; i+=7)
	{
		int t = 0;
		for (j = i; j < i + 7; j++)
		{
			bit[t++] = str[j];
		}
		int sum = 0;
		int exp = 6;
		for (k = 0; k <7; k++)
		{
			sum = sum + bit[k]*pow(2, exp);
			exp--;
		}
		printf("$%d", sum);
		fprintf(fp2, "%c", sum);//多位空格分开
	}
 	fclose(fp2);
}
void Translation()
{
	char c,character[100];
	char str[500], code[30][10], temp[10], str2[10], str3[1000] = { 0 };
	int count = 0,k=0,kk=0;
 	FILE *fp1 = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Codebook.txt", "r");
	while (fscanf(fp1, "%c:\t%s\n", &c, str)!=EOF)
	{
		character[count] = c;
		strcpy(code[count++], str);
	}//读取密码本
	fclose(fp1);
	FILE *fp2 = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Compression.txt", "r");
	FILE *fp3 = fopen("C:\\Users\\chenh\\Desktop\\ctest\\Translation.txt", "w+");
	fgets(str, 500, fp2);
	printf("\n");
	for (int i = 0; i < strlen(str); i++)
	{
		int num;
		num = str[i] - ' ' + 32;
		int p = 1, y = 0, yushu;
		k = 0;
		memset(str2, 0, sizeof(char) * 10);
		while (1)
		{
			yushu = num % 2;
			num /= 2;
			str2[k++] =yushu+48;
			if (num == 0)break;
		}
		for (int j = 6; j >= 0; j--)
		{
			if (str2[j] == '\0')str2[j] = '0';
			str3[kk++] = str2[j];
			printf("%c", str3[kk - 1]);
		}
	}
	int flag = 0;
	k = 0;
	memset(temp, '\0', sizeof(temp));
	for (int i = 0; i < strlen(str3); i++)
	{
		temp[k++] = str3[i];
		for (int j = 0; j < count; j++)
		{
			if (strcmp(temp, code[j]) == 0)
			{
				flag = 1;
				printf("%c", character[j]);
				fprintf(fp3, "%c", character[j]);
				break;
			}
		}
		if (flag)
		{
			k = 0;
			flag = 0;
			memset(temp, '\0', sizeof(temp));
		}
	}
 	fclose(fp3);
}
void draw(int b, int g, int r, int flag, int x, int y,int lenth)
{
	if (flag == 2)
	{
		circle(image, Point(x, y), 15, Scalar(b, g, r), -1);
		imshow("tree", image);
	}
	else if (flag == 1)//zuoyi
	{
		line(image, Point(x, y), Point(x - lenth, y + lenth), Scalar(255,255,0), 4, CV_AA);
		circle(image, Point(x - lenth, y + lenth), 15, Scalar(b, g, r), -1);
	}
	else//youyi
	{
		line(image, Point(x, y), Point(x + lenth, y + lenth), Scalar(255,255,0), 4, CV_AA);
		circle(image, Point(x + lenth, y + lenth), 15, Scalar(b , g, r), -1);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值