BMP图片与VGA(HDMI)时序互转

news2024/9/20 1:20:08

1.BMP介绍

BMP(Bitmap)是一种用于存储位图图像的文件格式,广泛应用于 Windows 操作系统中。BMP 文件可以存储高质量的图像数据,包括颜色深度较高的图片,同时支持无压缩或可选的简单压缩方式。

BMP格式

文件头(14 字节):

  • 文件类型:2 字节,通常为 BM
  • 文件大小:4 字节,整个 BMP 文件的大小。
  • 保留字段:4 字节,保留字段,值为 0。
  • 像素数据偏移量:4 字节,图像数据开始的位置。

信息头(40 字节,常见的 BITMAPINFOHEADER):

  • 头大小:4 字节,信息头的大小。
  • 图像宽度:4 字节,以像素为单位。
  • 图像高度:4 字节,以像素为单位(正数表示自下而上,负数表示自上而下)。
  • 颜色平面数:2 字节,通常为 1。
  • 每像素位数:2 字节,表示颜色深度,常见值为 24。
  • 压缩方式:4 字节,通常为 0 表示无压缩。
  • 图像大小:4 字节,图像数据的大小,压缩时有效。
  • 水平分辨率:4 字节,水平方向像素每米数。
  • 垂直分辨率:4 字节,垂直方向像素每米数。
  • 使用颜色数:4 字节,调色板中使用的颜色数。
  • 重要颜色数:4 字节,调色板中重要的颜色数。

图像数据:包含每个像素的颜色值,对于 24 位 BMP,每个像素由 3 个字节组成,分别表示红色绿色蓝色

示例
在这里插入图片描述

Tip:

  1. BMP的54个字节的文件头都是小端模式,即36_00_03_00实际的十六进制是(30036)h = (196,662)d = (256(宽)* 256 (高)*3+对齐字节+信息头)
  2. BMP图像的每行需要是4的倍数(即对齐),如果不够需要填充0,如上图256%4 = 0,所以196,662 = (256(宽)* 256 (高)*3(字节)+0+54)
  3. BMP中图像数据的存储是从左下开始的,即坐标(width:0,height:height)开始存贮的,而matlab中imread函数或者软件打开bmp查看数值时(如上图)是从左下读的,所以不用考虑存储的位置

2.BMP转VGA时序

首先,在verilog中是无法直接读取bmp图片的,需要将bmp通过脚本将其转为.dat文件,然后使用$readmemh函数去读取到数组中后,根据模拟的时钟信号将数据发出,下面是转bmp图片转dat文件的matlab代码:

注意:以下所有代码都是针对仿真的时候使用,且都需要替换文件名和路径!!!

clear;%从工作区中删除项目释放内存
clc;
close all;%关闭所有窗口
%main
% 1.读取图片数据
img = imread('1.bmp');
% imread函数两个参数:文件路径和读取格式
imtool(img,[]);
[h, w, ~] = size(img);      % 获取图像高度、宽度
fid = fopen('image_data.dat', 'w');
% 遍历图像数据,将其保存为十六进制形式
for i = h:-1:1              % 从底部开始
    for j = 1:w
        pixel_val = img(i,j,:);  % 获取每个像素的RGB值
        r = pixel_val(1);        % 红色通道
        g = pixel_val(2);        % 绿色通道
        b = pixel_val(3);        % 蓝色通道
        fprintf(fid, '%02X%02X%02X\n', r, g, b);  % 输出为 6 位十六进制,RGB 顺序
    end
end

当生成.dat文件之后,就可以直接将时序数据转换成VGA/HDMI 时序,如下所示:

