1. /***********************************************************************
  2. * U-Boot_bmp_logo_hacking
  3. * 声明:
  4. * 1. 该源代码来自myzr_android4_2_2_1_1_0.tar.bz2中的:
  5. * bootable/bootloader/uboot-imx/tools/bmp_logo.c
  6. * 2. 通过阅读该源码可以知道大致如何解析bmp图片,以及一些自动生成
  7. * 的文件是如何做到的,如一些自动生成.h和.c文件;
  8. * 3. 阅读该源码技能需求:
  9. * 1. bmp图片的格式的一些基本信息;
  10. * 2. 类Unix系统编程;
  11. * 3. C语言;
  12. * 4. 本源程序的阅读技巧:
  13. * 1. 本人是用了vim + ctags;
  14. * 2. 如果您是在windows下,传说中是可以是用Source Insight;
  15. * 3. 找main函数开始阅读;
  16. *
  17. * 2015-4-19 周日 晴 深圳 南山 西丽平山村 曾剑锋
  18. **********************************************************************/
  19.  
  20. /**
  21. * 源程序中仅仅是用了#include "compiler.h",由于我们仅仅需要本文件,
  22. * 所以本人注释了那一行,添加以下本文件需要用到的头文件
  23. */
  24. //#include "compiler.h"
  25. #include <errno.h>
  26. #include <stdlib.h>
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. /**
  32. * 用于大致描述一个bmp图片的结构体
  33. */
  34. typedef struct bitmap_s { /* bitmap description */
  35. uint16_t width;
  36. uint16_t height;
  37. uint8_t palette[*];
  38. uint8_t *data;
  39. } bitmap_t;
  40.  
  41. /**
  42. * 默认的颜色映射的大小
  43. */
  44. #define DEFAULT_CMAP_SIZE 16 /* size of default color map */
  45.  
  46. /*
  47. * Neutralize little endians.
  48. * bmp图片用的好象是小端的存储方式
  49. */
  50. uint16_t le_short(uint16_t x)
  51. {
  52. uint16_t val;
  53. uint8_t *p = (uint8_t *)(&x);
  54.  
  55. val = (*p++ & 0xff) << ;
  56. val |= (*p & 0xff) << ;
  57.  
  58. return val;
  59. }
  60.  
  61. /**
  62. * 在文件的当前位置,偏移多少个字节
  63. */
  64. void skip_bytes (FILE *fp, int n)
  65. {
  66. while (n-- > )
  67. fgetc (fp);
  68. }
  69.  
  70. /**
  71. * 错误输出函数,输出到标准错误输出
  72. */
  73. __attribute__ ((__noreturn__))
  74. int error (char * msg, FILE *fp)
  75. {
  76. fprintf (stderr, "ERROR: %s\n", msg);
  77.  
  78. fclose (fp);
  79.  
  80. exit (EXIT_FAILURE);
  81. }
  82.  
  83. int main (int argc, char *argv[])
  84. {
  85. /**
  86. * 局部变量说明:
  87. * 1. i : for循环计数;
  88. * 2. x : 字符暂存变量,for循环计数;
  89. * 3. fp : 打开的bmp文件指针;
  90. * 4. bmp : 用于存储bmp一些数据的数据结构;
  91. * 5. b : 指向上面bmp数据结构的指针;
  92. * 6. data_offset : bmp数据区相对文件头的偏移;
  93. * 7. n_colors : 实际使用了多少种颜色
  94. */
  95. int i, x;
  96. FILE *fp;
  97. bitmap_t bmp;
  98. bitmap_t *b = &bmp;
  99. uint16_t data_offset, n_colors;
  100.  
  101. /**
  102. * 命令行参数个数检查
  103. */
  104. if (argc < ) {
  105. fprintf (stderr, "Usage: %s file\n", argv[]);
  106. exit (EXIT_FAILURE);
  107. }
  108.  
  109. /**
  110. * 以二进制只读的方式打开bmp文件
  111. */
  112. if ((fp = fopen (argv[], "rb")) == NULL) {
  113. perror (argv[]);
  114. exit (EXIT_FAILURE);
  115. }
  116.  
  117. /**
  118. * 检查是否是bmp图片
  119. */
  120. if (fgetc (fp) != 'B' || fgetc (fp) != 'M')
  121. error ("Input file is not a bitmap", fp);
  122.  
  123. /*
  124. * read width and height of the image, and the number of colors used;
  125. * ignore the rest
  126. */
  127. /**
  128. * 前面的'B','M'占用了2个字节,
  129. * 2字节 + 8字节 = 10字节,
  130. * 这时文件指针正好指向11字节(保存bmp数据偏移的位置)
  131. */
  132. skip_bytes (fp, );
  133. if (fread (&data_offset, sizeof (uint16_t), , fp) != )
  134. error ("Couldn't read bitmap data offset", fp);
  135. skip_bytes (fp, );
  136.  
  137. /**
  138. * 前面的'B','M'占用了2个字节,
  139. * 2字节 + 8字节 = 10字节,
  140. * 10字节 + 2字节 = 12字节,
  141. * 12字节 + 6字节 = 18字节,
  142. * 这时文件指针正好指向19字节(保存bmp宽的位置)
  143. */
  144. if (fread (&b->width, sizeof (uint16_t), , fp) != )
  145. error ("Couldn't read bitmap width", fp);
  146. skip_bytes (fp, );
  147.  
  148. /**
  149. * 前面的'B','M'占用了2个字节,
  150. * 2字节 + 8字节 = 10字节,
  151. * 10字节 + 2字节 = 12字节,
  152. * 12字节 + 6字节 = 18字节,
  153. * 18字节 + 2字节 = 20字节,
  154. * 20字节 + 2字节 = 22字节,
  155. * 这时文件指针正好指向23字节(保存bmp高的位置)
  156. */
  157. if (fread (&b->height, sizeof (uint16_t), , fp) != )
  158. error ("Couldn't read bitmap height", fp);
  159. skip_bytes (fp, );
  160.  
  161. /**
  162. * 前面的'B','M'占用了2个字节,
  163. * 2字节 + 8字节 = 10字节,
  164. * 10字节 + 2字节 = 12字节,
  165. * 12字节 + 6字节 = 18字节,
  166. * 18字节 + 2字节 = 20字节,
  167. * 20字节 + 2字节 = 22字节,
  168. * 22字节 + 2字节 = 24字节,
  169. * 24字节 + 22字节 = 46字节,
  170. * 这时文件指针正好指向47字节(保存bmp图实际是用的颜色数)
  171. * skip_bytes (fp, 6); --> 跳出位图信息头
  172. */
  173. if (fread (&n_colors, sizeof (uint16_t), , fp) != )
  174. error ("Couldn't read bitmap colors", fp);
  175. skip_bytes (fp, );
  176.  
  177. /*
  178. * Repair endianess.
  179. * 防止数据出现大小不兼容的问题
  180. */
  181. data_offset = le_short(data_offset);
  182. b->width = le_short(b->width);
  183. b->height = le_short(b->height);
  184. n_colors = le_short(n_colors);
  185.  
  186. /* assume we are working with an 8-bit file */
  187. /**
  188. * 防止颜色数太小,或太大
  189. */
  190. if ((n_colors == ) || (n_colors > - DEFAULT_CMAP_SIZE)) {
  191. /* reserve DEFAULT_CMAP_SIZE color map entries for default map */
  192. n_colors = - DEFAULT_CMAP_SIZE;
  193. }
  194.  
  195. /**
  196. * 打印出一些注释信息和宏定义数据
  197. */
  198. printf ("/*\n"
  199. " * Automatically generated by \"tools/bmp_logo\"\n"
  200. " *\n"
  201. " * DO NOT EDIT\n"
  202. " *\n"
  203. " */\n\n\n"
  204. "#ifndef __BMP_LOGO_H__\n"
  205. "#define __BMP_LOGO_H__\n\n"
  206. "#define BMP_LOGO_WIDTH\t\t%d\n"
  207. "#define BMP_LOGO_HEIGHT\t\t%d\n"
  208. "#define BMP_LOGO_COLORS\t\t%d\n"
  209. "#define BMP_LOGO_OFFSET\t\t%d\n"
  210. "\n",
  211. b->width, b->height, n_colors,
  212. DEFAULT_CMAP_SIZE);
  213.  
  214. /* allocate memory */
  215. /**
  216. * 采用内存分配的方式,获取data的存储空间
  217. */
  218. if ((b->data = (uint8_t *)malloc(b->width * b->height)) == NULL)
  219. error ("Error allocating memory for file", fp);
  220.  
  221. /* read and print the palette information */
  222. /**
  223. * 以下是一个输出结果示例:
  224. * unsigned short bmp_logo_palette[] = {
  225. * 0x0FFF, 0x0DDE, 0x026B, 0x026B, 0x0FFF, 0x0FFF, 0x048C, 0x026B,
  226. * 0x026B, 0x0BDE, 0x047C, 0x027B, 0x09BE, 0x026B, 0x0EEF, 0x037B,
  227. * 0x08AD, 0x0DEF, 0x027B, 0x069D, 0x0CDE, 0x0ACE, 0x08BD, 0x07AD,
  228. * 0x027B, 0x058C, 0x037B, 0x0CDE, 0x06AD, 0x037C,
  229. * };
  230. */
  231. printf ("unsigned short bmp_logo_palette[] = {\n");
  232.  
  233. for (i=; i<n_colors; ++i) {
  234. b->palette[(int)(i*+)] = fgetc(fp); //个人查资料认为是blue
  235. b->palette[(int)(i*+)] = fgetc(fp); //个人查资料认为是green
  236. b->palette[(int)(i*+)] = fgetc(fp); //个人查资料认为是red
  237. x=fgetc(fp);
  238.  
  239. /**
  240. * 输出的结果正好和读出来的结果相反,主要是因为
  241. * 读取时,后面的高位,输出时先输出的是高位
  242. * 另外这里还考虑到格式化对齐的问题,主要是
  243. * 方便阅读输出的数据.
  244. */
  245. printf ("%s0x0%X%X%X,%s",
  246. ((i%) == ) ? "\t" : " ",
  247. (b->palette[(int)(i*+)] >> ) & 0x0F,
  248. (b->palette[(int)(i*+)] >> ) & 0x0F,
  249. (b->palette[(int)(i*+)] >> ) & 0x0F,
  250. ((i%) == ) ? "\n" : ""
  251. );
  252. }
  253.  
  254. /* seek to offset indicated by file header */
  255. /**
  256. * 感觉这行代码不应该放这里,应该放到下面2行后面去比较合理
  257. */
  258. fseek(fp, (long)data_offset, SEEK_SET);
  259.  
  260. /* read the bitmap; leave room for default color map */
  261. printf ("\n");
  262. printf ("};\n");
  263.  
  264. printf ("\n");
  265.  
  266. /**
  267. * 1. 以下是输出结果示例:
  268. * unsigned char bmp_logo_bitmap[] = {
  269. * 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  270. * 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  271. * ......
  272. * 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
  273. * 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
  274. * }
  275. * 2. 位图数据记录顺序是在扫描行内是从左到右,扫描行之间是从下到上,
  276. * Windows规定一个扫描行所占的字节数必须是4的倍数,不足以0填充;
  277. * 3. i = (b->height-1)*b->width : 相当于跳到数组的左下脚
  278. */
  279. printf ("unsigned char bmp_logo_bitmap[] = {\n");
  280. for (i=(b->height-)*b->width; i>=; i-=b->width) {
  281. for (x = ; x < b->width; x++) {
  282. b->data[(uint16_t) i + x] = (uint8_t) fgetc (fp) \
  283. + DEFAULT_CMAP_SIZE; //不知道这里为什么需要加这个参数
  284. }
  285. }
  286. fclose (fp);
  287.  
  288. /**
  289. * 输出bmp数据
  290. */
  291. for (i=; i<(b->height*b->width); ++i) {
  292. if ((i%) == )
  293. putchar ('\t');
  294. printf ("0x%02X,%c",
  295. b->data[i],
  296. ((i%) == ) ? '\n' : ' '
  297. );
  298. }
  299. printf ("\n"
  300. "};\n\n"
  301. "#endif /* __BMP_LOGO_H__ */\n"
  302. );
  303.  
  304. return ();
  305. }

