粤嵌实习-学习bmp文件格式并解析一张bmp图片、交叉开发在开发板上显示一张图片

粤嵌实习(电梯运行演示系统)

了解并使用bmp图片和交叉开发

bmp文件格式

bitmap文件头(14字节):

偏移量大小用途
0000H2字节用于标识BMP和DIB文件的魔数,一般为0x42 0x4D
0002H4字节BMP文件的大小(单位为字节)
0006H2字节保留,实际值因创建程序而异
0008H2字节保留,实际值因创建程序而异
000AH4字节位图数据(像素数组)的地址偏移,也就是起始地址。

DIB头(40字节):

偏移量大小用途
OEH4字节该头结构的大小(40字节)
12H4字节位图宽度,单位为像素(有符号整数)
16H4字节位图宽度,单位为像素(有符号整数)
1AH2字节色彩平面数,只有1为有效值
1CH2字节每个像素所占位数,即图像的色深,典型值为1、4、8、16、24和32
1EH4字节所使用的的压缩方法
22H4字节图像大小。原指位图数据的大小,与文件大小不是同一概念
26H4字节图像的横向分辨率,单位为像素每米(有符号整数)
2AH4字节图像的纵向分辨率,单位为像素每米(有符号整数)
2EH4字节调色板的颜色数,为0时表示颜色数为默认的2的色深数次方个
32H4字节重要颜色数,为0时表示所有颜色都是重要的,通常不使用本项

调色板(颜色值数组)

像素数组:这部分逐个像素表示图像,每一个像素使用一个或多个字节表示。通常像素是从上到下,从左到右保存的。

应用:读取一张图片的数据

先在共享文件夹下存放一张图片。

编写代码读取图片信息并打印。

int fd = open("./kkk.bmp",O_RDONLY);//共享文件夹下的图片
 if(fd == -1)
 {
  perror("open bmp error:");
  return -1;
 }
	unsigned char buf[64] = {0};
	read(fd,buf,64);

 //操作
 //判断是否为BMP图片
 if(buf[0] != 0x42 || buf[1] != 0x4d)
 {
  printf("NO\n");
  close(fd);
  return -1;
 }
 printf("Yes\n");
}

    //bmp图片信息的读取
	int fd = open(bmpname,O_RDWR);
	int size,width,high;
    short depth;     //两个字节
	lseek(fd,2,SEEK_SET);
	read(fd,&size,4);//读取图片的大小
	lseek(fd,0x12,SEEK_SET);
	read(fd,&width,4);//读取图片的宽度
	lseek(fd,0x16,SEEK_SET);
	read(fd,&high,4);//读取图片的高度
	lseek(fd,0x1C,SEEK_SET);
	read(fd,&depth,2);//读取图片的色深
	printf("bmp size=%d width=%d high = %d depth=%d\n",size,width,high,depth);

结果如下:

在这里插入图片描述

交叉开发:

1.连接与配置

(1)连接好开发板,启动开发板。

(2)打开设备管理器,查找识别出的端口号。

在这里插入图片描述

​ 若不能正确识别端口号,则需要安装驱动。

在这里插入图片描述

(3)使用SecureCRT软件来对开发板进行终端控制。

在这里插入图片描述

(4)打开SecureCRT.exe文件,连接开发板。

在这里插入图片描述

连接成功:

在这里插入图片描述

(5)创建工作文件夹。

①先删除home目录下的所有文件。

cd /home 
rm -rf *

②创建并进入自己的工作文件夹,下次使用开发板先进入此文件夹。

mkdir /home/117
cd /home/117

如下:

在这里插入图片描述

2.在开发板上运行一个程序

(1)编辑一个C文件,并保存到共享文件夹中。

(2)将其在虚拟机中编译成开发板上可执行文件。

如:

arm-linux-gcc hello.c -o hello

在这里插入图片描述

(3)传送可执行文件到开发板上,并执行。

rx 可执行文件名

chmod 0777 可执行文件名

./可执行文件名

在这里插入图片描述

应用:读取图片的数据并显示到开发板上

开发板屏幕为800*480。

定义BMP数据结构:

//定义一个bmp图片信息相关的结构体类型
typedef struct BMP
{
    char* bmpname;          //保存bmp图片的名称
    int size;               //文件的总大小
    int width;              //文件的宽
    int height;             //文件的高
    short bpp;              //色深
    char* data;             //像素数组的首地址
}BMP;

定义相关要用到的函数:

//屏幕初始化
void lcd_init();
//解除屏幕初始化
void lcd_uninit();
//画点
void lcd_point(int x,int y,int color);
//获取bmp图片信息
BMP get_bmp_info(char* bmpname);
//画一张bmp图片
void lcd_draw_bmp(char* bmpname, int x, int y);

全部写在bmp.h文件中,具体文件内容如下:

#ifndef __BMP_H
#define __BMP_H

#include <stdio.h>
#include <stdlib.h>
//open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//mmap
#include <sys/mman.h>
//close,read,write
#include <unistd.h>

//定义一个bmp图片信息相关的结构体类型
typedef struct BMP
{
    char* bmpname;          //保存bmp图片的名称
    int size;               //文件的总大小
    int width;              //文件的宽
    int height;             //文件的高
    short bpp;              //色深
    char* data;             //像素数组的首地址
}BMP;

//屏幕初始化
void lcd_init();
//解除屏幕初始化
void lcd_uninit();
//画点
void lcd_point(int x,int y,int color);
//获取bmp图片信息
BMP get_bmp_info(char* bmpname);
//画一张bmp图片
void lcd_draw_bmp(char* bmpname, int x, int y);

#endif

①读取所有像素点的信息。