module SIM_Generate_Data
#(
    parameter           P_CLK_PERIOD        = 5      ,    // 5ns
    parameter           P_RST_DURATION      = 50     ,    // 100ns
    parameter           P_H_MAX_CNT         = 800    ,    // 8bit
    parameter           P_H_SYNC            = 96     ,   
    parameter           P_H_FRONT           = 144    ,   //96  40 8
    parameter           P_V_MAX_CNT         = 525    ,   // 8bit
    parameter           P_V_SYNC            = 35     ,   //2  25  8
    parameter           P_V_FRONT           = 144    , 
    parameter           P_SCREEN_WIDTH      = 640    ,   //96  40 8 640 8 8  = 800
    parameter           P_SCREEN_HEIGHT     = 480    ,   //2  25  8 480 8 2  = 525
    parameter           P_IMAGE_WIDTH       = 256    ,
    parameter           P_IMAGE_HEIGHT      = 256    ,
    parameter           P_BACKFROUND_COLOR  = 24'h000000
)
(   
    output  wire            o_clk           ,
    output  wire            o_rst_n         ,
    output  wire    [7:0]   o_r_channel     ,
    output  wire    [7:0]   o_g_channel     ,
    output  wire    [7:0]   o_b_channel     ,
    output  reg             o_hsync         ,
    output  reg             o_vsync    
);
    
localparam      P_H_IMG_START = P_H_FRONT+P_SCREEN_WIDTH/2-P_IMAGE_WIDTH/2-1;
localparam      P_H_IMG_END   = P_H_FRONT+P_SCREEN_WIDTH/2+P_IMAGE_WIDTH/2-1;
localparam      P_V_IMG_START = P_V_FRONT+P_SCREEN_HEIGHT/2-P_IMAGE_HEIGHT/2-1;
localparam      P_V_IMG_END   = P_V_FRONT+P_SCREEN_HEIGHT/2+P_IMAGE_HEIGHT/2-1;
    
initial begin
    r_clk   = 1'b0;
    r_rst_n = 1'b0;
    #(P_RST_DURATION)r_rst_n = 1'b1;
end
    
initial begin
    $readmemh("../../../../../sim_data/image_data.dat", r_image_data);
    $display("Tip\:last image data read from file: %h",r_image_data[P_IMAGE_WIDTH*P_IMAGE_HEIGHT-1]);
end
    
always #(P_CLK_PERIOD/2) r_clk = ~r_clk;

reg                 r_clk           ;
reg                 r_rst_n         ;
reg     [23:0]      r_image_data  [P_IMAGE_WIDTH*P_IMAGE_HEIGHT-1:0];
reg     [15:0]      r_width_cnt     ;
reg     [15:0]      r_height_cnt    ;
reg     [7:0]       r_r_channel     ;
reg     [7:0]       r_g_channel     ;
reg     [7:0]       r_b_channel     ;
reg                 r_img_hsync     ;
reg                 r_img_vsync     ;
reg     [15:0]      r_h_cnt         ;
reg     [15:0]      r_v_cnt         ;
reg     [15:0]      r_total_cnt     ;
reg     [7:0]       or_r_channel    ;
reg     [7:0]       or_g_channel    ;
reg     [7:0]       or_b_channel    ;
reg     [7:0]       or_r_channel_1d ;
reg     [7:0]       or_g_channel_1d ;
reg     [7:0]       or_b_channel_1d ;

assign  o_clk       =   r_clk        ;
assign  o_rst_n     =   r_rst_n      ;
assign  o_r_channel =   or_r_channel_1d;
assign  o_g_channel =   or_g_channel_1d;
assign  o_b_channel =   or_b_channel_1d;

always @(posedge r_clk) begin
    if (!r_rst_n) begin
        o_hsync <= 1'b0;
        o_vsync <= 1'b0;
    end else begin
        o_hsync <= r_hsync;
        o_vsync <= r_vsync;
    end
end

//gererate r_hsync,r_vsync
always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)
        r_h_cnt <= 16'd0;
    else if(r_h_cnt == P_H_MAX_CNT-1) 
        r_h_cnt <= 16'd0;
    else
        r_h_cnt <= r_h_cnt + 16'd1;
end

