Hard-PNG/README.md

144 lines
7.2 KiB
Markdown
Raw Normal View History

2022-03-30 00:13:08 +08:00
![语言](https://img.shields.io/badge/语言-systemverilog_(IEEE1800_2005)-CAD09D.svg) ![仿真](https://img.shields.io/badge/仿真-iverilog-green.svg) ![部署](https://img.shields.io/badge/部署-quartus-blue.svg) ![部署](https://img.shields.io/badge/部署-vivado-FF1010.svg)
2021-11-01 15:44:10 +08:00
Hard-PNG
===========================
2022-03-29 19:41:01 +08:00
基于FPGA的流式的 **png** 图象解码器,输入 png 码流,输出原始像素
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
* 支持图像宽度<4000高度不限
* **支持所有颜色类型**:灰度、灰度+A、RGB、索引RGB、RGB+A。
* 仅支持8bit深度大多数 png 图像都是8bit深度
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| ![diagram](./figures/diagram.png) |
| :----: |
| 图1 : Hard-PNG 原理框图 |
2021-11-01 15:44:10 +08:00
# 背景知识
2022-03-29 19:41:01 +08:00
png 是仅次于jpg的第二常见的图象压缩格式。png支持透明通道A通道支持无损压缩支持索引RGB基于调色板的有损压缩。在色彩丰富的数码照片中png只能获得1~4倍的压缩比。在人工合成图例如平面设计png能获得10倍以上的压缩比。
png 图像文件的扩展名为 .png 。以本库中的 SIM/test_image/img01.png 为例它包含98字节这98字节就称为 png 码流。我们可以用 [WinHex软件](http://www.x-ways.net/winhex/) 查看到这些字节:
2021-11-01 15:44:10 +08:00
```
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, ...... , 0xAE, 0x42, 0x60, 0x82
```
2022-03-29 19:41:01 +08:00
该png码流解码后会产生原始像素这是个小图像只有4列2行共8个像素这些像素的十六进制表示如下表。其中R, G, B, A分别代表像素的红、绿、蓝、透明通道。
2021-11-01 15:44:10 +08:00
| | 列 1 | 列 2 | 列 3 | 列 4 |
| :---: | :---: | :---: | :---: | :---: |
2022-03-29 19:41:01 +08:00
| 行 1 | R:FF G:F2 B:00 A:FF | R:ED G:1C B:24 A:FF | R:00 G:00 B:00 A:FF | R:3F G:48 B:CC A:FF |
| 行 2 | R:7F G:7F B:7F A:FF | R:ED G:1C B:24 A:FF | R:FF G:FF B:FF A:FF | R:FF G:AE B:CC A:FF |
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
# 使用 Hard-PNG
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
RTL 目录中的 hard_png.sv 是一个能够输入 png 码流输出解压后的像素的模块它的接口如图2所示。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| ![接口图](./figures/interface.png) |
2021-11-01 15:44:10 +08:00
| :----: |
2022-03-29 19:41:01 +08:00
| 图2 : hard_png 接口图 |
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
hard_png 的使用方法很简单,在输入一张 png 图像的码流前,先要给模块复位(令 rstn=0 至少一个时钟周期),然后解除复位(令 rstn=1然后输入 png 码流,并从图象基本信息输出接口和像素输出接口中得到解码结果。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
以 SIM/test_image/img01.png 为例我们应该以图3的时序把 png 码流中的98个字节逐一输入到 hard_png 中。其中 ivalid 和 iready 构成了握手信号: ivalid=1 时说明外部想发送一个字节给 hard_png。iready=1 时说明 hard_png 已经准备好接收一个字节。只有 ivalid 和 iready 同时=1 时ibyte 才被成功的输入 hard_png 中。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| ![输入时序图](./figures/wave1.png) |
2021-11-01 15:44:10 +08:00
| :----: |
2022-03-29 19:41:01 +08:00
| 图3 : hard_png 的输入波形图 |
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
在输入的同时解压结果从模块中输出如图4。在一帧图象输出前newframe 信号会出现一个时钟周期的高电平脉冲,同时 colortype, width, height 有效。其中:
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
- width, height 分别为图象的宽度和高度
- colortype 为 png 图像的颜色类型,含义如下表。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| colortype | 3'd0 | 3'd1 | 3'd2 | 3'd3 | 3d4 |
| :-------: | :--: | :--: | :--: | :--: | :--: |
| 颜色类型 | 灰度 | 灰度+A | RGB | RGB+A | 索引RGB |
| 备注 | R=G=BA=0xFF | R=G=B≠A | R≠G≠BA=0xFF | R≠G≠B≠A | R≠G≠BA=0xFF |
然后ovalid=1 代表该时钟周期有一个像素输出,该像素的 R,G,B,A 通道分别出现在 opixelr,opixelg,opixelb,opixela 信号上。
| ![输出时序图](./figures/wave2.png) |
2021-11-01 15:44:10 +08:00
| :----: |
2022-03-29 19:41:01 +08:00
| 图4 : hard_png 的输出波形图 |
当一个 png 图象输入结束后,可以立即或稍后输入下一张图像(复位->解除复位->输入码流)。
2021-11-01 15:44:10 +08:00
# 仿真
2022-03-29 19:41:01 +08:00
仿真相关的东西都在 SIM 文件夹中,其中:
- test_image 中提供 14 张不同尺寸,不同颜色类型的 png 图像文件。
- tb_hard_png.sv 是仿真代码,它会依次进行这些图像的压缩,然后把结果(原始像素)写入 txt 文件中。
- tb_hard_png_run_iverilog.bat 包含了运行 iverilog 仿真的命令。
- validation.py Python代码对仿真输出和软件 png 解码的结果进行比对,验证正确性。
使用 iverilog 进行仿真前,需要安装 iverilog ,见:[iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md)
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
然后双击 tb_hard_png_run_iverilog.bat 运行仿真,会运行大约半小时(可以中途强制关闭,但产生的仿真波形就是不全的)。
仿真运行完后,可以打开生成的 dump.vcd 文件查看波形。
另外,每个 png 图像都会产生一个对应的 txt 文件,里面是解码结果。比如 img01.png 对应地产生 out01.txt ,里面包含了解码出的 8 个像素的值:
```
decode result: colortype:3 width:4 height:2
fff200ff ed1c24ff 000000ff 3f48ccff 7f7f7fff ed1c24ff ffffffff ffaec9ff
```
## 正确性验证
为了验证解压结果是否正确,我提供了 Python 程序 validation.py它对 .png 文件进行解压,并与仿真产生的 .txt 文件中的每个像素进行比较,若比较结果相同则验证通过。
为了运行 validation.py ,请安装 Python3 以及其配套的 [numpy](https://pypi.org/project/numpy/) 和 [PIL](https://pypi.org/project/Pillow/) 库。
安装好后,用 CMD 命令运行它,比如:
2021-11-01 15:44:10 +08:00
```
2022-03-29 19:41:01 +08:00
python validation.py test_image/img03.png out03.txt
2021-11-01 15:44:10 +08:00
```
2022-03-29 19:41:01 +08:00
这个命令的含义是: 比较 out03.txt 中的每个像素是否与 test_image/img03.png 匹配。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
打印如下(说明验证通过):
2021-11-01 15:44:10 +08:00
```
2022-03-29 19:41:01 +08:00
size1= (400, 4)
size2= (400, 4)
total 400 pixels validation successful!!
2021-11-01 15:44:10 +08:00
```
2022-03-29 19:41:01 +08:00
# 部署信息
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
## FPGA 资源消耗
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| FPGA 型号 | LUT | LUT(%) | FF | FF(%) | Logic | Logic(%) | BRAM | BRAM(%) |
| :----------------------------: | :--: | :----: | :--: | :---: | :---: | :------: | :-----: | :-----: |
| Xilinx Artix-7 XC7A35T | 2581 | 13% | 2253 | 5% | - | - | 792kbit | 44% |
| Altera Cyclone IV EP4CE40F23C6 | - | - | - | - | 4551 | 11% | 427kbit | 37% |
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
## 性能
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
在 Altera Cyclone IV EP4CE40F23C6 上部署 hard_png ,时钟频率= 50MHz (正好时序收敛)。根据仿真时每个图像消耗的时钟周期数,可以算出压缩图像时的性能,举例如下表。
2021-11-01 15:44:10 +08:00
2022-03-29 19:41:01 +08:00
| png文件名 | 颜色类型 | 图象长宽 | png 码流大小 (字节) | 消耗的时钟周期数 | 消耗时间 |
| :-----------: | :----------: | :----------: | :--------------: | :---------------: | :---------------: |
| img05.png | RGB | 300x256 | 96536 | 1105702 | 23ms |
| img06.png | 灰度 | 300x263 | 37283 | 395335 | 8ms |
| img10.png | 索引RGB | 631x742 | 193489 | 2374224 | 48ms |
| img14.png | 索引RGB | 1920x1080 | 818885 | 10177644 | 204ms |
2021-11-01 15:44:10 +08:00
# 参考链接
2022-03-29 19:41:01 +08:00
* [upng](https://github.com/elanthis/upng): 一个轻量化的 C 语言 png 解码库
* [TinyPNG](https://tinypng.com/): 一个利用索引 RGB 对 png 图像进行有损压缩的工具
* [PNG Specification](https://www.w3.org/TR/REC-png.pdf): png 标准手册