实现APNG图片解码及缩放显示
在实现GIF图片缩放的文章中,我们使用了GIF解码器来实现GIF图片的解码,然后修改了SSIV的代码来实现动图的缩放。而APNG也是一种动态图片,是在APNG格式上进行扩展而来的,关于apng的文档参考这个链接,关于PNG的详细资料参考这个链接。
APNG的结构图
普通的png的结构是Signature(校验)开头,然后是IHDR(包含图片信息),然后是各种辅助块,最后是IDAT数据块和IEDN结束块。而APNG的开始和PNG相同,只是在IDAT之前会有acTL块,标识着是APNG图片。APNG还比PNG多了fcTL和fdAT块,其中fcTL的信息是标识着下一帧图片的信息,如宽高,offset等,而fdAT则是数据块,和IDAT类似,却多了一个sequence_number(帧编号)。如果IDAT之前有fcTL那么IDAT的数据则当做第一帧(如上图),否则忽略(如下图)。
块的结构
每一块都是这个结构,4个字节标识数据的长度,4个字节标识块类型,然后是数据(如果数据长度为0则无数据内容),最后是CRC校验。除了PNG签名,其他数据都比较符合这个规则。
然后看一下每个部分的内容。
PNG signature:PNG签名,不是块类型,固定为8字节内容:137 80(P) 78(N) 71(G) 13 10 26 10
IHDR块内容:宽高就表示图片宽高,其他表示图片绘制信息
Width 4 bytes 宽度
Height 4 bytes 高度
Bit depth 1 byte 位深
Colour type 1 byte
Compression method 1 byte
Filter method 1 byte
Interlace method 1 byte
acTL块:包含了图片的帧数和循环次数(0表示无限循环)
num_frames 4bytes 帧数
num_plays 4bytes 循环次数
fcTL块:包含了当前帧图片的宽高,offset,延迟,和绘制方式
sequence_number 4bytes 帧编号
width 4bytes 宽度
height 4bytes 高度
x_offset 4bytes x偏移
y_offset 4bytes y偏移
delay_num 2bytes 延迟时间分子
delay_den 2bytes 延迟时间分母(如果未0则视为100,num和len的比就是延迟的秒)
dispose_op 1bytes 绘制下一帧时需要对当前缓冲区的操作
blend_op 1bytes 绘制当前帧时是混合还是直接替换
IDAT块:包含了图片数据。
frame_data Xbytes 数据,长度由块长度标识决定
fdAT块:包含了帧编号和图片数据
sequence_number 4bytes 帧编号
frame_data Xbytes 数据,长度由块长度标识决定
IEND块:标识图片的结尾,数据为空。
解析过程:先从数据流中读取信息,把图片各种信息保存下来,相关代码如下
int length, type;
boolean done = false;
while (!err() && !done) {length = readInt(); // 长度type = readInt(); // chunk typeswitch (type) {case APngConstant.IHDR_VALUE:readIHDR();break;case APngConstant.acTL_VALUE:readAcTL();break;case APngConstant.fcTL_VALUE:readFcTL();break;case APngConstant.IEND_VALUE:done = true;break;…………default:skip(length);break;}readCRC();if(!done) done = rawData.position() >= rawData.limit();
}
读取帧信息:获取当前帧信息并组合成图片。先读取PNG签名和第一个IDAT之前的所有除了acTL和fcTL的块信息,如果是IDAT的信息则直接读取;如果是fdAT的信息则需要进行处理,把fdAT块的类型改为IDAT,然后去掉帧编号,加上数据信息,因为改变了块的内容,需要重新进行CRC签名后加上修正后的CRC签名;最后加上IEND块;
CRC签名的方式:先更新TYPE的内容,然后更新数据信息即可。相关代码如下
public static void updateCRC(int offset, byte[] bytes, int dataLength) {CRC32 crc32 = new CRC32();// update typecrc32.update(bytes, offset, 4);if (dataLength > 0) {// update datacrc32.update(bytes, offset + 4, dataLength);}// 写入修正后的crcwriteInt4ToBytes((int) crc32.getValue(), bytes, offset + 4 + dataLength);}
生成Bitmap:如果是第一帧,可以直接生成图片,如果是其他帧,则需要blend_op来绘制相关区域。先绘制底图,如果blend_op为0(APNG_BLEND_OP_SOURCE)则需要先清除当前区域再绘制;如果是1(APNG_BLEND_OP_OVER)则可以直接绘制该区域。关于底图的处理则是根据dispose_op来操作的,如果是0(APNG_DISPOSE_OP_NONE)则保存当前为底图;如果是1(APNG_DISPOSE_OP_BACKGROUND)则需要清除当前区域后再保存;如果是2(APNG_DISPOSE_OP_PREVIOUS)则不保存(相当于使用上一帧的底图)。
到此实现了整个APNG图片的解析,源码地址。当然还存在一些问题,例如生成bitmap的方式还有待改进。
结合GIF实现缩放的方式,使用同样的方式即可实现APNG图片的缩放。效果图如下
实现APNG图片解码及缩放显示相关推荐
- 微信小程序图片等比缩放显示正中间
这是小程序 image标签的mode ,对图片的缩放做的处理 缩放 scaleToFill 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 缩放 aspectFit 保持纵横比缩放 ...
- css 图片居中放大,不同比例图片居中缩放显示的三种方法
效果 方法一动态给img标签src属性赋值来达到传入不同比例的图片时始终等比例缩放显示,兼容性最好 HTML代码 复制代码 CSS代码 .img-box{ /*限定图片盒子宽高*/ width:500 ...
- VC6 + OpenCV1.0实现图片缩放显示
用vc6新建一个win32控制台程序,代码: /*功能:实现加载jpg图片,并进行缩放显示开发环境: winXP + vc6 + openCV1.0头文件路径:D:\opensource\opencv ...
- [css] 如何让大小不同的图片等比缩放不变形显示在固定大小的div里?写个例子
[css] 如何让大小不同的图片等比缩放不变形显示在固定大小的div里?写个例子 图片等比缩放 img{ object-fit: cover/contain;}div宽高比例固定,跟随屏幕变化而变化, ...
- 腾讯云 sdk调用 显示 图片解码失败 解决方案
参考人脸识别接入常见问题汇总 - 腾讯云开发者社区-腾讯云的第六条 前情提要,接口需要image 的base64编码str,于是我的基本处理办法是 # 初始化用于对比的图片 filename1 = ' ...
- PyQt5学习:QLabel 标签控件两种 自适应缩放显示图片 方法比较
目录 1.测试代码 2.运行结果与代码分析 1.测试代码(注意py文件命名) 1.1Qtdesigner设计的uipy文件 zoomimage_test.py (请注意这个文件一定要命名为zoomim ...
- JS控制图片显示的大小(图片等比例缩放)
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- android 图片解码显示流程
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jingxia2008/article/details/32327699 问题来源 android 能 ...
- android图片解码显示,android 图片解码显示流程
问题来源 android 可以在 gallery 里面显示内部存储的图片,支持 jpeg,png,gif,bmp 等,甚至文件类型和图片后缀名不一致,只要是图片文件就能显示,然后 git 只会显示第一 ...
- stm32h743单片机嵌入式学习笔记6-压缩图片解码原理
软件解码: JPEG/JPG 的解码过程可以简单的概述为如下几个部分: 1 .从文件头读出文件的相关信息. JPEG 文件数据分为文件头和图像数据两大部分,其中文件头记录了图像的版本. 长宽.采样因子 ...
最新文章
- LeetCode题组:第206题-反转链表
- arm 跳转指令跳转范围
- 【独家揭秘】如何获得60万开发者信任?
- 线程池什么时候调用shutdown方法_ThreadPoolExecutor.shutdown()?
- Hadoop_计算框架MapReduce
- aix解锁oracle用户,aix用户被锁定的解决办法
- mysql trigger 有时 不执行_Mysql 寒假刷题TIPs
- timeout 和 deadline
- 汇编语言答案-王爽第三版
- solr集群solrCloud的搭建
- Sentry的安装搭建与使用
- Kafka权威指南-学习笔记---第一章
- sun认证 java怎么考_Sun认证Java程序员考试技巧分享
- psd 直接导入unity
- ASP一叶知秋 SaaS将会成为08重点
- 阿里云添加管理员用户进行协作
- NETSCOUT 1T10G-1000-2PAK网络分析仪套包
- 怎样知道别人的WiFi密码?
- 全国中学生计算机大赛+试题,全国青少年信息学奥林匹克竞赛(NOI2018)正式开幕(附day1试题)...
- 期货黄金交易平台哪个最可靠?如何选择?