always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)
        r_v_cnt <= 16'd0;
    else if(r_v_cnt == P_V_MAX_CNT-1 && r_h_cnt == P_H_MAX_CNT-1) 
        r_v_cnt <= 16'd0;
    else if(r_h_cnt == P_H_MAX_CNT-1)
        r_v_cnt <= r_v_cnt + 16'd1;
    else
        r_v_cnt <= r_v_cnt;
end

always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)
        r_img_hsync <= 1'b0;
    else if(r_h_cnt < P_H_SYNC)
        r_img_hsync <= 1'b1;
    else
        r_img_hsync <= 1'b0;
end
always @(posedge r_clk , negedge r_rst_n) begin
    if(!r_rst_n)begin
        r_vsync <= 1'b0;
    end else if(r_v_cnt >P_V_IMG_START && r_v_cnt <= P_V_IMG_END)begin
        r_vsync <= 1'b1;
    end else begin
        r_vsync <= 1'b0;
    end
end

always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)
        r_img_vsync <= 1'b0;
    else if(r_v_cnt < P_V_SYNC)
        r_img_vsync <= 1'b1;
    else
        r_img_vsync <= 1'b0;
end


always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)begin
        r_width_cnt <= 16'd0;
        r_height_cnt <= 16'd0;
        r_r_channel <= 8'd0;
        r_g_channel <= 8'd0;
        r_b_channel <= 8'd0;
    end else if(r_h_cnt > P_H_IMG_START && r_h_cnt <= P_H_IMG_END && r_v_cnt > P_V_IMG_START && r_v_cnt <= P_V_IMG_END)begin  //show image data
        r_r_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][23:16];
        r_g_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][15:8];
        r_b_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][7:0];
        r_width_cnt <= r_width_cnt + 16'd1;
        if(r_h_cnt == P_H_IMG_END )
            r_height_cnt = r_height_cnt + 16'd1;
        else
            r_height_cnt = r_height_cnt;
    end else if(r_h_cnt > P_H_FRONT-1 && r_h_cnt < (P_H_FRONT+P_SCREEN_WIDTH) && r_v_cnt > P_V_FRONT-1 && r_v_cnt < (P_V_FRONT+P_SCREEN_HEIGHT))begin  //show background color)begin
        r_r_channel <= P_BACKFROUND_COLOR[23:16];
        r_g_channel <= P_BACKFROUND_COLOR[15:8];
        r_b_channel <= P_BACKFROUND_COLOR[7:0];
    end
    else begin
        r_width_cnt <= 16'd0;
        r_r_channel <= 8'd0;
        r_g_channel <= 8'd0;
        r_b_channel <= 8'd0;
    end
end

//actully generated image data output
always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)begin
        or_r_channel <= 8'd0;
        or_g_channel <= 8'd0;
        or_b_channel <= 8'd0;
        r_hsync <= 1'b0;
    end else if(r_h_cnt > P_H_IMG_START && r_h_cnt <= P_H_IMG_END && r_v_cnt > P_V_IMG_START && r_v_cnt <= P_V_IMG_END)begin  //show image data
        r_hsync <= 1'b1;
        or_r_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][23:16];
        or_g_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][15:8];
        or_b_channel <= r_image_data[r_width_cnt+r_height_cnt*P_IMAGE_WIDTH][7:0];
    end else begin
        r_hsync <= 1'b0;
        or_r_channel <= 8'd0;
        or_g_channel <= 8'd0;
        or_b_channel <= 8'd0;
    end
end

always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)begin
        or_r_channel_1d <= 8'd0;
        or_g_channel_1d <= 8'd0;
        or_b_channel_1d <= 8'd0;
    end else begin
        or_r_channel_1d <= or_r_channel;
        or_g_channel_1d <= or_g_channel;
        or_b_channel_1d <= or_b_channel;
    end
end

