學過GIS的人應該都知道,在這個大數據時代,我們的地圖數據量有時候往往是非常龐大的,存儲它將會耗費非常多的內存,讀取速度也相對減慢了。所以GISer們常常會對柵格的地圖數據進行壓縮編碼存儲,等到要用到這個數據的時候再解壓縮顯示就好了,這樣不僅可以節約大量的存儲空間,而且節省了系統讀取和反應的時間。柵格數據壓縮編碼的方法有很多種,包括鏈式編碼、行程編碼、塊式編碼和四叉樹編碼。今天我們就來講一下行程編碼(也叫游程編碼)。
所謂游程編碼,就是只在各行(或列)數據的代碼發生變化時依次記錄該代碼以及相同代碼重復的個數,即按(屬性值,重復個數)編碼。例如:圖像某一行一部分像素的顏色分別是222222222333333111(一個像素對應一個顏色代號),那么用游程編碼的方式壓縮就是293613,是不是就節省了一些空間呢?注意這才只是圖像的一小部分,要是整個圖像都用這種方法來存儲,可想而知將會節省更多的空間啦!
我們假設給你一幅圖像(這也是我以前做過的作業啦~\(≧▽≦)/~嘻嘻),這個圖像是.dat格式的,按照第一個字節存儲圖像的寬度值Width(int型的哈),第二個字節存儲圖像的高度值Height,從第三個字節位置開始一直到最后存儲的都是圖像上每一個像素上的顏色(unsigned型)。
原圖是這樣的:
代碼如下:

1 // 柵格數據游程編碼后解壓縮.cpp : 定義控制台應用程序的入口點。 2 // 3 4 #include "stdafx.h" 5 #include "Graph.h" 6 #include "malloc.h" 7 8 void drawpicture(unsigned R[]); 9 10 int _tmain(int argc, _TCHAR* argv[]) 11 { 12 unsigned * a=NULL,* b=NULL,* c=NULL; 13 14 FILE* fp = fopen("../圖片int.dat", "rb");//二進制文件讀操作 15 if (fp) 16 { 17 //讀入數組 18 int width, height; 19 fread(&width, sizeof(int), 1, fp); 20 fread(&height, sizeof(int), 1, fp); 21 22 a = (unsigned*)malloc(sizeof(unsigned)* (width * height + 2)); 23 a[0] = width; 24 a[1] = height; 25 fread(a + 2, sizeof(unsigned), width*height, fp); 26 } 27 fclose(fp); 28 29 30 printf("原圖為:"); 31 drawpicture(a); 32 33 34 //游程編碼壓縮 35 int w = 2 + a[0]*a[1]; 36 37 b = (unsigned*)malloc(sizeof(unsigned)* (2 * w)); 38 b[0] = a[0]; 39 b[1] = a[1]; 40 int j = 3, t = a[2]; 41 for (int i = 3; i <= w; i++)//b[2]存放的是b[2]到數組末尾一共的元素個數 42 { 43 int n = 1; 44 for (; i < w && a[i] == t; i++) 45 n++; 46 47 b[j++] = t; 48 b[j++] = n; 49 50 if (i < w) 51 t = a[i]; 52 else 53 break; 54 } 55 b[2] = j; 56 printf("壓縮完成."); 57 //壓縮完畢 58 59 //解壓縮 60 61 c = (unsigned*)malloc(sizeof(unsigned)* (b[0] * b[1] + 2)); 62 c[0] = b[0]; 63 c[1] = b[1]; 64 int k = 2; 65 for (int i = 3; i<b[2]; i += 2) 66 { 67 for (j = 0; j < b[i + 1]; j++) 68 c[k++] = b[i]; 69 } 70 //解壓完畢 71 72 clearWindow(); 73 printf("現在圖為:"); 74 drawpicture(c); 75 clearWindow(); 76 } 77 78 void drawpicture(unsigned R[]) 79 { 80 setOrig(100,100); 81 82 for (int i = 0; i < R[0] * R[1]; i++) 83 { 84 setPixel(i % R[0], i / R[0], R[i + 2]); 85 } 86 getchar(); 87 88 clearWindow(); 89 90 return ; 91 }
現在是見證奇跡的時刻,經過游程編碼壓縮后的圖像,再解壓后得到代碼中的c數組,顯示C數組的結果是否和壓縮之前一模一樣呢?!結果如下:
看看是不是還是一模一樣呢!好啦,大功告成!