Verilog实现生成BMP文件(BMP文件格式,二进制文件读写)

Git地址:
https://gitee.com/whik/bmp_gen_c_and_verilog/tree/master/verilog

BMP文件格式详解参考:

Verilog实现生成BMP,注意宽度必须进行4字节对齐,使用0来补充,否则部分宽度图片生成乱码。可使用PhotoShop生成宽度10,长度5的图片验证,数据存储为BMP文件最后一行为图片第一行的像素数据。先选择图像->模式->8位/通道,再保存为BMP,Windows,24Bit。

Verilog实现生成BMP

module main;

/* rgb_565 to rgb_888 */
function [23:0] rgb_888 (
    input [15:0] rgb_565
);
begin
    rgb_888[23:16] = rgb_565[15:11] / 31.0 * 255.0;//r
    rgb_888[15:8]  = rgb_565[10:5]  / 63.0 * 255.0; //g
    rgb_888[7:0]   = rgb_565[4:0]   / 31.0 * 255.0;  //b
end
endfunction

/* small to big: 0x12345678 -> 0x78563412 */
function [31:0] to_small_endian(
    input [31:0] big_endian
);
begin
    to_small_endian[31:24] = big_endian[7:0];
    to_small_endian[23:16] = big_endian[15:8];
    to_small_endian[15:8]  = big_endian[23:16];
    to_small_endian[7:0]   = big_endian[31:24];
end
endfunction

/* num to char: 5->"5" */
function [7:0] num_to_ascii(
    input [3:0] num
);
    num_to_ascii[7:0] = num + "0";
endfunction

/* num to filename string: 7890->"7890.bmp" */
function [8*8-1:0] num_to_filename(
    input [13:0] num
);
begin
    num_to_filename[8*8-1 : 8*8-8] = num_to_ascii(num / 1000);   //1
    num_to_filename[7*8-1 : 7*8-8] = num_to_ascii(num / 100 % 10); //2
    num_to_filename[6*8-1 : 6*8-8] = num_to_ascii(num / 10 % 10);  //3
    num_to_filename[5*8-1 : 5*8-8] = num_to_ascii(num % 10);     //4
    num_to_filename[4*8-1 : 0    ] = ".bmp";
end
endfunction

function [31:0] width_4byte_align(
    input [31:0] width
);
    width_4byte_align = ((width * 24) / 8 + 3) / 4 * 4;
endfunction

//close bmp file
task bmp_file_close(
    input integer fd
);
begin
    $fclose(fd);
    $display("file is close!");
end
endtask

//bmp write rgb data 565 format
task bmp_file_write(
    input integer fd,
    input [15:0] rgb_data_565
);
    reg [23:0] rgb_data_888;
    begin
        rgb_data_888 = rgb_888(rgb_data_565);
        // B G R
        $fwrite(fd, "%c%c%c", rgb_data_888[7:0], rgb_data_888[15:8], rgb_data_888[23:16]);
    end
endtask

//write num zero
task bmp_file_write_zero(
    input integer fd,
    input integer zero_num
);
integer idx;
begin
    if(zero_num > 0)
    begin
        for(idx = 0; idx < zero_num; idx = idx + 1)
            $fwrite(fd, "%c", 0);
    end
end
endtask