always @(posedge r_clk,negedge r_rst_n) begin
    if(!r_rst_n)begin
        r_total_cnt <= 16'd0;
    end else if(!r_vsync)
        r_total_cnt <= 16'd0;
    else if(r_hsync && r_vsync)
        r_total_cnt <= r_total_cnt + 16'd1;
    else
        r_total_cnt <= r_total_cnt;
end
endmodule

3.将VGA时序转成BMP 图片

在转的时候,同时生成了.dat文件,如果生成的bmp不对,可以查看对应的.dat与原.dat文件的差异,也可以直接比较生成的BMP文件差异。

在这里插入图片描述

module SIM_output_image_TB
#(
    parameter                   P_DATA_WIDTH = 8    ,
    parameter                   P_IMG_WIDTH  = 256  ,
    parameter                   P_IMG_HEIGHT = 256
)
(
    input                       i_clk    ,
    input                       i_rst_n  ,
    input                       i_h_sync ,
    input                       i_v_sync ,
    input  [P_DATA_WIDTH-1:0]   i_data  
);

// 定义输入信号
reg                             ri_h_sync       ,
                                ri_v_sync       ;
reg         [P_DATA_WIDTH-1:0]  ri_data         ;
wire                            w_valid_signal  ;

assign w_valid_signal = ri_h_sync && ri_v_sync  ;

always @(posedge i_clk or negedge i_rst_n) begin
    if (!i_rst_n) begin
        ri_h_sync <= 'd0;
        ri_v_sync <= 'd0;
        ri_data   <= 'd0;
    end else begin
        ri_h_sync <= i_h_sync;
        ri_v_sync <= i_v_sync;
        ri_data   <= i_data  ;
    end
end

/*--------------大端模式转小端模式----------------*/
//bmp采取的是小端模式
function [31:0] big_convert_little_endian(
    input   [31:0] fi_data 
);
begin
    big_convert_little_endian[7:0]   = fi_data[31:24] ;
    big_convert_little_endian[15:8]  = fi_data[23:16] ;
    big_convert_little_endian[23:16] = fi_data[15:8]  ;
    big_convert_little_endian[31:24] = fi_data[7:0]   ;
end
endfunction
/*--------------宽度4字节对齐----------------*/
/*
在 BMP 文件中,图像数据的每一行必须是 4 字节对齐的,这意味着每行的数据大小必须是 4 的倍数。如果图像的每行像素数据没有达到 4 字节的倍数,就需要在每行的末尾添加一些填充字节,使其达到 4 字节的倍数
*/
function [31:0] f_image_width_align(
    input [31:0] fi_image_width
);
    if(fi_image_width>0)begin
        f_image_width_align = fi_image_width + (4-((fi_image_width * 3) % 4))%4;
    end else
        $display("image_width is less than or equal to zero!");
endfunction


/*--------------bmp文件写入----------------*/
task bmp_file_write(
    input   integer  ti_fp,
    input   [23:0]   ti_image_data
);
    begin
        $fwrite(ti_fp, "%c%c%c", ti_image_data[7:0],ti_image_data[15:8],ti_image_data[23:16]);
    end
endtask
/*--------------bmp文件关闭----------------*/
task bmp_file_close(
    input   integer  fp
);
    begin
        $fclose(fp);
        $display("BMP file already closed!");
    end
endtask

/*--------------bmp文件末尾补0----------------*/
task bmp_paddings_zero(
    input   integer  ti_fp      ,
    input   integer  ti_zero_num
);
    integer i;
begin
    if(ti_zero_num>0)begin
        for (i=0;i<ti_zero_num;i=i+1) begin
            $fwrite(ti_fp,"%c",0);  // 填充字节
        end
    end
