数据压缩之Huffman编码

实验介绍

通过已有的HuffmanCodes项目,
1.对sena.img、omaha.img、sensin.img、Bookshelf1.img等raw图像文件进行Huffman编码;
2.自行编写一段程序,对sena.img、omaha.img、sensin.img三者进行相邻像素差值计算,并输出差值图像。然后分别对输出的差值图像进行Huffman编码;
3.使用对sensin.img图像进行Huffman编码时生成的码本(编码树),对Bookshelf1.img和sena.img图像进行Huffman编码,与自身计算得到的码本的压缩效果进行对比。

实验环境介绍和项目使用方法

本次实验使用的软件为Visual Studio 2019(版本最好在2013以上);
具体安装方式参考链接:VS2019安装教程

安装好VS2019后,打开HuffmanCodec项目文件,
即打开HuffmanCodec.sln文件。

带参数调试VS项目的方法:
对具体需要使用的项目右键,设置为启动项目;
下面以打开HuffmanEnc项目为例
设置启动项目如图设置为启动项目后,启动项目会高亮显示;
然后同样对使用的项目右键,点击最下面的属性,选择配置属性下的调试
调试程序参数设置界面
在命令参数部分写入需要设置的命令即可。
以HuffEnc项目为例,从huff_enc.doc或huff_enc.c中的usage()函数中的内容可以得知,本项目输入参数包含四种:
-i 代表输入文件,本次输入的为.img格式的raw图像文件;
-o 代表输出文件,本程序的输出为.huff或.huffenc后缀的Huffman编码文件;
-c 代表编码使用的码本文件,依然以.huff或.huffenc为后缀,如果不设置,默认在编码前计算出对应图像的码本;
-s 代表码本的存储位置,以.huff或.huffenc为后缀,如果-c没有被设置,则输出由图像自身计算出的码本,如果-c被设置,则输出和-c同样的码本;如果不设置,则默认写入-o对应的输出文件的头部;

所以,输入参数的格式为:
-i 输入文件路径 -o 输出.huff文件路径 -c 输入码本路径 -s 输出码本路径
其中每一部分需要用空格间隔开。

(需要注意的是,这样的输入格式是因为项目中代码使用了相应的函数进行设置,并非所有项目的输入都有同样的参数设置格式,这里不再对这种函数进行介绍)

1.对.img图像文件进行Huffman编码

本次实验所用的图片大小皆为64KB,如图所示:
img图像文件
编码后结果如图所示:
其中.huffenc为图像编码后结果
_code.huffenc为对应的码本文件
Huffman编码后结果
可以看到编码后文件大小整体被压缩了大概5~9KB

2.编写diff程序得到差值图像,并进行Huffman编码

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
	FILE* ifp, * ofp;
	unsigned char* file, * tmp, * tmp_diff;
	int	size;
	char infile[80], outfile[80];
	strcpy(infile, argv[1]);
	strcpy(outfile, argv[2]);
	fopen_s(&ifp, infile, "rb");
	if (ifp == NULL) {
		printf("infile open error!");
		return 0;
	}
	fseek(ifp, 0, 2); /* 指针从文件末尾开始 */
	size = ftell(ifp); /* 获取指针所在的位置,(这里就相当于获取到了文件数据的个数) */
	++size;
	fseek(ifp, 0, 0); /* 指针从文件开头开始 */
	file = (unsigned char*)malloc(size * sizeof(unsigned char) * 4); /* 开辟空间 */
	tmp = (unsigned char*)malloc(size * sizeof(unsigned char) * 4);
	tmp_diff = (unsigned char*)malloc(size * sizeof(unsigned char) * 4);
	if (file == NULL) {
		printf("Unable to allocate memory for file.\n");
		exit(1);
	}
	/* 获取文件内容 */
	fread(file, sizeof(unsigned char), size, ifp);
	fclose(ifp);
	fopen_s(&ofp, outfile, "wb");
	if (ofp == NULL) {
		printf("outfile open error!");
		return 0;
	}
	int i,j;
	for (i = 0;i < size;++i) {
		*(tmp + i) = *(file + i);
	}
	for (i = 0;i < 256;++i) {
		for (j = 0;j < 256;++j) {
			if (j == 0)
			{
				*(tmp_diff + i * 256 + j) = (*(tmp + i * 256 + j) - 128);
			}
			else
			{
				*(tmp_diff + i * 256 + j) = (*(tmp + i * 256 + j) - *(file + i * 256 + j - 1));
			}
		}
	}
	fwrite(tmp_diff, sizeof(unsigned char), size, ofp);
	fclose(ofp);
	return 0;
}

(#define _CRT_SECURE_NO_WARNINGS为忽视老版本函数警告,
可根据具体情况进行删减;
本项目在之前的大项目下会有传参问题,
故需要在新的文件夹下另建一个项目;
本项目使用main函数进行传参,
第一个参数为 输入.img原图像的路径
第二个参数为 输出.img差值图像的路径
输出的路径同样需要先创建好文件夹)

本项目的差值压缩方法:
通常情况下,当前位置与其左侧位置的互信息最大,
即二者的相关性高,顾使用其与左侧的差值代替当前位置;

使用当前像素值减去左侧像素值得到当前位置的差值;
最左侧像素则减去128得到最左侧位置对应的差值。
使用本程序对sena.img、omaha.img、sensin.img三个图像分别进行处理,
得到输出的差值图像;
之后再对输出的差值图像进行Huffman编码;
结果如图所示:
在这里插入图片描述
其中_diff.img为差值图像文件;
_diff.huff对Huffman编码后的文件;
_diffcode.huff为计算出的码本文件;
可以看到,差值图像普遍比原图像增加了1KB,
是因为差值处理引入了负数导致整体大小变大了一点;

也可以看到
对差值图像编码后文件大小比原图像的编码后文件压缩比更高;
其中sena.img和sensin.img压缩提升多,但omaha.img压缩提升不明显。

3.使用其他图像码本对图像进行Huffman编码

首先使用对sensin.img图像的码本
即sensin_code.huffenc文件
对Bookshelf1.img和sena.img图像进行Huffman编码。

结果如下图所示:
在这里插入图片描述
可以看到使用sensin码本编码的bookshelf1.img,
编码后文件大小比使用自身码本得到的文件更大,
甚至比原图像文件更大;
而sena.img使用sensin码本编码后压缩效果也不如使用原码本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值