task bmp_file_new(
     input [13:0] filenum
    ,input [31:0] width
    ,input [31:0] height
    
    ,output reg [31:0] width_real
    ,output integer fd
);
    /* file header(14 Byte) and map info(40 Byte) */
    reg [7:0] bmp_head_map [53:0]; 
    reg [31:0] bfSize;  /* = w*h*3*/
    reg [31:0] width_small;
    reg [31:0] height_small;
    reg [8*8-1:0] filename;
    reg [23:0] rgb_data_888;
    integer idx;
    
    begin
        //width 4 byte align
        width_real = width_4byte_align(width);
        $display("width: %03d, width_real: %03d", width, width_real);
        //width and height to small endian
        width_small  = to_small_endian(width);
        height_small = to_small_endian(height);
        
        bfSize       = to_small_endian(width_real * height + 54 + 2);
        filename     = num_to_filename(filenum);
        
        bmp_head_map[0 ] = 'h42;
        bmp_head_map[1 ] = 'h4d;
        //bfSize
        bmp_head_map[2 ] = bfSize[31:24];
        bmp_head_map[3 ] = bfSize[23:16];
        bmp_head_map[4 ] = bfSize[15:8] ;
        bmp_head_map[5 ] = bfSize[7:0]  ;
        
        bmp_head_map[6 ] = 'h0;
        bmp_head_map[7 ] = 'h0;
        bmp_head_map[8 ] = 'h0;
        bmp_head_map[9 ] = 'h0;
        
        bmp_head_map[10] = 'h36;
        bmp_head_map[11] = 'h0;
        bmp_head_map[12] = 'h0;
        bmp_head_map[13] = 'h0;
        
        bmp_head_map[14] = 'h28;
        bmp_head_map[15] = 'h0;
        bmp_head_map[16] = 'h0;
        bmp_head_map[17] = 'h0;
        //width
        bmp_head_map[18] = width_small[31:24];
        bmp_head_map[19] = width_small[23:16];
        bmp_head_map[20] = width_small[15:8] ;
        bmp_head_map[21] = width_small[7:0]  ;
        //height
        bmp_head_map[22] = height_small[31:24];
        bmp_head_map[23] = height_small[23:16];
        bmp_head_map[24] = height_small[15:8] ;
        bmp_head_map[25] = height_small[7:0]  ;
        
        bmp_head_map[26] = 'h01;
        bmp_head_map[27] = 'h0;
        //24Bit RGB_888
        bmp_head_map[28] = 'h18;
        bmp_head_map[29] = 'h0;
        
        bmp_head_map[30] = 'h0;
        bmp_head_map[31] = 'h0;
        bmp_head_map[32] = 'h0;
        bmp_head_map[33] = 'h0;
        bmp_head_map[34] = 'h0;
        bmp_head_map[35] = 'h0;
        bmp_head_map[36] = 'h0;
        bmp_head_map[37] = 'h0;
        bmp_head_map[38] = 'h0;
        bmp_head_map[39] = 'h0;
        bmp_head_map[40] = 'h0;
        bmp_head_map[41] = 'h0;
        bmp_head_map[42] = 'h0;
        bmp_head_map[43] = 'h0;
        bmp_head_map[44] = 'h0;
        bmp_head_map[45] = 'h0;
        bmp_head_map[46] = 'h0;
        bmp_head_map[47] = 'h0;
        bmp_head_map[48] = 'h0;
        bmp_head_map[49] = 'h0;
        bmp_head_map[50] = 'h0;
        bmp_head_map[51] = 'h0;
        bmp_head_map[52] = 'h0;
        bmp_head_map[53] = 'h0;
        
        fd = $fopen(filename,"wb+"); 
        if(fd != 0)
        begin
            $display("filename: %08s, width: %04d, height: %04d", filename, width, height);
            
            for(idx = 0; idx <= 53; idx = idx + 1)
                $fwrite(fd, "%c", bmp_head_map[idx]);
        end
        else 
            $display("file create failed: %d", fd);
    end
endtask

integer fd = 0, i = 0, j = 0;
reg [31:0] width_real = 0;
reg [31:0] w = 0, h = 0;

initial 
begin
    w = 301;
    h = 401;

    bmp_file_new(w, w, h, width_real, fd);
    
    for(i = 0; i < h; i = i + 1) 
    begin
        for(j = 0; j < w; j = j + 1)
            bmp_file_write(fd, 16'b01000_000111_01111); /* BGR */
        
        bmp_file_write_zero(fd, width_real - w * 3);
    end
    bmp_file_write_zero(fd, 2);
    bmp_file_close(fd);
    // $finish;
end

endmodule

生成的图片:
在这里插入图片描述
Git地址:
https://gitee.com/whik/bmp_gen_c_and_verilog/tree/master/verilog

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

whik1194

如果对你有帮助,欢迎打赏。谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值