jpg是一种压缩的图片格式,之所以压缩是为了减小图片所占空间,jpg压缩原理这里不罗嗦,可以自行百度或者b站,大佬讲的比我好,jpg解压缩就是逆向过程,用opencv啥的解压缩就是一句话的事儿,但对于fpga硬件来说就是大型工程了。
整个工程思路框图如下:
第一步:百度下载一张1280X720尺寸的jpg格式图片,用matlab等工具将jpg图片转为c语言数组;
第二步:用vivado的sdk将c语言数组拷贝到zynq的ps端ddr3;
第三步:用axi4主控制器从zynq的ps端ddr3中把jpg图像读到zynq的pl端fpga,并转为axis数据流;
第四步:jpg图像的axis数据流进入jpg解码器模块,并解码转化为rgb数据,并生成场同步信号vs和数据有效信号de;
第五步:用fdma方案将rgb数据写入ddr3做三帧缓存并读出;
第六步:读出的rgb图像数据送hdmi显示模块输出显示器;
补充说明:
1:由于jpg是单张图片,并不像视频那样是连续的,所以这里从ps端ddr3中读取图像需要认为的给一个脉冲信号,相当于视频的场同步信号vs,由于使用的是zynq,所以直接用axi_gpio输出给fpga,这样就能由sdk软件控制jpg图片的读取;
2:第五步中的fdma方案是我一直用的图像缓存方案,可参考我之前的文章fdma三帧缓存方案
FPGA工程如下:
BD部分:
FPGA代码部分:
SDK代码部分:
int main()
{
init_platform();
write_pic(); //拷贝jpg数组到内存
XGpioCfg = XGpio_LookupConfig(XPAR_AXI_GPIO_0_DEVICE_ID);
XGpio_CfgInitialize(&video_gpio, XGpioCfg, XGpioCfg->BaseAddress);
XGpio_SetDataDirection(&video_gpio, 1, 0);
XGpio_SetDataDirection(&video_gpio, 2, 0);
XGpio_DiscreteWrite(&video_gpio, 2, 4096*30);
XGpio_DiscreteWrite(&video_gpio, 1, 1);
while(1){
XGpio_DiscreteWrite(&video_gpio, 1, 1);
usleep(30000);
XGpio_DiscreteWrite(&video_gpio, 1, 3); //SDK触发jpg读脉冲,切记要用debug单步调试模式
XGpio_DiscreteWrite(&video_gpio, 1, 1);
}
cleanup_platform();
return 0;
}
上板调试:
开发板:米联客zynq7100开发板;
开发环境:vivado2019.1;
输入:1280X720尺寸jpg图片;
输出:720P分辨率HDMI视频,rgb888格式;
调试要点:
1、运行SDK时切记要用debug单步调试模式,这样才能稳步触发jpg读图片并解码,因为在while(1)死循环里时间间隔太小,硬件反应不过来,如果需要持续触发则需要加适当的延时;
2、SDK拷贝图片进ddr3时需要4K对齐;
3、XGpio_DiscreteWrite(&video_gpio, 2, 4096*30);这句话是jpg读图片的地址长度,可以适当设置大一些,因为jpg解码器在读到jpg数据包帧尾时就完成了解码,多余的数据不会再利用;
直接上调试结果:
左边屏幕为jpg原图;左边屏幕为解码后输出hdmi显示的rgb视频;
福利:快**“关注并私信我”**获得源码及工程吧。。。