bmp图片转换成16进制数据

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jorney_dong/article/details/17411057

最近在开发中要在aboot中显示一张图片。但是发现aboot中显示图片不是直接拿图片文件来显示的,而是把一个16进制的数据序列依次往屏幕上搬运,就可以了。

那问题是,怎么把一张图片转换成16进制的数据序列?

在网上也找了一些资料,也咨询了一些同事,最后终于搞定,下面把相关的做法写下来备忘。

我们的aboot中显示方式只支持24bit bmp图片,所以要先看一下拿到的图片是不是这种格式。不是的话,就先用小画家或更高级的工具转成这种格式。然后,到ubuntu下运行命令:

 xxd -i logo.bmp logo.h
这个命令会把图片转换成16进制数字,写进一个头文件logo.h,这个头文件中会有一个数组,和一个表示数组长度(也就是bmp文件长度)的变量。

logo.h:

unsigned char logo_bmp[] = {
  0x42, 0x4d, 0xde, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
  0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x22, 0x01,
  0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xc4, 0x0e, 0x00, 0x00, 0xc4, 0x0e, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned int logo_bmp_len = 117214;
好了,已经拿到16进制的数据序列了,这就是我们要用的数据序列吗?不!还有好几步要做:

1. 了解bmp图片格式的知道,这个数组的前面一段是文件头信息,但是aboot中不需要这一段,所以要把它删除。

2. 另外,bmp图片如果每一行的字节数不是4的倍数,就会在每一行的最后添加若干字节空数据以对齐。这个空数据也要删除。

以 24bit bmp: 134X290 为例:

图片每一行134个像素,每个像素3个字节,所以每一行是134*3 == 402个字节,bmp会在每一行的最后添加两个字节来对齐。我们就要把这两个字节删除。

到这里可以了吗?还是没有,如果你试一下,就会发现,显示出来的图片是头向下倒过来的!因为bmp的数据就是从下往上存的。知道这一点,你可以一开始就在windows上把图片先做一个180度旋转,否则,就还要做下面两步处理:

3.反转整张图,即把数组的数组头尾互换一下。

4.做完步骤3,你会发现图片的颜色不对了!怎么回事? 是啊,R,B的位置也换了,R、G、B各占一个字节,所以还要每三个字节,就要把R和B的位置换一下。

好了,大功告成!

不过只是对左右对称的图片是可以的,如果左右不对称,则要先把图片转个180度,然后,只做上面的前两步,就可以了。

(其实旋转以后左右是反的,看下一篇:http://blog.csdn.net/jorney_dong/article/details/17419703

下面看一下具体处理图片的代码:

main.c:

#include <stdio.h>

//TO_DO ++++++++

#include "logo.h"

//bmp width, height
int bytes_per_bpp = 3;
int bmp_width = 134;
int bmp_height = 290;
unsigned int file_len = 117214;
unsigned char *bmp_file_data = logo_bmp;
#define REVERT_BMP  1   //revert the bmp: 1, don't revert: 0
//TO_DO  --------


/*bmp文件的前部是文件头信息,aboot中画图不需要这些
 * 1 删除文件头信息,
 * 
 * 以 24bit bmp: 134X290 为例
 * 图片每一行134个像素,每个像素3个字节,所以每一行是134*3 == 402个字节,
* bmp会在每一行的最后添加两个字节对齐。
* aboot中要用这个图片的话,
* 2.要把每行最后的两个对齐字节删除
* 
* 每行最后的两个字节删除以后
* 因为bmp本身的图片是倒的,
* 3.反转整张图
* 
* 反转整张图以后,R和B也互换了,导致颜色不对
* R、G、B各占一个字节,
* 4.这里是使其中的R 和 B互换。
* 
* 所以,如果把拿到手的图片先在windows上做一下180度的旋转,
* 应该可以省略步骤3和4,把上面的 REVERT_BMP 设定为0 即可。
*/
int main()
{
	unsigned int i = 0;
	unsigned int j = 0;
	unsigned int bmp_info_len = 0;
	unsigned int temp = 0;
	unsigned int actual_data_len = 0;
	unsigned char result_arry[file_len];
	unsigned char result_arry2[file_len];
	unsigned int data_bytes_per_row = (bmp_width*bytes_per_bpp);
	unsigned int total_bytes_per_row = 0;
	unsigned int null_bytes_per_row = 0;
	unsigned int array_len = 0; 
	if(data_bytes_per_row%4 != 0)
	{
		null_bytes_per_row = 4-data_bytes_per_row%4;
	}
	
	total_bytes_per_row = data_bytes_per_row + null_bytes_per_row;//total bytes per row
	bmp_info_len = file_len - total_bytes_per_row*bmp_height;//bmp file info len,or len to delete
	printf("file_len:---------------> %d \n",file_len);
	printf("bmp_info_len:-----------> %d \nnull_bytes_per_row:-----> %d\n",bmp_info_len,null_bytes_per_row);
	
	
	//1 删除文件头信息,
	for(i=bmp_info_len,j=0;i<file_len;i++,j++)
	{
		result_arry2[j] = bmp_file_data[i];
	}
	array_len = j;
	printf("step 1 over.\n");
	printf("data total_bytes:-------> %d \n",file_len-bmp_info_len);
	printf("total_bytes_per_row:----> %d \n",total_bytes_per_row);
	
	//in data <-- bmp_file_data[..]
	//2.删除每行最后的若干个字节,存于result_arry2
	for(i=1,j=0;i<=array_len;i++)
	{
		//delete null data at the end of row 
		result_arry[j] = result_arry2[i-1];
		j++;
		if(i%total_bytes_per_row==0)
		{
			j -= null_bytes_per_row;
		}

	}// out data to -->result_arry[..]
	printf("step 2 over.\n");
	
	array_len = j;
	
	#if REVERT_BMP
	//3.这里是反转整张图
	for(i=0,j=0;i<array_len;i++,j++)
	{
		result_arry2[j] = result_arry[array_len-i-1];
	}
	printf("step 3 over.\n");
	//in data <-- result_arry[..]
	//4. R、G、B各占一个字节,这里是使其中的R 和 B互换。
	for(i=0,j=0;i<array_len;)
	{
		result_arry[j] = result_arry2[i+2];
		result_arry[j+1] = result_arry2[i+1];
		result_arry[j+2] = result_arry2[i];
		i += 3;
		j += 3;
	}
	printf("step 4 over.\n");
	#endif
	printf("actual data array_len:---> %d \n",array_len);
	
    FILE* fout = fopen("resutfile.h","w+");
    if (fout == NULL) {
        printf("Failed to open\n");
        return;
    }
   for (i=0;i<array_len;)
    {
		fprintf(fout,"0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, \n",
		result_arry[i],result_arry[i+1],result_arry[i+2],result_arry[i+3],
		               result_arry[i+4],result_arry[i+5],result_arry[i+6],result_arry[i+7],
		              result_arry[i+8],result_arry[i+9],result_arry[i+10],result_arry[i+11]);
		              i +=12;
	}

  if (fclose(fout) != 0) {
        printf("Failed to close \n");
        return;
    }

	
}

上面已经说过处理的步骤,这里再说一下上面代码的用法:


0.在ubuntu下运行命令:

xxd -i logo.bmp logo.h

看main.c中的 TO_DO 段,填写相应的信息:
1.在main.c中引用上面生成的头文件
2.把bmp文件的信息:宽,高,在main.c填写好。
3.把这个头文件logo.h中的数组长度赋给变量file_len.
4.把这个头文件logo.h中的数组地址赋给(unsigned char *bmp_file_data).
5.定义 REVERT_BMP 的值,如果在这里要图片反转一下,就设1, 如果已经是反转的图片,就设0.

6.把logo.h放在main程序所在的路径
7.编译:
gcc -o main main.c

8.执行:
./main
就会生成一个resultfile.h,这个文件的内容就是最后aboot中要用的bmp图片的数据。


展开阅读全文

没有更多推荐了,返回首页