Hard-PNG/README.md
WangXuan95 432e4d0440 update
2022-04-02 19:45:58 +08:00

147 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

![语言](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)
Hard-PNG
===========================
基于FPGA的流式的 **png** 图象解码器,输入 png 码流,输出原始像素
* 支持图像宽度<4000高度不限
* **支持所有颜色类型**灰度灰度+ARGB索引RGBRGB+A
* 仅支持8bit深度大多数 png 图像都是8bit深度)。
| ![diagram](./figures/diagram.png) |
| :----: |
| **图1** : Hard-PNG 原理框图 |
# 背景知识
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/) 查看到这些字节
```
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, ...... , 0xAE, 0x42, 0x60, 0x82
```
该png码流解码后会产生原始像素这是个小图像只有4列2行共8个像素这些像素的十六进制表示如下表其中R, G, B, A分别代表像素的红绿透明通道
| | 1 | 2 | 3 | 4 |
| :---: | :---: | :---: | :---: | :---: |
| 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 |
# 使用 Hard-PNG
RTL 目录中的 hard_png.sv 是一个能够输入 png 码流输出解压后的像素的模块它的接口如**图2**所示
| ![接口图](./figures/interface.png) |
| :----: |
| **图2** : hard_png 接口图 |
## 输入码流
hard_png 的使用方法很简单 SIM/test_image/img01.png 这张图像为例**图3**在输入一张图象的码流前先要令 istart 上产生一个高电平脉冲宽度至少为一个时钟周期然后通过 ivalid ibyte 信号来输入码流这张图象的 png 码流有 98 字节 98 字节都要逐一输入给 hard_png其中 ivalid iready 构成了握手信号 ivalid=1 时说明外部想发送一个字节给 hard_pngiready=1 时说明 hard_png 已经准备好接收一个字节只有 ivalid iready 同时=1 时握手才成功ibyte 才被成功的输入 hard_png
| ![输入时序图](./figures/wave1.png) |
| :----: |
| **图3** : hard_png 的输入波形图 |
当一张 png 图象的码流输入结束后可以立即或稍后输入下一张图像也就是让 istart 上产生高电平脉冲然后输入码流)。
## 输出图像信息和像素
在输入码流的同时这张图象的解压结果也就是图像基本信息和原始像素会从模块中输出**图4**在图象的像素输出前ovalid 信号会出现一个时钟周期的高电平脉冲同时 colortype, width, height 会有效其中
- width, height 分别是图象的宽度和高度
- colortype png 图像的颜色类型含义如下表
| colortype | 3'd0 | 3'd1 | 3'd2 | 3'd3 | 3d4 |
| :-------: | :--: | :--: | :--: | :--: | :--: |
| 颜色类型 | 灰度 | 灰度+A | RGB | RGB+A | 索引RGB |
| 备注 | R=G=BA=0xFF | R=G=B≠A | RGBA=0xFF | RGBA | RGBA=0xFF |
然后ovalid=1 代表该时钟周期有一个像素输出该像素的 R,G,B,A 通道会分别出现在 opixelr,opixelg,opixelb,opixela 信号上
| ![输出时序图](./figures/wave2.png) |
| :----: |
| **图4** : hard_png 的输出波形图 |
# 仿真
仿真相关的东西都在 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)
然后双击 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 命令运行它比如
```
python validation.py test_image/img03.png out03.txt
```
这个命令的含义是 比较 out03.txt 中的每个像素是否与 test_image/img03.png 匹配
打印如下说明验证通过
```
size1= (400, 4)
size2= (400, 4)
total 400 pixels validation successful!!
```
# 部署信息
## FPGA 资源消耗
| FPGA 型号 | LUT | LUT(%) | FF | FF(%) | Logic | Logic(%) | BRAM | BRAM(%) |
| :----------------------------: | :--: | :----: | :--: | :---: | :---: | :------: | :-----: | :-----: |
| Xilinx Artix-7 XC7A35T | 2581 | 13% | 2253 | 5% | - | - | 792kbit | 44% |
| Altera Cyclone IV EP4CE40F23C6 | - | - | - | - | 4682 | 11% | 427kbit | 37% |
## 性能
Altera Cyclone IV EP4CE40F23C6 上部署 hard_png 时钟频率= 50MHz 正好时序收敛)。根据仿真时每个图像消耗的时钟周期数可以算出压缩图像时的性能举例如下表
| 文件名 | 颜色类型 | 图象长宽 | 像素数 | png 码流大小 (字节) | 时钟周期数 | 消耗时间 |
| :-----------: | :----------: | :----------: | :--------------: | :---------------: | :---------------: | ------------- |
| img05.png | RGB | 300x256 | 76800 | 96536 | 1105702 | 23ms |
| img06.png | 灰度 | 300x263 | 78900 | 37283 | 395335 | 8ms |
| img09.png | RGBA | 300x263 | 78900 | 125218 | 1382303 | 28ms |
| img10.png | 索引RGB | 631x742 | 468202 | 193489 | 2374224 | 48ms |
| img14.png | 索引RGB | 1920x1080 | 2073600 | 818885 | 10177644 | 204ms |
# 参考链接
* [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 标准手册