【轉】旋轉門算法


//門一旦打開就不關閉,是指在一個壓縮段內。

說明:該算法的壓縮效果和數據有很大關系,一般測試時用正弦波數據,壓縮效果很好,如果用隨機數,基本不會壓縮。

 

==============================

程序說明:

 E(壓縮精度)的值要根據待壓縮的數值來定,如果E的值太小,解壓誤差會很小,但壓縮率低。

 如果E的值太大,壓縮比非常高,100MB的文件可能就只有幾M,但解壓誤差非常大。所以E要多試幾次取一個比較合理的值。

 

5.解壓過程:(線性插值)有起點和終點坐標可以求出線段的公式,然后根據某點x軸坐標求出其對應的y的值,也就是實際的值。

=====================

 

#include <stdio.h>

#define MAX_DOUBLE 1.79769e+308
#define E 3

struct point
{
	int x, y;
};

void compress()
{
	FILE * fin = fopen("rand.txt", "r");	
	FILE * fout = fopen("out.txt", "w");
	
	//上門和下門,初始時門是關着的
	double up_gate = -MAX_DOUBLE;         
	double down_gate = MAX_DOUBLE;
	
	//當前數據的上斜率和下斜率
	double now_up, now_down;	
	
	int data;				//當前讀取到的數據
	int last_read_data;		//當前數據的前一個數據
	int last_stored_data;	//最近保存的點	

	//read and save the first data
	fscanf(fin, "%d", &last_stored_data);
	fprintf(fout, "0 %d ", last_stored_data);
	
	last_read_data =  last_stored_data;
	
	int last_stored_t = 0;  //最近保存數據的時間,init 0
	
	//循環處理數據
	int t=0;
 	while(++t, fscanf(fin, "%d", &data) != EOF)
 	{
	 	now_up = double(data-last_stored_data-E) / (t-last_stored_t);
	 	if(now_up > up_gate)
	 		up_gate = now_up;

 		now_down = double(data-last_stored_data+E) / (t-last_stored_t);
 		if(now_down < down_gate)
 			down_gate = now_down;

 		if(up_gate >= down_gate)
		{
			//保存前一個點
			fprintf(fout, "%d %d ", t-1, last_read_data);
			
			last_stored_t = t-1; //修改最近保存數據時間點
			last_stored_data = last_read_data;
			
			//初始化兩扇門為當前點與上個點的斜率 
		 	up_gate = double(data-last_stored_data-E);
		 	down_gate = double(data-last_stored_data+E);
		}
		last_read_data = data;
 	}
 	// sava end point
	fprintf(fout, "%d %d ", t-1, last_read_data);
	
	fclose(fin);
	fclose(fout);
}

void uncompress()
{
	FILE * fin = fopen("out.txt", "r");
	FILE * fout = fopen("src.txt", "w");	

	point a,b;	
	fscanf(fin, "%d %d", &a.x, &a.y);
	
	while(fscanf(fin, "%d %d", &b.x,&b.y) != EOF)
	{
		//Step.1
		fprintf(fout, "%d ", a.y);
		
		//Step.2		
		if(a.x+1 != b.x)
		{
			double k = double(b.y - a.y) / (b.x - a.x); //計算斜率 
			for(int i=a.x+1; i<b.x; i++)
			{
				//線性插值求被壓縮掉的數據 
				fprintf(fout, "%.0lf ", k*(i-a.x) + a.y);
			}
		}

		a.x = b.x;
		a.y = b.y;
	}
	fprintf(fout, "%d ", b.y);
	fclose(fin);
	fclose(fout);
}

int main(void)
{
	compress();
	uncompress();
	return 0;
}

  

其實把current , lastRead, lastStored定義為Point類型程序會更清晰。

下面上一下壓縮效果圖,界面是用.Net中的Chart控件做的,用法很簡單,如果想直觀的看到結果,你們可以托一個控件上去看看效果~ 挺好玩的。

上面的曲線是原數據,總共是800個點,壓縮后可以看到,儲存的點屈指可數。

從圖中可以看出對均勻變化的數據壓縮效果是非常好的,但是隨機數基本上不會被壓縮,圖就不貼了。

 

轉自:http://blog.csdn.net/gneveek/article/details/7821151


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM