灰度图压缩(DCT+RLE)平均压缩率18%

缺点:高频段有阴影

/*
Auto folder version	[1]
Name				[imcp.cpp]
Branch				[image_process]
File type			[cpp]
Direction			[灰度图像压缩,支持分辨率:120*160,240*320,480*640,960*1280]
*/

#include "stdafx.h"

#include
#include


const int dct_f88[8][8] =  //JPEG亮度分量量化矩阵
{
	16,11,10,16,24,40,51,61,	//[0][0]:16
	12,12,14,19,26,58,60,55,
	14,13,16,24,40,57,69,56,
	14,17,22,29,51,87,80,62,
	18,22,37,56,68,109,103,77,
	24,35,55,64,81,104,113,92,
	49,64,78,87,103,121,120,101,
	72,92,95,98,112,100,103,99
};
/*行程编码顺序
{
	 <0>0,		<1>1,		 <2>5,		 <3>6,		<4>14,		<5>15,		<6>27,		<7>28,
	 <8>2,		<9>4,		 <10>7,		<11>13,		<12>16,		<13>26,		<14>29,		<15>42,
	 <16>3,		<17>8,		<18>12,		<19>17,		<20>25,		<21>30,		<22>41,		<23>43,
	 <24>9,		<25>11,		<26>18,		<27>24,		<28>31,		<29>40,		<30>44,		<31>53,
	<32>10,		<33>19,		<34>23,		<35>32,		<36>39,		<37>45,		<38>52,		<39>54,
	<40>20,		<41>22,		<42>33,		<43>38,		<44>46,		<45>51,		<46>55,		<47>60,
	<48>21,		<49>34,		<50>37,		<51>47,		<52>50,		<53>56,		<54>59,		<55>61,
	<56>35,		<57>36,		<58>48,		<59>49,		<60>57,		<61>58,		<62>62,		<63>63
};*/

const int jpeg_natural_order[64+16] = {
	0,  1,  8, 16,  9,  2,  3, 10,
	17, 24, 32, 25, 18, 11,  4,  5,
	12, 19, 26, 33, 40, 48, 41, 34,
	27, 20, 13,  6,  7, 14, 21, 28,
	35, 42, 49, 56, 57, 50, 43, 36,
	29, 22, 15, 23, 30, 37, 44, 51,
	58, 59, 52, 45, 38, 31, 39, 46,
	53, 60, 61, 54, 47, 55, 62, 63,
	63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
	63, 63, 63, 63, 63, 63, 63, 63
};

float		dct_mat[8][8];//用于存储DCT矩阵
float		dct_mat_temp[8][8];//用于存储临时计算量
signed char dct_mat_out[8][8];//dct计算得到的数据
static int	is_imcp_first_use = 0;
int			dct_inpt[8][8];
float		dcXmap_table[64][256];//高速查找表

//初始化DCT变换矩阵到dct_mat
void init_dct_mat()	//初始化DCT矩阵
{
	int i, j, t;
	for (i = 0; i < 8; i++) dct_mat[0][i] = sqrt(2.0 / 8)*sqrt(1.0 / 2);
	for (i = 1; i<8; i++)
	{
		t = 0;
		for (j = 0; j<8; j++)
		{
			dct_mat[i][j] = sqrt(2.0 / 8)*cos(3.14159265354 / (2.0 * 8)*(i + t));
			t += 2 * i;
		}
	}
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 8; j++) {
			for (t = 0; t < 256; t++)
			{
				dcXmap_table[i * 8 + j][t] = dct_mat[i][j] * t;
			}
		}
	}
}

//img_ori为输入8*8区域左上角的指针,width为图像宽度,buffer为输出压缩数据所存储的首地址,返回使用了多少字节buffer
int dct_rle_encoder(const unsigned char *img_ori, int width, unsigned char *buffer)
{
	float t;
	int i, j, k, ct;
	signed char *pDct = (signed char*)dct_mat_out;
	signed char left, right;
	signed int res;
	//Temp=dct_mat*MAP_IN
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 8; j++) {
			t = 0;
			ct = i * 8;
			for (k = 0; k < 8; k++)
				//t += dct_mat[i][k] * img_ori[k*width + j];
				t += dcXmap_table[ct + k][img_ori[k*width + j]];
			dct_mat_temp[i][j] = t;
		}
	}
	//DCT=Temp*T(dct_mat)
	for (i = 0; i<8; i++) {
		for (j = 0; j<8; j++) {
			t = 0;
			for (k = 0; k < 8; k++)
			{
				t += dct_mat_temp[i][k] * dct_mat[j][k];
			}
			dct_mat_out[i][j] = (signed char)(t / dct_f88[i][j] + (t > 0 ? 0.5 : -0.5));	//归一化
		}
	}
	//对DCT进行RLE编码,第一个直流分量不参与编码
	k = 0;
	buffer[k++] = pDct[0];//直流分量不参与编码
	//下面是RLE编码
	i = 1;								//i始终跟着right
	left = pDct[jpeg_natural_order[i]];	//left从下标1开始
	while (i < 64)
	{
		ct = i;
		do{
			right = pDct[jpeg_natural_order[++i]];//更新right
		} while ((left == right) && (i < 64));
		ct = i - ct;
		if (ct == 1)
		{
			res = left + 64;	//转化为移码
			res = res > 127 ? 127 : res;
			res = res < 0 ? 0 : res;	//限定存储最高位为1
			buffer[k++] = (unsigned char)res;	//存储left
			left = right;
		}
		else
		{
			//存储
			res = left + 64;	//转化为移码
			res = res > 127 ? 127 : res;
			res = res < 0 ? 0 : res;	//限定存储最高位为1
			buffer[k++] = (ct & 0x7F) | 0x80;	//先存储个数(标记为1XXXXXXX)
			buffer[k++] = (unsigned char)res;						//在存储值
																	//==
			left = right;
		}
	} 
	return k;
}