BMP get_bmp_info(char* bmpname)
{
	//可以下载其他格式的图片,在电脑自带的图片编辑中,将图片的像素进行调整,另存为bmp(24位)图片即可
	//size --> 0x02 - 4字节   宽 --> 0x12 -- 4字节  高 ->> 0x16 -- 4字节      色深 ->> 0x1c -- 2字节
	int fd_bmp = open(bmpname, O_RDONLY);//写入bmp文件名
	if (fd_bmp == -1)
	{
		printf("open bmp error\n");
		exit(1);
	}
    //判断是否是bmp文件
	char bm[2] = {0};
	read(fd_bmp, bm, 2);
	if (!(bm[0] == 'B' && bm[1] == 'M'))
	{
	printf("%s is not a bmp file\n", bmpname);
	exit(1);
	}
	
BMP bmp;
bmp.bmpname = bmpname;

//大小
lseek(fd_bmp, 0x02, SEEK_SET);
read(fd_bmp, &bmp.size, 4);

//宽
lseek(fd_bmp, 0x12, SEEK_SET);
read(fd_bmp, &bmp.width, 4);
//高
read(fd_bmp, &bmp.height, 4);
//色深
lseek(fd_bmp, 0x1c, SEEK_SET);
read(fd_bmp, &bmp.bpp, 2);

//开辟一块空间用来保存像素数组
bmp.data = (char*)malloc(bmp.size - 54);
lseek(fd_bmp, 0x36, SEEK_SET);
read(fd_bmp, bmp.data, (bmp.size-54));

close(fd_bmp);
return bmp;
}

②将图片显示到开发板上。

void lcd_draw_bmp(char* bmpname, int x, int y)
{
	BMP bmp = get_bmp_info(bmpname);
	//打印图片的基本信息
	printf("bmpname = %s, size = %d, width = %d, height = %d, bpp = %hd\n", 
			bmp.bmpname, bmp.size, bmp.width, bmp.height, bmp.bpp);

	//一行的有效字节数
	int line_types = abs(bmp.width) * bmp.bpp / 8;

	//一行的填充字节数
	int pad_types = (line_types % 4 == 0) ? 0 : (4 - (line_types % 4));

	int color;
	char* p = bmp.data; //遍历指针,遍历整个像素数组

	//解析像素数组中的数据并画到开发板上
	for (int h = 0; h < abs(bmp.height); h++) //表示行
	{
		for (int w = 0; w < abs(bmp.width); w++) //表示列
		{
			char b = *(p++);
			char g = *(p++);
			char r = *(p++);
			char a = (bmp.bpp == 24) ? 0 : *(p++);

			color = a << 24 | r << 16 | g << 8 | b;

			// width > 0 : 从左到右保存每一个像素点
            // width < 0 : 从右到左保存每一个像素点
			// height > 0: 从下到上保存每一个像素点
            // height < 0: 从上到下保存每一个像素点

			int m =x+(bmp.width>0?w:(bmp.width-1-w));
			int n =y+(bmp.height<0?h:(bmp.height-1-h));

			lcd_point(m, n, color);
		}
		p += pad_types;//跳过填充字节
	}

③编译运行程序

1.先在linux下编译程序。

​ 此处采用了gcc编译同时编译多个c文件,需将各个.c文件和.h文件放在同一个文件夹下。

在这里插入图片描述

2.向工作文件夹中传入所需的图片(此处已经传入在开发板中文件名为bg1的图片bg1.bmp)

在这里插入图片描述

在这里插入图片描述

3.传入并执行文件。

在这里插入图片描述

4.结果如下:

在这里插入图片描述

  • 10
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现多张图片的轮流播放,可以使用Linux下的GTK+图形库进行开发。具体实现步骤如下: 1. 在Linux开发板上安装GTK+图形库。 2. 编写程序,打开一个窗口,将图片显示在窗口中。 3. 使用GTK+提供的延时函数,控制图片显示时间。 4. 利用GTK+提供的回调函数机制,实现多张图片的轮流播放。 以下是一个简单的示例代码: ```c #include <gtk/gtk.h> #define IMAGE_NUM 3 // 图片数量 #define IMAGE_WIDTH 320 // 图片宽度 #define IMAGE_HEIGHT 240 // 图片高度 #define INTERVAL_TIME 2000 // 图片切换时间间隔,单位为毫秒 GtkWidget *window; // 窗口 GtkWidget *image; // 图片控件 int idx = 0; // 当前显示图片序号 // 图片路径 const char* image_paths[IMAGE_NUM] = { "/path/to/image1.jpg", "/path/to/image2.jpg", "/path/to/image3.jpg" }; // 切换图片 gboolean switch_image(gpointer data) { idx = (idx + 1) % IMAGE_NUM; gtk_image_set_from_file(GTK_IMAGE(image), image_paths[idx]); return TRUE; } int main(int argc, char *argv[]) { gtk_init(&argc, &argv); // 创建窗口 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Image Viewer"); gtk_window_set_default_size(GTK_WINDOW(window), IMAGE_WIDTH, IMAGE_HEIGHT); // 创建图片控件 image = gtk_image_new_from_file(image_paths[0]); // 添加图片控件到窗口中 gtk_container_add(GTK_CONTAINER(window), image); // 显示窗口 gtk_widget_show_all(window); // 设置定时器,定时切换图片 g_timeout_add(INTERVAL_TIME, switch_image, NULL); // 进入GTK+主循环 gtk_main(); return 0; } ``` 这个程序会在窗口中显示多张图片,并且每隔一定时间就会自动切换到下一张图片。你可以根据自己的需求修改图片数量、图片大小和切换时间间隔等参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

风-世

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值