定制企业网站有哪些,深圳网页设计与制作本科工资多少钱,中国建设银行海南省分行网站,丽江网页制作公司03-基于GEC6818开发板实现加载一张图片 实现基于GEC6818开发板实现加载一张BMP文件。其中详细解析了一张BMP格式图的内容。 其他相关GEC6818开发板的内容可以参考 01-基于粤嵌GEC6818实现屏幕的显示固定颜色进行自动切换 02-基于GEC6818开发板的画正方形、画圆的操作——使用mm…03-基于GEC6818开发板实现加载一张图片 实现基于GEC6818开发板实现加载一张BMP文件。其中详细解析了一张BMP格式图的内容。 其他相关GEC6818开发板的内容可以参考 01-基于粤嵌GEC6818实现屏幕的显示固定颜色进行自动切换 02-基于GEC6818开发板的画正方形、画圆的操作——使用mmap映射提高效率 文章目录 03-基于GEC6818开发板实现加载一张图片一、 bmp图片的格式内容1.1 BITMAP文件头1.2 DIB头1.3 调色板颜色数值组1.4 像素数组 二、 实例练习2.1加载一张图片实现代码2.2 进阶对于图片大小不是800*480的图片进行轮播 一、 bmp图片的格式内容
我们要加载一张图片就必须知道这张图片的一些特定格式并获取其中的像素数组。
那么BMP文件主要由四部分组成BITMAP文件头DIB头调色板颜色数值组像素数组。
1.1 BITMAP文件头 文件头时表征这个文件是什么格式例如我们下面代码中会提及的判断这个图片是不是真的BMP文件则可以 //判断是否为真的BMP文件unsigned char buf[2];read(fd,buf,2);if(buf[0]! 0x42 || buf[1]! 0x4d)//若果不是B M 的ASCII码{printf(NOT BMP\n);return;}1.2 DIB头 这一部分也非常重要因为其中包含了很多图片的基础信息比如图片的宽度高度色深以及图片的大小等这些都有助于我们后续对这个文件进行进一步的操作。 //读取数据int width,height,depth;//读取宽度将偏移量偏移到宽度lseek(fd,0x12,SEEK_SET);read(fd,width,4);//读取四个字节read(fd,height,4);//高度lseek(fd,0x1c,SEEK_SET);read(fd,depth,4);1.3 调色板颜色数值组 1.4 像素数组 二、 实例练习
2.1加载一张图片实现代码
#include stdio.h
#include fcntl.h
#include unistd.h
#include sys/mman.h
#include stdlib.h
#include math.h int lcd_fd -1; // 全局的lcd描述符
unsigned int* plcd NULL;void lcdinit() {lcd_fd open(/dev/fb0, O_RDWR);if (-1 lcd_fd) {perror(open fb0 error);exit(1);}plcd mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);if (plcd MAP_FAILED) {perror(mmap error);return;}
}void lcd_destory() {munmap(plcd, 800 * 480 * 4);close(lcd_fd);
}void point(int x, int y, unsigned int color) {if (x 0 x 800 y 0 y 480) {*(plcd y * 800 x) color;}
}void display_sql(int w, int h, int x0, int y0, int color) {int x, y;for (y 0; y h; y) {for (x 0; x w; x) {point(x x0, y y0, color);}}
}
//添加背景颜色-color
void display_bgm(int color) {int w 800,h480;int x, y;for (y 0; y h; y) {for (x 0; x w; x) {point(x , y , color);}}
}void display_bmp(const char* filename,int x0,int y0)
{//打开文件int fd open(filename, O_RDONLY);if(-1 fd){perror(open bmp error);return;}//判断是否为真的BMP文件unsigned char buf[2];read(fd,buf,2);if(buf[0]! 0x42 || buf[1]! 0x4d)//若果不是B M 的ASCII码{printf(NOT BMP\n);return;}//读取数据int width,height,depth;//读取宽度将偏移量偏移到宽度lseek(fd,0x12,SEEK_SET);read(fd,width,4);//读取四个字节read(fd,height,4);//高度lseek(fd,0x1c,SEEK_SET);read(fd,depth,4);//只支持色深24和32if(!(depth 24 || depth 32)){printf(NOT Support!\n);return;}printf(width %d height %d depth %d , width,height,depth);//4.获取像素数组int line_valid_bytes abs(width)*depth/8;//一行有效字节数int line_bytes;//一行总字节数有效字节数赖子数 int laizi 0;if(line_valid_bytes%4){laizi 4-line_valid_bytes%4;}line_bytes line_valid_bytes laizi;int total_bytes line_bytes*abs(height);//整个像素数组的大小
//开辟一块动态内存unsigned char *piexl (unsigned char *)malloc(total_bytes); //用完后需要释放内存lseek(fd,54,SEEK_SET);read(fd,piexl,total_bytes);unsigned char a,r,g,b;int color;int i 0;int x,y;for(y0;yabs(height);y){for(x0;xabs(width);x){//a r g b 0xargb 小端模式 b g r ab piexl[i];g piexl[i];r piexl[i];if(depth 32){a piexl[i];}else{a 0;//不透明}color(a24)|(r16)|(g8)|(b);//在屏幕对应的位置显示point(width0?x0x:x0abs(width)-x-1, height0?y0abs(height)-y-1:y0y,color);}//每一行的末尾 有可能填充几个赖子i laizi;}//释放内存free(piexl);//关闭文件close(fd);
}int main() {lcdinit();display_bgm(0x000000);display_bmp(picture.bmp,0,0);lcd_destory();return 0;
}
上面代码中存在一段需要好好理解的一段
int line_valid_bytes abs(width)*depth/8;//一行有效字节数int line_bytes;//一行总字节数有效字节数赖子数 int laizi 0;if(line_valid_bytes%4){laizi 4-line_valid_bytes%4;}line_bytes line_valid_bytes laizi;int total_bytes line_bytes*abs(height);这段代码计算了与BMP图像相关的字节信息。具体来说它涉及到了BMP图像中每一行的数据存储方式以及为什么需要计算和使用这些值。
以下是代码中各部分的解释 line_valid_bytes abs(width) * depth / 8; width 表示图像的宽度。depth 表示每个像素的位深度通常为24表示RGB每个颜色通道8位或32带有额外的透明度通道。这一行计算了每一行的有效字节数。例如如果图像的宽度是800像素深度是24位则每一行需要 800 * 3 2400 字节来存储数据。 laizi 0; 这是一个中文词汇“赖子”的拼音通常用于描述不完全的部分或余数。 if(line_valid_bytes % 4) 这里检查有效字节数是否可以被4整除。在BMP文件格式中每一行的数据存储通常会在每行结束时填充到4字节的倍数。如果不能整除就需要在每一行的末尾添加一些额外的字节通常为0使其达到4字节的倍数。 laizi 4 - line_valid_bytes % 4; 如果line_valid_bytes不能被4整除laizi会被设置为使得总字节数达到4字节倍数所需的字节数。 line_bytes line_valid_bytes laizi; 计算了每一行总共所需的字节数。 int total_bytes line_bytes * abs(height); 这里计算了整个BMP图像所需的总字节数。它是每一行总字节数乘以图像的高度。
总的来说这段代码的目的是为了正确地计算BMP图像在内存中的字节布局。由于BMP图像要求每一行的数据存储都必须是4字节的倍数所以需要进行这样的计算来确保数据的正确存储和访问。
2.2 进阶对于图片大小不是800*480的图片进行轮播
因为我们的LCD的大小是800*480但是我们的图片的分辨率不是完全满足这个分辨率那么就需要对图片进行居中显示那么就只需要设置一定的偏移量就可以了.可以直接加入下面一段代码进去即可。 //处理居中的情况if(width800||height480){x0 (int)(800-width)/2;y0 (int)(480-height)/2;}具体实现代码。 #include stdio.h
#include fcntl.h
#include unistd.h
#include sys/mman.h
#include stdlib.h
#include math.h int lcd_fd -1; // 全局的lcd描述符
unsigned int* plcd NULL;void lcdinit() {lcd_fd open(/dev/fb0, O_RDWR);if (-1 lcd_fd) {perror(open fb0 error);exit(1);}plcd mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);if (plcd MAP_FAILED) {perror(mmap error);return;}
}void lcd_destory() {munmap(plcd, 800 * 480 * 4);close(lcd_fd);
}void point(int x, int y, unsigned int color) {if (x 0 x 800 y 0 y 480) {*(plcd y * 800 x) color;}
}
//添加背景颜色-color
void display_bgm(int color) {int w 800,h480;int x, y;for (y 0; y h; y) {for (x 0; x w; x) {point(x , y , color);}}
}void display_mid(const char* filename)
{int x0,y0;//打开文件int fd open(filename, O_RDONLY);if(-1 fd){perror(open bmp error);return;}//判断是否为真的BMP文件unsigned char buf[2];read(fd,buf,2);if(buf[0]! 0x42 || buf[1]! 0x4d)//若果不是B M 的ASCII码{printf(NOT BMP\n);return;}//读取数据int width,height,depth;//读取宽度将偏移量偏移到宽度lseek(fd,0x12,SEEK_SET);read(fd,width,4);//读取四个字节read(fd,height,4);//高度lseek(fd,0x1c,SEEK_SET);read(fd,depth,4);//只支持色深24和32if(!(depth 24 || depth 32)){printf(NOT Support!\n);return;}printf(width %d height %d depth %d , width,height,depth);//处理居中的情况if(width800||height480){x0 (int)(800-width)/2;y0 (int)(480-height)/2;}//4.获取像素数组int line_valid_bytes abs(width)*depth/8;//一行有效字节数int line_bytes;//一行总字节数有效字节数赖子数 int laizi 0;if(line_valid_bytes%4){laizi 4-line_valid_bytes%4;}line_bytes line_valid_bytes laizi;int total_bytes line_bytes*abs(height);//整个像素数组的大小//开辟一块动态内存unsigned char *piexl (unsigned char *)malloc(total_bytes); //用完后需要释放内存lseek(fd,54,SEEK_SET);read(fd,piexl,total_bytes);unsigned char a,r,g,b;int color;int i 0;int x,y;for(y0;yabs(height);y){for(x0;xabs(width);x){//a r g b 0xargb 小端模式 b g r ab piexl[i];g piexl[i];r piexl[i];if(depth 32)//32 色的有透明度但是对24位的来说无所谓这个a的都无效{a piexl[i];}else{a 0;//不透明}color(a24)|(r16)|(g8)|(b);//在屏幕对应的位置显示point(width0?x0x:x0abs(width)-x-1, height0?y0abs(height)-y-1:y0y,color);}//每一行的末尾 有可能填充几个赖子i laizi;}//释放内存free(piexl);//关闭文件close(fd);
}int main() {lcdinit();//display_bgm(0x000000);const char* images[] {1.bmp,2.bmp,3.bmp};int num_images sizeof(images) / sizeof(images[0]);int current_image_index 0;while(1){ display_mid(images[current_image_index]);sleep(2);display_bgm(0xFFFFFF);current_image_index (current_image_index 1) % num_images; // 切换到下一张图片}lcd_destory();return 0;
}
居中图片的显示