随机推荐

  1. grafana 批量添加图表

    利用grafana做监控展示特别方便,而且界面还很有科技感,一般的使用都是自己手动添加图表,或者使用别人提供好的模板. 在一种情况下就比较尴尬了,我有100个实例的内存数据想展示,如果都放在一个tab ...

  2. 《剑指offer》第十八题(删除链表中重复的结点)

    // 面试题18(二):删除链表中重复的结点 // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复 // 结点被删除之后,链表如图3.4(b)所示. #include &l ...

  3. java日期获取前一天和后一天

    import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import j ...

  4. docker运行python3.6+flask小记

    docker新手. 目的:开发运行多个web api项目的时候,方便开发,兼顾部署. 方案大概这样: 1 隔离:系统运行在容器里,1容器只起1进程,代替在host起多个venv或虚拟机: 2调试和备份 ...

  5. RabbitMQ入门_13_消息持久化

    参考资料:https://www.rabbitmq.com/tutorials/tutorial-two-java.html 默认情况下,队列中的消息是不持久化的.如果 RabbitMQ 崩溃,队列中 ...

  6. C#中的?

    1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.为了使值类型也 ...

  7. 开发环境运行正常,发布服务器后提示HTTP 错误 403.14 - Forbidden

    一.发布服务器后报错 今天在项目发布中遇到一件奇怪的事,开发完成的项目,发布到服务器上时 1. 发布到A服务器,一切正常 2. 发布到B服务器,提示403服务器错误 在同事电脑上重新打包发布代码,并发 ...

  8. OC MRC之 @property参数(代码分析)

    第一部分 // // main.m // 04-@property参数 // // Created by apple on 13-8-9. // Copyright (c) 2013年 itcast. ...

  9. 让个人域名下GithubPage完美支持https

    让个人域名下GithubPage完美支持https 欢迎访问完美HTTPS支持的GithubPage个人博客 : https://zggdczfr.cn/ 前言 最近笔记本挂了送去维修,耽误了我的学习 ...

  10. 使用Jenkins自动编译我的.net 项目

    1.Jenkins是什么? Jenkins是一个可扩展的持续集成的引擎,主要用于持续自动的构建.测试软件项目 监控一些定时执行的任务.   2.安装配置 最新的Jenkins 安装包可以从这里下载:h ...