verilog 读写BMP文件

verilog 读写BMP文件

一个偶然的机会发现verilog可以直接读取bmp文件,出于好奇花了几个小时做了两个小实验。引起好奇的原因是,之前做了一个验证的小项目,利用Python或者MATLAB将图像转化为txt文本,随后利用verilog的fscan函数将txt文本导入,根据VESA标准时序输出像素数据。若能直接读取bmp文件,则将跳过Python的处理,直接对像素数据进行处理,方便很多呀。下面将结合自身的理解,简单谈一谈verilog读写bmp文件的过程。

BMP文件存储格式

在对bmp文件进行读写操作之前,个人觉得有必要简单了解一下bmp文件格式,否则你会一脸懵逼,不知道如何处理bmp文件中存储的像素数据。bmp文件的存储格式是Windows系统中广泛使用的图像文件格式,对图像不做任何程度的压缩处理,主要分为位图头文件,位图信息头,调色板信息,像素数据四大部分,由于通常是处理RBG图像,因此仅讨论RGB的情况

  1. 位图头文件 :文件的格式、大小等信息,前14Byte;主要关心的是图像尺寸,像素数据开始位置
  2. 位图信息头:提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息,前40Byte;主要关心的是图像宽度,图像高度
  3. 调色板信息:保留字,不关心
  4. 像素数据 :像素数据,8bit一个像素数据,即1Byte。
    详细介绍请参考文献:link

verilog 读bmp文件

1、设置参数

// 图像属性 : 图像宽度, 图像高度,图像尺寸, 像素开始点(与BMP存储格式有关)
integer bmp_width;
integer bmp_high;
integer bmp_size;
integer start_index;

// BMP file id
integer bmp_file_id;
integer bmp_dout_id;
integer dout_txt_id;
    
// 文件句柄
integer h;

// 存储bmp文件数据
reg [7:0]rd_data[0:2 ** 24];
reg [7:0]rd_data2[0:2 ** 24];

2、打开bmp文件

// 打开原始图像(输入图像)
bmp_file_id = $fopen("1.bmp", "rb");
// 打开输出图像
bmp_dout_id = $fopen("dout3.bmp", "wb");
// 打开输出数据
dout_txt_id = $fopen("dout3.txt", "w+");

3、读bmp文件

// 读取BMP文件
h = $fread(rd_data, bmp_file_id);
  
// 图像宽度,21~18Byte
bmp_width = {rd_data[21], rd_data[20], rd_data[19], rd_data[18]};
// 图像宽度,25~22Byte
bmp_high = {rd_data[25], rd_data[24], rd_data[23], rd_data[22]};
// 像素开始位置,13~10Byte 
start_index = {rd_data[13], rd_data[12], rd_data[11], rd_data[10]};
// 图像尺寸 ,5~2Byte
bmp_size = {rd_data[5], rd_data[4], rd_data[3], rd_data[2]};

4、关闭bmp文件

 $fclose(bmp_file_id);

verilog 写bmp文件

1、图像正常写,值得注意的是:写入BMP文件的数据格式必须是%u,否则出错

reg [31:0]wr_data;
    integer i; 
    initial begin
        for(i = 0; i < 555*695*3 + 54; i = i + 4)begin
            wr_data = {rd_data[i + 3], rd_data[i + 2], rd_data[i + 1], rd_data[i]};
            $fwrite(bmp_dout_id, "%u", wr_data); // **注意写入BMP文件的数据格式必须是%u,否则出错**
            $fwrite(dout_txt_id, "%h\n", wr_data[7:0]);
            $fwrite(dout_txt_id, "%h\n", wr_data[15:8]);
            $fwrite(dout_txt_id, "%h\n", wr_data[23:16]);
            $fwrite(dout_txt_id, "%h\n", wr_data[31:24]);
        end
        $fclose(bmp_dout_id);
        $fclose(dout_txt_id);
    end

2、图像关于右下角对称

integer i = 0;
integer j = 0;
integer index;
integer p1 = 54;// 像素的起始位置
reg [7:0]wr_data2;
initial begin
	for(i = bmp_size - 1; i > start_index - 1; i = i - 1)begin
		wr_data2 = rd_data[i];// 最后一个像素
		//rd_data[p1] = wr_data2;// 使用这条语句出错,原因不明
		p1 = p1 + 1;// 像素位置从头开始累加
	end
	for(j = 0; j < start_index; j = j + 1)begin
            rd_data2[j] = rd_data[j];
        end
        for(index = 0; index < bmp_size; index = index + 4)begin
            wr_data = {rd_data2[index + 3], rd_data2[index + 2], rd_data2[index + 1], rd_data2[index]};
            $fwrite(bmp_dout_id, "%u", wr_data);
            $fwrite(dout_txt_id, "%h\n", wr_data[7:0]);
            $fwrite(dout_txt_id, "%h\n", wr_data[15:8]);
            $fwrite(dout_txt_id, "%h\n", wr_data[23:16]);
            $fwrite(dout_txt_id, "%h\n", wr_data[31:24]);
        end
        $fclose(bmp_dout_id);
