NIOS2随笔——JPEG解码与VGA显示

简介:

1. 系统概述

本设计采用NIOS2 32位处理器,通过SPI接口将SD/TF卡中的JPEG图片数据读取到内存中,SD/TF卡的文件系统为FAT32,NIOS2软件实现JPEG解码后,启动framereader和Clocked Video Output模块,最终在VGA显示器上显示JPEG图像,系统框图如下:

wKiom1hyOLKh4a8LAABiPj1DLCI656.png


2. JPEG格式

JPEG(Joint Photographic Experts Group)是第一个国际图像压缩标准,提供了良好的压缩性能的同时,具有较好的图像质量,被广泛应用电子产品和芯片设计中。

JPEG文件格式有两种保存方式,分别是Baseline JPEG和Progressive JPEG。

Baseline JPEG:这种类型的JPEG文件存储方式是按从上到下的扫描方式,把每一行顺序的保存在JPEG文件中。显示时,数据将按照从上到下一行一行的被显示出来。

Progressive JPEG:包含多次扫描,这些扫描顺寻的存储在JPEG文件中。显示时,会先显示整个图片的模糊轮廓,随着扫描次数的增加,图片变得越来越清晰。

JPEG压缩算法过程如下:

wKiom1hyO-7zQcSTAAAFrvAYuH0466.gif

3. Tiny JPEG Decompressor

TJpgDec是一个通用的JPEG图像解码模块,基于C语言开发且可以用于小型嵌入式系统中。

TJpgDec提供了两个API函数接口:

  • jd_prepare为图像解码准备足够的信息

  • jd_decomp执行解码任务

还提供了两个I/O函数接口:

  • Input function: 从输入流中读取JPEG文件数据

  • Output function: 将图像数据写入输出设备

wKioL1hyPhHRfpzcAAANDOA7iuw621.png

开源的代码可以在http://elm-chan.org/fsw/tjpgd/00index.html下载。


3. 搭建Qsys

在博文NIOS2随笔——FAT32文件系统的基础上,在Qsys平台上添加framereader和Clocked Video Output组件,设置分辨率为640*480,VGA相关内容可以参考博文FPGA设计——VGA (Altera)

搭好的Qsys平台如下图:

wKioL1hyPzKzq5vPAAEtOwmsJNg487.jpg


4. NIOS2软件设计

TTJpgDec是基于Baseline JPEG算法编写,需要以Baseline方式保存一幅JPEG图片到SD卡中,图像分辨率为640*480,文件名为desk.jpg,在电脑中打开如下:

wKioL1hyP_zCr3ElAAh-zmph3IM660.png

在博文NIOS2随笔——FAT32文件系统的软件基础上,编写软件代码。

移植JPEG软件解码模块,主要是编写Input和Output函数。VGA显示部分,要对framereader组件初始化,然后存放在数组中的图像数据便会不停地被读取到Clocked Video Output模块,最后数据会被送到VGA编码芯片显示。编写好的Input、Output及main函数代码设计如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//============JPEG user function==============
 
/*------------------------------*/
/* User defined input funciton  */
/*------------------------------*/
 
UINT  in_func (JDEC* jd,  BYTE * buff,  UINT  nbyte)
{
     u32  rb=0;     //number of byte read
     f_read(&tf_jpeg,buff,nbyte,&rb);
 
     return  rb;
}
 
/*------------------------------*/
/* User defined output funciton */
/*------------------------------*/
 
UINT  out_func (JDEC* jd,  void * bitmap, JRECT* rect)
{
        BYTE  *src, *dst;
        UINT  y, bws, bwd;
 
         if  (rect->left == 0) {
             printf ( "\r%lu%%" , (rect->top << jd->scale) * 100UL / jd->height);
         }
 
         src = ( BYTE *)bitmap;
         dst = picture_buffer + 3 * (rect->top * FRAME_WIDTH+ rect->left);
         bws = 3 * (rect->right - rect->left + 1);
         bwd = 3 * FRAME_WIDTH;
         for  (y = rect->top; y <= rect->bottom; y++) {
             memcpy (dst, src, bws);
             src += bws; dst += bwd;
         }
 
         return  1;
}
 
FATFS fs;
FIL  tf_jpeg;
BYTE  res=0;
 