end
endtask
/*--------------建立bmp文件----------------*/
task bmp_file_create(
    input   integer         ti_image_width       ,
    input   integer         ti_image_height      ,

    output  reg     [31:0]  to_real_row_width ,
    output  integer         o_fp  
);
    reg [7:0]   bmp_header [53:0]; // bmp文件头
    reg [31:0]  binary_file_size ; // 文件大小
    reg [31:0]  little_endian_width,little_endian_height; // 宽度转为小端模式
    integer     i;
    begin
        to_real_row_width = f_image_width_align(ti_image_width); // 真实行宽
        $display("image_width = %03d,real_image_width = %03d",ti_image_width,to_real_row_width);
        little_endian_width  =  big_convert_little_endian(to_real_row_width); // 宽度转为小端模式
        little_endian_height =  big_convert_little_endian(ti_image_height);   // 宽度转为小端模式
        binary_file_size = big_convert_little_endian(to_real_row_width*3*ti_image_height + 54);
        /*--------------bmp文件头(14bytes)---------------*/
        //标识符:2 字节 ("BM")
        bmp_header[0]   = 8'h42;
        bmp_header[1]   = 8'h4d;
        // 文件大小:4 字节
        bmp_header[2]   = binary_file_size[31:24]; //因为前面大端转小端的已经转了,所以这里直接赋值
        bmp_header[3]   = binary_file_size[23:16];
        bmp_header[4]   = binary_file_size[15:8] ;
        bmp_header[5]   = binary_file_size[7:0]  ;
        // 保留位:4 字节(通常为 0)
        bmp_header[6]   = 8'h00;
        bmp_header[7]   = 8'h00;
        bmp_header[8]   = 8'h00;
        bmp_header[9]   = 8'h00;
        // 像素数据的偏移量:4 字节
        bmp_header[10]  = 8'h36;
        bmp_header[11]  = 8'h00;
        bmp_header[12]  = 8'h00;
        bmp_header[13]  = 8'h00;
        /*--------------bmp信息头(40bytes)---------------*/
        //信息头大小:4 字节(通常为 40)
        bmp_header[14]  = 8'h28;
        bmp_header[15]  = 8'h00;
        bmp_header[16]  = 8'h00;
        bmp_header[17]  = 8'h00;
        // 图像宽度:4 字节
        bmp_header[18]  = little_endian_width[31:24];
        bmp_header[19]  = little_endian_width[23:16];
        bmp_header[20]  = little_endian_width[15:8] ;
        bmp_header[21]  = little_endian_width[7:0]  ;
        // 图像高度:4 字节
        bmp_header[22]  = little_endian_height[31:24];
        bmp_header[23]  = little_endian_height[23:16];
        bmp_header[24]  = little_endian_height[15:8] ;
        bmp_header[25]  = little_endian_height[7:0]  ;
        // 颜色平面数:2 字节(必须为 1)
        bmp_header[26]  = 8'h01;
        bmp_header[27]  = 8'h0;
        // 每像素位数:2 字节(例如 24 位表示 RGB)
        bmp_header[28]  = 8'h18;
        bmp_header[29]  = 8'h0;
        // 压缩方式:4 字节(0 表示不压缩)
        bmp_header[30]  = 8'h0;
        bmp_header[31]  = 8'h0;
        bmp_header[32]  = 8'h0;
        bmp_header[33]  = 8'h0;
        // 图像数据大小:4 字节
        bmp_header[34]  = 8'h0;
        bmp_header[35]  = 8'h0;
        bmp_header[36]  = 8'h0;
        bmp_header[37]  = 8'h0;
        // 水平方向分辨率:4 字节
        bmp_header[38]  = 8'h0;
        bmp_header[39]  = 8'h0;
        bmp_header[40]  = 8'h0;
        bmp_header[41]  = 8'h0;
        // 垂直方向分辨率:4 字节
        bmp_header[42]  = 8'h0;
        bmp_header[43]  = 8'h0;
        bmp_header[44]  = 8'h0;
        bmp_header[45]  = 8'h0;
        // 使用的颜色数:4 字节(0 表示使用所有颜色)
        bmp_header[46]  = 8'h0;
        bmp_header[47]  = 8'h0;
        bmp_header[48]  = 8'h0;
        bmp_header[49]  = 8'h0;
        // 重要的颜色数:4 字节(0 表示所有颜色都重要)
        bmp_header[50]  = 8'h0;  
        bmp_header[51]  = 8'h0;
        bmp_header[52]  = 8'h0;
        bmp_header[53]  = 8'h0;
        //打开文件
        o_fp = $fopen("../../../../../sim_data/result.bmp", "w");
        if(o_fp!= 0)begin
            $display("width:%d,height:%d",ti_image_width,ti_image_height);
            for (i = 0;i <= 53 ;i = i + 1) begin
                $fwrite(o_fp,"%c",bmp_header[i]);
            end
        end else
            $display("Error opening result.bmp file!\n");
    end
