/* * Basic BMP data process and Raw picture data handle functions. * Could be used to adjust pixel data format, get infomation, etc. * * Copyright (C) 2011 Wayne Xia * * This work is licensed under the terms of the GNU LGPLv3. */ #include "util.h" #include "bmp.h" #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_24bpp(u8 *src, u8 *dest, int width, int height, int bytes_per_line_dest) { int bytes_per_line_src = 3 * width; 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); } } struct bmp_decdata *bmp_alloc(void) { struct bmp_decdata *bmp = malloc_tmphigh(sizeof(*bmp)); return bmp; } 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; } void bmp_get_size(struct bmp_decdata *bmp, int *width, int *height) { *width = bmp->width; *height = bmp->height; } 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; /* now only support 24bpp bmp file */ if ((depth == 24) && (bmp->bpp == 24)) { raw_data_format_adjust_24bpp(bmp->datap, pic, width, height, bytes_per_line_dest); return 0; } return 1; }