zoukankan      html  css  js  c++  java
  • U-Boot_bmp_logo_hacking

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