| /* |
| * Basic BMP data process and Raw picture data handle functions. |
| * Could be used to adjust pixel data format, get information, etc. |
| * |
| * Copyright (C) 2011 Wayne Xia <xiawenc@cn.ibm.com> |
| * |
| * This work is licensed under the terms of the GNU LGPLv3. |
| */ |
| #include "malloc.h" // malloc_tmphigh |
| #include "string.h" // memcpy |
| #include "util.h" // struct bmp_decdata |
| |
| struct bmp_decdata { |
| struct tagRGBQUAD *quadp; |
| unsigned char *datap; |
| int width; |
| int height; |
| int bpp; |
| }; |
| |
| #define bmp_load4byte(addr) (*(u32 *)(addr)) |
| #define bmp_load2byte(addr) (*(u16 *)(addr)) |
| |
| typedef struct tagBITMAPFILEHEADER { |
| u8 bfType[2]; |
| u8 bfSize[4]; |
| u8 bfReserved1[2]; |
| u8 bfReserved2[2]; |
| u8 bfOffBits[4]; |
| } BITMAPFILEHEADER, tagBITMAPFILEHEADER; |
| |
| typedef struct tagBITMAPINFOHEADER { |
| u8 biSize[4]; |
| u8 biWidth[4]; |
| u8 biHeight[4]; |
| u8 biPlanes[2]; |
| u8 biBitCount[2]; |
| u8 biCompression[4]; |
| u8 biSizeImage[4]; |
| u8 biXPelsPerMeter[4]; |
| u8 biYPelsPerMeter[4]; |
| u8 biClrUsed[4]; |
| u8 biClrImportant[4]; |
| } BITMAPINFOHEADER, tagBITMAPINFOHEADER; |
| |
| typedef struct tagRGBQUAD { |
| u8 rgbBlue; |
| u8 rgbGreen; |
| u8 rgbRed; |
| u8 rgbReserved; |
| } RGBQUAD, tagRGBQUAD; |
| |
| /* flat picture data adjusting function |
| * description: |
| * switch the vertical line sequence |
| * arrange horizontal pixel data, add extra space in the dest buffer |
| * for every line |
| */ |
| static void raw_data_format_adjust(u8 *src, u8 *dest, int width, |
| int height, int bytes_per_line_src, int bytes_per_line_dest) |
| { |
| int i; |
| for (i = 0 ; i < height ; i++) { |
| memcpy(dest + i * bytes_per_line_dest, |
| src + (height - 1 - i) * bytes_per_line_src, bytes_per_line_src); |
| } |
| } |
| |
| /* allocate decdata struct */ |
| struct bmp_decdata *bmp_alloc(void) |
| { |
| struct bmp_decdata *bmp = malloc_tmphigh(sizeof(*bmp)); |
| return bmp; |
| } |
| |
| /* extract information from bmp file data */ |
| int bmp_decode(struct bmp_decdata *bmp, unsigned char *data, int data_size) |
| { |
| if (data_size < 54) |
| return 1; |
| |
| u16 bmp_filehead = bmp_load2byte(data + 0); |
| if (bmp_filehead != 0x4d42) |
| return 2; |
| u32 bmp_recordsize = bmp_load4byte(data + 2); |
| if (bmp_recordsize != data_size) |
| return 3; |
| u32 bmp_dataoffset = bmp_load4byte(data + 10); |
| bmp->datap = (unsigned char *)data + bmp_dataoffset; |
| bmp->width = bmp_load4byte(data + 18); |
| bmp->height = bmp_load4byte(data + 22); |
| bmp->bpp = bmp_load2byte(data + 28); |
| return 0; |
| } |
| |
| /* get bmp properties */ |
| void bmp_get_info(struct bmp_decdata *bmp, int *width, int *height, int *bpp) |
| { |
| *width = bmp->width; |
| *height = bmp->height; |
| *bpp = bmp->bpp; |
| } |
| |
| /* flush flat picture data to *pc */ |
| int bmp_show(struct bmp_decdata *bmp, unsigned char *pic, int width, |
| int height, int depth, int bytes_per_line_dest) |
| { |
| if (bmp->datap == pic) |
| return 0; |
| if ((depth == bmp->bpp) && (bmp->bpp%8 == 0)) { |
| raw_data_format_adjust(bmp->datap, pic, width, height, |
| (bmp->bpp/8)*width, bytes_per_line_dest); |
| return 0; |
| } |
| return 1; |
| } |