游程编码压缩及解压缩

学过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 }
View Code

现在是见证奇迹的时刻,经过游程编码压缩后的图像,再解压后得到代码中的c数组,显示C数组的结果是否和压缩之前一模一样呢?!结果如下:

看看是不是还是一模一样呢!好啦,大功告成!

posted @ 2016-10-23 14:12  yogurtWX  阅读(4866)  评论(1编辑  收藏  举报