endtask

/*--------------建立输出dot文件指针,方便后续写入数据----------------*/
task output_create_dot_file(
    output      integer to_fp
);
begin
    to_fp = $fopen("../../../../../sim_data/output.dat", "w"); 
    if (to_fp == 0)
        $display("Error creating dot file!\n");
    else
        $display("Dot file created successfully!\n");
end
endtask

/*--------------根据.dat文件指针,持续写入数据----------------*/
task output_write_dot_file(
    input   integer     ti_fp,
    input   [23:0]      ti_data 
);
begin
    if(ti_fp!= 0) begin
        $fwrite(ti_fp,"%04X\n",ti_data);
        $display("Expected uppercase hex output: %04X", ti_data);
    end
    else
        $display("Error writing dot file!\n");
end
endtask

/*--------------根据.dat文件指针,关闭----------------*/
task output_close_dot_file(
    input   integer     ti_fp
);
begin
    if (ti_fp != 0) begin
        $display("Closing dot file: %d", ti_fp);
        $fclose(ti_fp);
    end else begin
        $display("Error closing dot file: Invalid file pointer");
    end
end
endtask

// 定义输出信号
integer bmp_file    ; // 文件指针
integer dot_file    ; // 文件指针
integer real_width  ;
integer w, h        ; // 当前像素坐标
integer i, j        ; // 循环变量
// 存储像素数据
reg [23:0] image_data [0:P_IMG_WIDTH*P_IMG_HEIGHT-1]; // 24位色,每个像素3字节

// 初始化仿真信号
initial begin
    i = 0;
    j = 0;
    bmp_file_create(P_IMG_WIDTH, P_IMG_HEIGHT, real_width, bmp_file); // 创建BMP文件,写入bmp文件头
    output_create_dot_file(dot_file); // 创建输出文件
end
// 仿真结束时写入图像数据
always @(posedge i_clk or negedge i_rst_n) begin
    if (!i_rst_n) begin
        w <= 0;
        h <= 0;  // 从左下角开始填充
    end else if (w_valid_signal) begin
        // 存储像素数据,8位输入拼接为24位RGB数据
        image_data[h * P_IMG_WIDTH + w] <= {ri_data, ri_data, ri_data};
        $display("h:%04d, w:%04d, data:%04X", h, w, {ri_data, ri_data, ri_data});
        output_write_dot_file(dot_file,{ri_data, ri_data, ri_data});
        // 坐标递增
        if (w == P_IMG_WIDTH - 1) begin
            w <= 0;
            if (h == P_IMG_HEIGHT - 1) begin
                h <= 0;
                output_close_dot_file(dot_file);  // 关闭输出的对比文件文件
                // 当图像数据全部写入时,输出 BMP 文件
                for (i = 0; i < P_IMG_HEIGHT; i = i + 1) begin
                    for (j = 0; j < P_IMG_WIDTH; j = j + 1) begin
                        bmp_file_write(bmp_file, image_data[i * P_IMG_WIDTH + j]);
                        // 行填充部分 0
                        bmp_paddings_zero(bmp_file, real_width - P_IMG_WIDTH);
                    end
                end
                bmp_file_close(bmp_file);
                
                #10; 
                $finish;  // 仿真结束
            end else
                h <= h + 1;  // 填充下一行
        end else 
            w <= w + 1;  // 填充下一列
    end
