大一第一次大作业-QOI解码编码器

· · 个人记录

一天12h直接肝完的奇迹

调试到裂开

https://phoboslab.org/log/2021/11/qoi-fast-lossless-image-compression

https://blog.csdn.net/u013798145/article/details/122094109

https://qoiformat.org/qoi-specification.pdf

参考代码:https://github.com/phoboslab/qoi/blob/master/qoi.h

调试可用:https://tools.acm.sjtu.app/qoi/

首先考虑encode的方式

按优先级排列分别是RUN,INDEX,DIFF,LUMA,RGB,RGBA

对于rgb格式只用前五种,rgba会用到第六种

整体以8\text{bit}为单位进行储存

0个像素默认为r=0,g=0,b=0,a=255

如果当前像素与前一个像素信息相同,则用RUN(编码开头前两位为11)记录其重复次数(<=62,因为取到就会与RGB和RGBA对应的编码重复,注意存储的时候会有一个-1的偏差存储,从0开始存,输出的时候注意这一点)

如果不同,会有一个哈希数组记录着前面像素的信息,如果能够找到对应的哈希且具体信息相同(因为可能具体信息不同而哈希相同),则使用INDEX编码(编码开头为00)

哈希方式为r*3+g*5+b*7+a*11(即使为rgb格式也要算a血的教训)

注意这里处理方式是如果哈希内部的值不同,那么就替换他,实时更新

那么如果不同的话,我们就来到DIFF和LUMA编码

两种方法都是通过该像素和前一个像素的残差来编码的

如果RGB三个通道残差都在-21范围内(当前像素减之前的)

那么就是用DIFF记录(编码开头为01),占用6\text{bit}

而若不能用DIFF且G通道残差在-3231范围内

R和B的残差与G的残差之差(前者减后者)在-87范围内

那么可以使用LUMA(编码为10),先用剩余的6\text{bit}存储G的残差

然后再使用8\text{bit}分成两半记录R和B的残差与G的残差之差

如果上述都不能使用的话,就只能直接记录rgb,反向压缩(就是没用压缩反而扩大了,因为要打标签)

rgb标签为11111110,后面再记录rgb数值

除了rgb和rgba编码剩下编码都有不错的平均压缩率,而且压缩效率很快

如果是rgba格式的话,只需要改变一点

即在使用DIFF和LUMA的时候必须要求前后的a相同,如果不同只能使用rgba编码(标签为11111111)

所有QOI文件最后会有8个00000001代表文件结束

写的时候注意是按像素个数读入输出还是按压缩后的数量读入输出

这个QOI的初始设计者可能就是想要在模256意义下运算,为了避免各种麻烦,助教建议以后所有的变量统一大小运算(位数)

码风提示(大作业一定要注意):变量名多用下划线使含义清晰

别用逗号表达式,用分号表达式

if条件换行的时候条件对齐