//buffer为需要解压的首地址(一次性仅解压8*8区域),width为图像宽度,img_out为输出8*8区域的左上角指针,返回使用了多少字节buffer
int dct_rle_decoder(const unsigned char *buffer, int width, unsigned char *img_out)
{
	float t = 0;
	int i, j, k, ct_in, ct_cp;
	int *pInt = (int*)dct_inpt;
	int temp;
	ct_in = 0;
	ct_cp = 0;
	pInt[jpeg_natural_order[ct_in++]] = buffer[ct_cp++];//DC
	while (ct_in < 64)//AC采集63个
	{
		temp = (int)buffer[ct_cp++];
		if (temp > 127)
		{
			k = (int)(temp & 0x7f);
			temp = (int)buffer[ct_cp] - 64;
			for (i = 0; i < k; i++)
			{
				pInt[jpeg_natural_order[ct_in++]] = temp;
			}
			ct_cp += 1;
		}
		else
		{
			pInt[jpeg_natural_order[ct_in++]] = temp - 64;
		}
	}

	for (i = 0; i < 8; i++)
		for (j = 0; j < 8; j++)
			dct_inpt[i][j] *= dct_f88[i][j];	//还原DCT结果


	//Temp=T(dct_mat)*DCT
	for (i = 0; i<8; i++) {
		for (j = 0; j<8; j++) {
			t = 0;
			for (k = 0; k<8; k++)
				t += dct_mat[k][i] * dct_inpt[k][j];
			dct_mat_temp[i][j] = t;
		}
	}
	//MAP_IN=Temp*dct_mat
	for (i = 0; i<8; i++) {
		for (j = 0; j<8; j++) {
			t = 0;
			for (k = 0; k<8; k++)
				t += dct_mat_temp[i][k] * dct_mat[k][j];
			if (t > 255) t = 255;
			if (t < 0) t = 0;
			img_out[i*width + j] = (unsigned char)(t);
		}
	}
	return ct_cp;
}


int imcp_encoder(const unsigned char *bmp_gray_in, int height, int width, unsigned char *buffer)
{
	int ct = 0, i, j;
	int coder_ct;
	unsigned char *ori_now = (unsigned char*)bmp_gray_in;
	unsigned char *buf_now = (unsigned char*)buffer;
	/*if (!is_imcp_first_use)
	{
		init_dct_mat();
		is_imcp_first_use = 1;
	}*/
	for (i = 0; i < height / 8; i++)
	{
		for (j = 0; j < width / 8; j++)
		{
			coder_ct = dct_rle_encoder(ori_now + j * 8, width, buf_now);
			buf_now += coder_ct;
			ct += coder_ct;
		}
		ori_now += 8 * width;
	}
	return ct;
}


int imcp_decoder(const unsigned char *buffer, int buffer_len, int height, int width, unsigned char *bmp_gray_out)
{
	int ct = 0, i, j;
	int coder_ct;
	unsigned char *ori_now = (unsigned char*)bmp_gray_out;
	unsigned char *buf_now = (unsigned char*)buffer;
	/*if (!is_imcp_first_use)
	{
		init_dct_mat();
		is_imcp_first_use = 1;
	}*/
	for (i = 0; i < height / 8; i++)
	{
		for (j = 0; j < width / 8; j++)
		{
			coder_ct = dct_rle_decoder(buf_now, width, ori_now + j * 8);
			buf_now += coder_ct;
			ct += coder_ct;
			if (ct > buffer_len) return 0;
		}
		ori_now += 8 * width;
	}
	return 1;
}

 

 

 

你可能感兴趣的:(机器视觉)