grml...
[seabios.git] / src / bmp.c
1 /*
2 * Basic BMP data process and Raw picture data handle functions.
3 * Could be used to adjust pixel data format, get infomation, etc.
4 *
5 * Copyright (C) 2011 Wayne Xia <xiawenc@cn.ibm.com>
6 *
7 * This work is licensed under the terms of the GNU LGPLv3.
8 */
9 #include "util.h"
10 #include "bmp.h"
11
12 #define bmp_load4byte(addr) (*(u32 *)(addr))
13 #define bmp_load2byte(addr) (*(u16 *)(addr))
14
15 typedef struct tagBITMAPFILEHEADER {
16     u8 bfType[2];
17     u8 bfSize[4];
18     u8 bfReserved1[2];
19     u8 bfReserved2[2];
20     u8 bfOffBits[4];
21 } BITMAPFILEHEADER, tagBITMAPFILEHEADER;
22
23 typedef struct tagBITMAPINFOHEADER {
24     u8 biSize[4];
25     u8 biWidth[4];
26     u8 biHeight[4];
27     u8 biPlanes[2];
28     u8 biBitCount[2];
29     u8 biCompression[4];
30     u8 biSizeImage[4];
31     u8 biXPelsPerMeter[4];
32     u8 biYPelsPerMeter[4];
33     u8 biClrUsed[4];
34     u8 biClrImportant[4];
35 } BITMAPINFOHEADER, tagBITMAPINFOHEADER;
36
37 typedef struct tagRGBQUAD {
38     u8 rgbBlue;
39     u8 rgbGreen;
40     u8 rgbRed;
41     u8 rgbReserved;
42 } RGBQUAD, tagRGBQUAD;
43
44 /* flat picture data adjusting function
45 * description:
46 *   switch the vertical line sequence
47 *   arrange horizontal pixel data, add extra space in the dest buffer
48 *       for every line
49 */
50 static void raw_data_format_adjust_24bpp(u8 *src, u8 *dest, int width,
51                                         int height, int bytes_per_line_dest)
52 {
53     int bytes_per_line_src = 3 * width;
54     int i;
55     for (i = 0 ; i < height ; i++) {
56         memcpy(dest + i * bytes_per_line_dest,
57            src + (height - 1 - i) * bytes_per_line_src, bytes_per_line_src);
58     }
59 }
60
61 struct bmp_decdata *bmp_alloc(void)
62 {
63     struct bmp_decdata *bmp = malloc_tmphigh(sizeof(*bmp));
64     return bmp;
65 }
66
67 int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size)
68 {
69     if (data_size < 54)
70         return 1;
71
72     u16 bmp_filehead = bmp_load2byte(data + 0);
73     if (bmp_filehead != 0x4d42)
74         return 2;
75     u32 bmp_recordsize = bmp_load4byte(data + 2);
76     if (bmp_recordsize != data_size)
77         return 3;
78     u32 bmp_dataoffset = bmp_load4byte(data + 10);
79     bmp->datap = (unsigned char *)data + bmp_dataoffset;
80     bmp->width = bmp_load4byte(data + 18);
81     bmp->height = bmp_load4byte(data + 22);
82     bmp->bpp = bmp_load2byte(data + 28);
83     return 0;
84 }
85
86 void bmp_get_size(struct bmp_decdata *bmp, int *width, int *height)
87 {
88     *width = bmp->width;
89     *height = bmp->height;
90 }
91
92
93 int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width
94              , int height, int depth, int bytes_per_line_dest)
95 {
96     if (bmp->datap == pic)
97         return 0;
98     /* now only support 24bpp bmp file */
99     if ((depth == 24) && (bmp->bpp == 24)) {
100         raw_data_format_adjust_24bpp(bmp->datap, pic, width, height,
101                                         bytes_per_line_dest);
102         return 0;
103     }
104     return 1;
105 }