end	

整体代码

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
参考文献:
[1]: www.360doc.com/content/12/0913/17/10724725_235932895.shtml
[2]: https://blog.csdn.net/k331922164/article/details/108655028

  • 9
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA读写SD卡读取BMP图片通过LCD显示例程实验 Verilog逻辑源码Quartus工程文件+文档说明,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 1 实验简介 在前面的实验中我们练习了 SD 卡读写,VGA 视频显示等例程,本实验将 SD 卡里的 BMP 图 片读出,入到外部存储器,再通过 VGA、LCD 等显示。 本实验如果通过液晶屏显示,需要有液晶屏模块。 2 实验原理 在前面的实验中我们在 VGA、LCD 上显示的是彩条,是 FPGA 内部产生的数据,本实验将彩 条替换为 SD 内的 BMP 图片数据,但是 SD 卡读取速度远远不能满足显示速度的要求,只能先 入外部高速 RAM,再读出后给视频时序模块显示 module top( input clk, input rst_n, input key1, output [5:0] seg_sel, output [7:0] seg_data, output vga_out_hs, //vga horizontal synchronization output vga_out_vs, //vga vertical synchronization output[4:0] vga_out_r, //vga red output[5:0] vga_out_g, //vga green output[4:0] vga_out_b, //vga blue output sd_ncs, //SD card chip select (SPI mode) output sd_dclk, //SD card clock output sd_mosi, //SD card controller data output input sd_miso, //SD card controller data input output sdram_clk, //sdram clock output sdram_cke, //sdram clock enable output sdram_cs_n, //sdram chip select output sdram_we_n, //sdram write enable output sdram_cas_n, //sdram column address strobe output sdram_ras_n, //sdram row address strobe output[1:0] sdram_dqm, //sdram data enable output[1:0] sdram_ba, //sdram bank address output[12:0] sdram_addr, //sdram address inout[15:0] sdram_dq //sdram data ); parameter MEM_DATA_BITS = 16 ; //external memory user interface data width parameter ADDR_BITS = 24
FPGA读写SD卡测试实验 Verilog逻辑源码Quartus工程文件+文档说明,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 // 2017/6/19 meisq 1.0 Original //*******************************************************************************/ module sd_card_test( input clk, input rst_n, input key1, output SD_nCS, output SD_DCLK, output SD_MOSI, input SD_MISO, output [5:0] seg_sel, output [7:0] seg_data ); parameter S_IDLE = 0; parameter S_READ = 1; parameter S_WRITE = 2; parameter S_END = 3; reg[3:0] state; wire sd_init_done; reg sd_sec_read; wire[31:0] sd_sec_read_addr; wire[7:0] sd_sec_read_data; wire sd_sec_read_data_valid; wire sd_sec_read_end; reg sd_sec_write; wire[31:0] sd_sec_write_addr; reg [7:0] sd_sec_write_data; wire sd_sec_write_data_req; wire sd_sec_write_end; reg[9:0] wr_cnt; reg[9:0] rd_cnt; wire button_negedge; reg[7:0] read_data; ax_debounce ax_debounce_m0 ( .clk (clk), .rst (~rst_n), .button_in (key1), .button_posedge (), .button_negedge (button_negedge), .button_out () ); wire[6:0] seg_data_0; seg_decoder seg_decoder_m0( .bin_data (read_data[3:0]), .seg_data (seg_data_0) ); wire[6:0] seg_data_1; seg_decoder seg_decoder_m1( .bin_data (read_data[7:4]), .seg_data (seg_data_1) ); seg_scan seg_scan_m0( .clk (clk), .rst_n (rst_n), .seg_sel (seg_sel), .seg_data (seg_data), .seg_data_0 ({1'b1,7'b1111_111}), .seg_data_1 ({1'b1,7'b1111_111}), .seg_data_2 ({1'b1,7'b1111_111}), .seg_data_3 ({1'b1,7'b1111_111}), .seg_data_4 ({1'b1,seg_data_1}), .seg_data_5 ({sd_init_done,seg_data_0}) ); always@(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) wr_cnt <= 10'd0; else if(state == S_WR

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值