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

1. 系统概述

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

wKioL1hlw1qQ8WNJAABiPLjUvaI537.png


2. BMP格式

BMP(Bitmap)是Windows操作系统中的标准图像文件格式,采用位映射存储格式,没有采用任何压缩技术。图像深度可为1、4、8和24bit,图像的扫描方式是按照从左到右、从下到上的顺序。

BMP图像文件由四部分组成:

  • 位图头文件数据结构

  • 位图信息数据结构

  • 调色板(可选)

  • 位图数据

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
//位图文件头   
typedef  struct  tagBITMAPFILEHEADER
{
     WORD  bfType;      //位图文件的类型,必须为BM-0x424d(1-2字节)
     DWORD  bfSize;     //位图文件的大小,以字节为单位(3-6字节,低位在前)
     WORD  bfReserved1; //位图文件保留字,必须为0(7-8字节)
     WORD  bfReserved2; //位图文件保留字,必须为0(9-10字节)
     DWORD  bfOffBits;  //位图数据的起始位置,以相对于位图(11-14字节,低位在前)
                      //文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;
//位图信息头  
typedef  struct  tagBITMAPINFOHEADER{
     DWORD  biSize; //本结构所占用字节数(15-18字节)
     LONG  biWidth; //位图的宽度,以像素为单位(19-22字节)
     LONG  biHeight; //位图的高度,以像素为单位(23-26字节)
     WORD  biPlanes; //目标设备的级别,必须为1(27-28字节)
     WORD  biBitCount; //每个像素所需的位数,必须是1(双色),(29-30字节)
     //4(16色),8(256色)16(高彩色)或24(真彩色)之一
     DWORD  biCompression; //位图压缩类型,必须是0(不压缩),(31-34字节)
     //1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
     DWORD  biSizeImage; //位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节)
     LONG  biXPelsPerMeter; //位图水平分辨率,每米像素数(39-42字节)
     LONG  biYPelsPerMeter; //位图垂直分辨率,每米像素数(43-46字节)
     DWORD  biClrUsed; //位图实际使用的颜色表中的颜色数(47-50字节)
     DWORD  biClrImportant; //位图显示过程中重要的颜色数(51-54字节)
}BITMAPINFOHEADER;


3. 搭建Qsys

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

搭好的Qsys平台如下图:

wKiom1hlIeajGgCfAAEtOb1N9D8746.jpg

4. NIOS2软件设计

往SD卡中保存一幅分辨率为640*480的24位BMP格式图片,图片名为:friend.bmp,电脑中打卡如下图:

wKioL1hlJfLShiq0AAEr2yS3VCA704.jpg

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

由于图像是24位图,没有调色板信息,所以软件只要按照BMP格式偏移54个字节后,读取的便是第一个图像字节数据。VGA显示部分,要对framereader组件初始化,然后存放在数组中的图像数据便会不停地被读取到Clocked Video Output模块,最后数据会被送到VGA编码芯片显示。软件代码设计如下:

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
//filename: main.c
//author:   shugen.yin
//date:     2016.12.29
//function: BMP decode and VGA show
#include <stdio.h>
#include <system.h>
#include <string.h>
#include <io.h>
#include "unistd.h"
#include "sd_spi.h"
#include "ff.h"
#include "altera_avalon_pio_regs.h"
 
#define FRAME_ADDR  (framebuf0 + 0x00000000)
#define FRAME_WIDTH   640
#define FRAME_HEIGHT  480
#define FRAME_SIZE  (FRAME_WIDTH*FRAME_HEIGHT)
unsigned  int  framebuf0[FRAME_SIZE];
 
void  FrameRd_init(){
     IOWR(ALT_VIP_VFR_0_BASE, 3, 0);              // Frame Select
     IOWR(ALT_VIP_VFR_0_BASE, 4, framebuf0);      // Frame 0 Base Address
     IOWR(ALT_VIP_VFR_0_BASE, 5, FRAME_SIZE/8);   // Frame 0 Words => 640*480
     IOWR(ALT_VIP_VFR_0_BASE, 6, FRAME_SIZE);     // Frame 0 Single Cycle Color Patterns
     IOWR(ALT_VIP_VFR_0_BASE, 7, 0);              // Frame 0 Reserved Bit
     IOWR(ALT_VIP_VFR_0_BASE, 8, FRAME_WIDTH);    // Frame 0 Width
     IOWR(ALT_VIP_VFR_0_BASE, 9, FRAME_HEIGHT);   // Frame 0 Height
     IOWR(ALT_VIP_VFR_0_BASE, 10, 3);             // Frame 0 Interlaced => 3 = 0011 bedeutet progressive output
     IOWR(ALT_VIP_VFR_0_BASE, 0, 1);              // start Frame Reader
 
}
 
void  frame_init(){
     BYTE  pic_buf[FRAME_SIZE*3+54];
     UINT  i;
     UINT  j=0;
 
     f_mount(&fs, "" ,0);
     res=f_open(&fdst, "0:/friend.bmp" , FA_READ);
     if (res==FR_OK)
     {
        res = f_read(&fdst,pic_buf,FRAME_SIZE*3+54,&br);
        f_close(&fdst);
     }
 
     printf ( "file read success!\n" );
 
     for (i=54;i<FRAME_SIZE*3+54;i=i+3)
     {
         j++;
         framebuf0[FRAME_SIZE-j] = pic_buf[i]+(pic_buf[i+1])*256+(pic_buf[i+2])*65536;
 
     }
     printf ( "image processed done!\n" );
}
 
int  main ( void )
{
     frame_init();
     FrameRd_init();
 
     while (1);
 
     return  0;
}


5. 编译运行

编译成功后,以Hardware方式运行,终端打印:file read success! image processed done!

wKioL1hlNoCBCMuiAABMdUL0ZYs953.jpg


6. 最终结果

图片正常显示,和电脑上打开的friend.bmp一致。

wKiom1hlNrTgGwPwAAKDiCbi6gU909.jpg


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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Bmp To Mif 转换器 // (karimov 2005) // This program was originnaly written by one of the ECE241 students to convert an image // supplied in a BMP file into an MIF file format for use with Quartus II. // // This program has recently been modified to work with the new VGA controller used with the DE2 // board. // // What to do: // 1. Create an image in Microsoft paint (or other program). The image must be 160 pixels wide, 120 pixels high and // use 24-bits to represent colour information. // 2. Once you create the image you need, flip it up-side down. Then save the BMP file. (example: foo.bmp) // 3. Run this converter in command prompt using the name of the BMP file you created as a command-line parameter. // For example: // bmp2mif foo.bmp // 4. The program generates two files: // image.colour.mif - an MIF file with 3 bits colour information obtained from the BMP file you supplied // image.mono.mif - an MIF file containing 1 bit of colour for every pixel on the screen. The dot will either be // black or white. // You can change the file names once they are created, but they should still have the .mif extension. // // 5. Copy the proper MIF file to the directory where your design is located and include it in your project. // 6. Change the BACKGROUND_IMAGE parameter of the VgaAdapter to indicate your MIF file. // 7. The COLOR_CHANNEL_DEPTH parameter must be set to 1 to work with the image.colour.mif file. #include #include #define FLIP_INT(c) ((c >> 24) & 0x000000FF) | ((c & 0x00FF0000) >> 8) | ((c & 0x0000FF00) << 8) | ((c & 0x000000FF) <> 8) | ((c & 0x00FF) << 8) typedef struct s_header { unsigned short bfType; unsigned int bfSize; unsigned short reserved1; unsigned short reserved2; unsigned int offset; } t_bmp_header; typedef struct s_bmp_info { unsigned int biSize; unsigned int biWidth; unsigned int biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; unsigned int biXPelsPerMeter; unsigned int biYPelsPerMeter; unsigned int biClrUsed; unsigned int biClrImportant; } t_bmp_info; int faprint(FILE *fcol, FILE *fm, const char *pattern) { fprintf(fcol, pattern); return fprintf(fm, pattern); } int main(int argc, char* argv[]) { FILE *f, *fcol, *fm; int y; unsigned int x, c, r, g, b; unsigned int width, height; if (argc != 2) { printf("Usage: bmp2mif \n"); return 0; } else { printf("Input file is: %s\n", argv[1]); } printf("This program converts n x m 24-bit .BMP image to MIF file\n"); printf("There are 2 files produced:\n"); printf("\timage.colour.mif - 8-colour channel, n x m x 3\n"); printf("\timage.mono.mif - black and white image, n x m x 1\n\n"); f = fopen(argv[1], "rb"); fcol = fopen("image.colour.mif", "wb"); fm = fopen("image.mono.mif", "wb"); if (f) { t_bmp_header header; t_bmp_info info; fread(&header, 14, 1, f); /* sizeof(t_bmp_header) returns 16 instead of 14. Should be 14. */ fread(&info, sizeof(t_bmp_info), 1, f); #if !defined (WIN32) header.bfSize = FLIP_INT(header.bfSize); header.bfType = FLIP_SHORT(header.bfType); header.offset = FLIP_INT(header.offset); header.reserved1 = FLIP_SHORT(header.reserved1); header.reserved2 = FLIP_SHORT(header.reserved2); info.biSize = FLIP_INT(info.biSize); info.biWidth = FLIP_INT(info.biWidth); info.biHeight = FLIP_INT(info.biHeight); info.biPlanes = FLIP_SHORT(info.biPlanes); info.biBitCount = FLIP_SHORT(info.biBitCount); info.biCompression = FLIP_INT(info.biCompression); info.biSizeImage = FLIP_INT(info.biSizeImage); info.biXPelsPerMeter = FLIP_INT(info.biXPelsPerMeter); info.biYPelsPerMeter = FLIP_INT(info.biYPelsPerMeter); info.biClrUsed = FLIP_INT(info.biClrUsed); info.biClrImportant = FLIP_INT(info.biClrImportant); #endif printf("Input file is %ix%i %i-bit depth\n", info.biWidth, info.biHeight, info.biBitCount); if (info.biBitCount == 24) { char temp[100]; width = info.biWidth; height = info.biHeight; printf("Converting...\n"); sprintf(temp, "Depth = %i;\r\n",width*height); faprint(fcol, fm, temp); fprintf(fcol, "Width = 3;\r\n"); fprintf(fm, "Width = 1;\r\n"); faprint(fcol, fm, "Address_radix=dec;\r\n"); faprint(fcol, fm, "Data_radix=bin;\r\n"); faprint(fcol, fm, "Content\r\n"); faprint(fcol, fm, "BEGIN\r\n"); sprintf(temp, "\t[0..%i] : 000;\r\n", width*height - 1); fprintf(fcol, temp); sprintf(temp, "\t[0..%i] : 0;\r\n", width*height - 1); fprintf(fm, temp); fseek(f, 54, SEEK_SET); for(y=height-1; y >=0; y--) { x = 0; fprintf(fcol, "\t%i :", y*width+x); fprintf(fm, "\t%i :", y*width+x); for(x=0; x 0) && ((x % 40) == 0)) { fprintf(fcol, ";\r\n\t%i :", y*width + x); fprintf(fm, ";\r\n\t%i :", y*width + x); } #if defined (WIN32) c = ((c >> 24) & 0x000000FF) | ((c & 0x00FF0000) >> 8) | ((c & 0x0000FF00) << 8) | ((c & 0x000000FF) <>= 8; b = (c & 0xFF0000) >> 16; g = (c & 0x00FF00) >> 8; r = (c & 0x0000FF); c = r + g + b; c /= 3; r = (r >= 128 ? 1 : 0); g = (g >= 128 ? 1 : 0); b = (b >= 128 ? 1 : 0); c = (c >= 128 ? 1 : 0); fprintf(fcol, " %i%i%i", r, g, b); fprintf(fm, " %i", c); } faprint(fcol, fm, ";\r\n"); if ((x*3) % 4 != 0) { fread(&c, 4-((x*3) % 4), 1, f); } } faprint(fcol, fm, "End;\r\n"); } else printf("Input file image.bmp is not in a 24-bit colour format!\n"); fclose(fm); fclose(fcol); fclose(f); printf("All done.\n"); } else printf("Cannot open input file. Check for input.bmp\n"); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值