end
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2136319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

低代码-赋能新能源汽车产业加速前行

在“双碳”战略目标的引领下&#xff0c;全球新能源汽车产业正经历着前所未有的发展和变革&#xff0c;新能源汽车整车制造成为绿色低碳转型的重要领域。在政府的大力扶持下&#xff0c;新能源整车制造领域蓬勃发展&#xff0c;已成为全球汽车产业不可逆转的重要趋势。新能源汽…

上传文件到钉盘流程详解

文章目录 前言准备工作实现过程Maven依赖封装一个工具类获取文件上传信息unionId获取钉盘目录spaceId创建上传到钉盘前言 本文详解如何通过钉钉的API实现上传文件到钉盘目录,代码通过JAVA实现。 准备工作 1、在钉钉开发者后台创建一个钉钉企业内部应用; 2、创建并保存好应…

五星级可视化页面(23):污水处理、防汛可视化大屏

本期是第23期&#xff0c;分享一下水处理相关的大屏&#xff0c;欢迎老铁们勇于讨论&#xff0c;品鉴。

10款高效电脑监控软件推荐,电脑屏幕监控软件

在现代工作环境中&#xff0c;企业越来越依赖电脑监控软件来确保员工的工作效率、数据安全以及合规性。这些软件可以帮助管理者监督员工的日常活动&#xff0c;防止数据泄露&#xff0c;并确保工作时间得以合理使用。以下&#xff0c;我们将为您推荐10款高效的电脑监控软件&…

以太网传输出现不分包

最近对手件反馈,在传输文件的时候,我们这边发包太快,导致对手件网络出现了拥塞,把他们程序给搞死了。他们抓了一下他们收到的包,发现我们发送的数据包都大于了MTU设置的值。现在被要求更改。 排查方法:为什么我们发送的数据包会大于MTU的值。 可能性一:配置了Dont Fra…

Cryptography and Network Security: Principles and Practice(Lesson 2 notes)

