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
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值