verilog 读写BMP文件
一个偶然的机会发现verilog可以直接读取bmp文件,出于好奇花了几个小时做了两个小实验。引起好奇的原因是,之前做了一个验证的小项目,利用Python或者MATLAB将图像转化为txt文本,随后利用verilog的fscan函数将txt文本导入,根据VESA标准时序输出像素数据。若能直接读取bmp文件,则将跳过Python的处理,直接对像素数据进行处理,方便很多呀。下面将结合自身的理解,简单谈一谈verilog读写bmp文件的过程。
BMP文件存储格式
在对bmp文件进行读写操作之前,个人觉得有必要简单了解一下bmp文件格式,否则你会一脸懵逼,不知道如何处理bmp文件中存储的像素数据。bmp文件的存储格式是Windows系统中广泛使用的图像文件格式,对图像不做任何程度的压缩处理,主要分为位图头文件,位图信息头,调色板信息,像素数据四大部分,由于通常是处理RBG图像,因此仅讨论RGB的情况
- 位图头文件 :文件的格式、大小等信息,前14Byte;主要关心的是图像尺寸,像素数据开始位置。
- 位图信息头:提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息,前40Byte;主要关心的是图像宽度,图像高度。
- 调色板信息:保留字,不关心
- 像素数据 :像素数据,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