int  main ( void )
{
     UINT  *work;
     JDEC tjpeg_dev;
     UINT  x=0;
     UINT  y;
 
     FrameRd_init();
 
     f_mount(&fs, "" ,0);
     //Open a JPEG file
     res = f_open(&tf_jpeg, "0:/desk.jpg" ,FA_READ);
 
     work =  malloc (3800);
 
     //Prepare to decompress
     res = jd_prepare(&tjpeg_dev, in_func, work, 3800, &tf_jpeg);
 
     if  (res == JDR_OK) {
         //Ready to dcompress. Image info is available here.
         printf ( "Image dimensions: %u by %u. %u bytes used.\n" , tjpeg_dev.width, tjpeg_dev.height, 3800 - tjpeg_dev.sz_pool);
 
         res = jd_decomp(&tjpeg_dev, out_func, 0);    // Start to decompress with 1/1 scaling
         if  (res == JDR_OK) {
             //Decompression succeeded. You have the decompressed image in the frame buffer here.
             printf ( "\nOK  \n" );
         }
         else
         {
             printf ( "Failed to decompress: rc=%d\n" , res);
         }
 
     }
     else
     {
         printf ( "Failed to prepare: rc=%d\n" , res);
     }
 
     f_close(&tf_jpeg);        //Close the JPEG file
 
     for (y=0;y<FRAME_SIZE*3;y=y+3)
     {
         picture_buf[x] = picture_buffer[y]*65536+(picture_buffer[y+1])*256+(picture_buffer[y+2]);
         x++;
     }
 
     printf ( "image processed done\n" );
 
     while (1);
 
     return  0;
}


5. 编译运行

编译成功后,以Hardware方式运行,终端打印进度信息,最后显示:image processed done!

wKioL1hyQm7jGpepAAAvyy_w3Nw746.png


6. 最终结果

图片正常显示,和电脑上打开的desk.jpg一致,此图片还是博主4年前用Nokia手机在群租房里面拍的一张照片,满满的回忆啊。

wKioL1hyRFXzuzPOAAB2FBbvZ1c151.jpg




本文转自 shugenyin 51CTO博客,原文链接:http://blog.51cto.com/shugenyin/1890239

相关文章
|
Android开发 异构计算
nios ii FIFO读取FPGA数据交互实验1
nios ii FIFO读取FPGA数据交互实验1
258 0
nios ii FIFO读取FPGA数据交互实验1
|
Android开发 C++ 芯片
nios ii小实验——第一个demo指导书
nios ii小实验——第一个demo指导书
191 0
nios ii小实验——第一个demo指导书
|
异构计算
nios ii小实验——SDRAM读写
nios ii小实验——SDRAM读写
244 0
nios ii小实验——SDRAM读写
|
6月前
FFmpeg开发笔记(二十二)FFmpeg中SAR与DAR的显示宽高比
《FFmpeg开发实战》书中指出,视频宽高处理需考虑采样宽高比(SAR),像素宽高比(PAR)和显示宽高比(DAR)。SAR对应AVCodecParameters的sample_aspect_ratio,PAR为width/height。当SAR的num与den不为1时,需计算DAR以正确显示视频。书中提供了转换公式和代码示例,通过SAR或DAR调整视频尺寸。在修正后的playsync2.c程序中,成功调整了meg.vob视频的比例,实现了正确的画面显示。
88 0
FFmpeg开发笔记(二十二)FFmpeg中SAR与DAR的显示宽高比
|
存储 传感器 编解码
Qt开发笔记之编码x264码流并封装mp4(三):Qt使用x264库对.yuv文件编码为.h264文件
Qt开发笔记之编码x264码流并封装mp4(三):Qt使用x264库对.yuv文件编码为.h264文件
Qt开发笔记之编码x264码流并封装mp4(三):Qt使用x264库对.yuv文件编码为.h264文件
|
编解码 计算机视觉 Windows
Qt实用技巧:使用QMediaPlayer和Windows自带组件播放swf、rmvb、mpg、mp4等视频文件
Qt实用技巧:使用QMediaPlayer和Windows自带组件播放swf、rmvb、mpg、mp4等视频文件
Qt实用技巧:使用QMediaPlayer和Windows自带组件播放swf、rmvb、mpg、mp4等视频文件
|
存储 编解码 Linux
嵌入式Linux下LCD应用编程: 调用giflib库解码显示GIF动态图
嵌入式Linux下LCD应用编程: 调用giflib库解码显示GIF动态图
774 0
嵌入式Linux下LCD应用编程: 调用giflib库解码显示GIF动态图