Playfair Cipher Operation steps Construct a 55 letter matrix based onThe matrix is ​​constructed using a keyword (key)Then from left to right, from top to bottom; fill in the letters of the key in sequence (note: repeated letters in the key are not fil…

Open-Sora代码详细解读(2):时空3D VAE

Diffusion Models视频生成 前言&#xff1a;目前开源的DiT视频生成模型不是很多&#xff0c;Open-Sora是开发者生态最好的一个&#xff0c;涵盖了DiT、时空DiT、3D VAE、Rectified Flow、因果卷积等Diffusion视频生成的经典知识点。本篇博客从Open-Sora的代码出发&#xff0c;深…

齐活儿了:一文读懂ERP和MRP、MES、CRM、WMS、SRM、APS等系统

ERP&#xff0c;即企业资源计划系统&#xff0c;是驱动企业资源整合与高效管理的核心引擎。它覆盖了企业财务、人力资源、研发创新、生产制造、供应链管理、采购活动、销售市场、客户服务以及资产管理这九大核心业务领域&#xff0c;形成了一个全方位、多层次的企业价值链管理体…

a-table 定时平滑轮播组件

效果图&#xff1a; 实现代码如下&#xff1a; <template><div class"scroll-container" mouseenter"stopScroll" mouseleave"startScroll"><a-table:columns"columns":data-source"visibleData":paginatio…

【BFS专项】— 解决最短路问题

1、迷宫中离入口最近的出口 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 利用BFS层序遍历&#xff0c;新建一个变量统计步数代码&#xff1a; class Solution {int dx[] {0, 0, -1, 1};int dy[] {1, -1, 0, 0};public int nearestExit(char[][] maze, int[] en…

安泰高压放大器在基于EHD电喷的柔性压力传感器制备研究中的应用

实验名称&#xff1a;基于EHD电喷的柔性压力传感器制备技术研究 研究方向&#xff1a;EHD电喷技术是近年来出现的一种微纳尺度的新型3D打印技术&#xff0c;因其打印精度高、设备操作简单、材料来源广泛以及成本低等特点受到广泛关注&#xff0c;在柔性电子、生物医疗和可穿戴设…

C++ 继承【一篇让你学会继承】

1. 继承的概念及定义 1.1 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特征的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&…

基于JavaWeb开发的java springboot+mybatis电影售票网站管理系统前台+后台设计和实现

基于JavaWeb开发的java springbootmybatis电影售票网站管理系统前台后台设计和实现 &#x1f345; 作者主页 网顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获…

【Linux实践】实验二:LINUX操作基础

【Linux实践】实验二&#xff1a;LINUX操作基础 实验目的实验内容实验步骤及结果1. 打开终端2. 关闭计算机命令3. 查看帮助文档4. 修改计算机主机名5. 显示月历和时间6. 统计行数、字符数、单词数 这章开始要涉及到命令了&#xff0c;其他关于命令的内容可以看我 2021年写的笔记…

量水堰计的校准与维护:确保测量结果的准确性

量水堰计作为水利工程中用于测量和调节水流量的重要设备&#xff0c;其准确性和可靠性直接关系到水利设施的正常运行及数据收集的精度。因此&#xff0c;定期校准与维护量水堰计是确保测量结果准确性的关键步骤。本文将从量水堰计的校准方法和周期&#xff0c;以及日常维护保养…

wifi贴码推广能赚钱吗?wifi贴码怎么跟商家沟通?

大家好&#xff0c;我是鲸天科技千千&#xff0c;大家都知道我是做开发的&#xff0c;平时会给大家分享一些互联网相关的创业项目和网络技巧&#xff0c;感兴趣的可以给我点个关注。 最近WiFi这个项目很多朋友来问我&#xff0c;我是前两年就接触过这个&#xff0c;所以比较了…

望繁信科技携流程智能解决方案亮相CNDS 2024新能源产业数智峰会

9月13日&#xff0c;CNDS 2024中国新能源产业数智峰会在北京圆满落幕。本次峰会以“走向数字新能源”为主题&#xff0c;汇聚了来自新能源领域的顶尖领袖、专家学者及知名企业代表&#xff0c;共同探讨数字化技术在新能源行业中的创新应用和发展趋势。上海望繁信科技有限公司&a…

中秋出游热度十足!喆啡酒店如何巧妙捕捉多元旅游需求?

中秋假期临近&#xff0c;多家旅游OTA平台陆续发布旅游热度预测&#xff0c;皆认为中秋小长假有望延续暑期旅游热度。马蜂窝大数据显示&#xff0c;“中秋去哪”关键词近一周热度环比上涨110%&#xff0c;且“中秋3日游”关键词的热度更是大涨175%。消费趋势方面&#xff0c;受…

CAT1 DTU软硬件设计开源资料分析(TCP协议+GNSS定位版本 )

一、CAT1 DTU方案简介&#xff1a; 远程终端单元DTU&#xff0c;一种针对通信距离较长和工业现场环境恶劣而设计的具有模块化结构的、特殊的计算机测控单元&#xff0c;它将末端检测仪表和执行机构与远程控制中心相连接。 奇迹TCP DTUGNSS版本DTU&#xff0c;用于将远程现场的…

【面试干货】软件测试面试题汇总

我把软件测试面试的整个题库都搬来啦&#xff0c;面试能拿下80%&#xff0c;剩下就看你满不满意公司的开价咯。以下答案都是我自己写的&#xff0c;大家根据自己的经历稍作改动&#xff0c;答案仅供参考哦&#xff01;题库持续更新&#xff0c;需要PDF版可以点击文末小卡片领取…