编辑: You—灰機 2019-07-02

12 11

10 9

8 7

6 5

11 10

9 8

7 6

5 4

10 9

8 7

6 5

4 3

9 8

7 6

5 4

3 2

8 7

6 5

4 3

2 1

7 6

5 4

3 2

1 0

6 5

4 3

2 1

0 0

5 4

3 2

1 0

0 0 PNG Spec中指出,如果PNG文件不是采用隔行扫描方法存储的话,那么,数据是按照行(ScanLine)来存储的,为了区分第一行,PNG规定在每一行的前面加上0以示区分,因此,上面的图像映射应该如下:

0 12

11 10

9 8

7 6

5 0

11 10

9 8

7 6

5 4

0 10

9 8

7 6

5 4

3 0

9 8

7 6

5 4

3 2

0 8

7 6

5 4

3 2

1 0

7 6

5 4

3 2

1 0

0 6

5 4

3 2

1 0

0 0

5 4

3 2

1 0

0 0 另外,需要注意的是,由于PNG在存储图像时为了节省空间,因此每一行是按照位(Bit)来存储的,而并不是我们想象的字节(Byte),如果你没有忘记的话,我们的IHDR数据块中的色深就指明了这一点,所以,为了凑成PNG所需要的IDAT,我们的数据得改成如下:

0 203

169 135

101 0

186 152

118 84

0 169

135 101

67 0

152 118

84 50

0 135

101 67

33 0

118 84

50 16

0 101

67 33

0 0

84 50

16 0 最后,我们对这些数据进行LZ77压缩就可以得到IDAT的正确内容了. 然而,事情并不是这么简单,因为我们研究的是手机上的PNG,如果需要在手机上完成LZ77压缩工作,消耗的时间是可想而知的,因此,我们得再想办法加减少压缩时消耗的时间. 好在LZ77也提供了无压缩的压缩方法(奇怪吧?),因此,我们只需要简单的使用无压缩的方式写入数据就可以了,这样虽然浪费了空间,却换回了时间! 好了,让我们看一看怎么样凑成无压缩的LZ77压缩块: 字节 意义 0~2 压缩信息,固定为0x78, 0xda, 0x1 3~6 压缩块的LEN和NLEN信息 压缩的数据 最后4字节 Adler32信息 其中的LEN是指数据的长度,占用两个字节,对于我们的图像来说,第一个Scan Line包含了5个字节(如第一行的0, 203, 169, 135, 101),所以LEN的值为5(字节/行) * 8(行) = 40(字节),生成字节为28 00(低字节在前),NLEN是LEN的补码,即NLEN = LEN ^ 0xFFFF,所以NLEN的为 D7 FF,Adler32信息为24 A7 0B A4(具体算法见源程序),因此,按照这样的顺序,我们生成IDAT数据块,最后,我们将IHDR、PLTE、IDAT和IEND数据块写入文件中,就可以得到PNG文件了,如图: (选中的部分为生成的"压缩"数据) 至此,我们已经能够采用最快的时间将数组转换为PNG图片了.

下载(注:源文件不在本站服务器,都将跳转到源网站下载)
备用下载
发帖评论
相关话题
发布一个新话题