Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/bmp.c
| Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | static bool checkbmp(const uchar *mem, const size_t size) | ||||
| return ok; | return ok; | ||||
| } | } | ||||
| bool imb_is_a_bmp(const uchar *buf, size_t size) | bool imb_is_a_bmp(const uchar *buf, size_t size) | ||||
| { | { | ||||
| return checkbmp(buf, size); | return checkbmp(buf, size); | ||||
| } | } | ||||
| static size_t imb_bmp_calc_row_size_in_bytes(size_t x, size_t depth) | |||||
| { | |||||
| if (depth <= 8) { | |||||
| return (depth * x + 31) / 32 * 4; | |||||
| } | |||||
| return (depth >> 3) * x; | |||||
| } | |||||
| ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) | ImBuf *imb_bmp_decode(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) | ||||
| { | { | ||||
| ImBuf *ibuf = NULL; | ImBuf *ibuf = NULL; | ||||
| BMPINFOHEADER bmi; | BMPINFOHEADER bmi; | ||||
| int x, y, depth, ibuf_depth, skip; | int x, y, depth, ibuf_depth, skip; | ||||
| const uchar *bmp; | const uchar *bmp; | ||||
| uchar *rect; | uchar *rect; | ||||
| ushort col; | ushort col; | ||||
| double xppm, yppm; | double xppm, yppm; | ||||
| bool top_to_bottom = false; | bool top_to_bottom = false; | ||||
| (void)size; /* unused */ | (void)size; /* unused */ | ||||
| if (checkbmp(mem, size) == 0) { | if (checkbmp(mem, size) == 0) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); | colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); | ||||
| bmp = mem + LITTLE_LONG(*(int *)(mem + 10)); | const size_t pixel_data_offset = LITTLE_LONG(*(int *)(mem + 10)); | ||||
| bmp = mem + pixel_data_offset; | |||||
| if (CHECK_HEADER_FIELD_BMP(mem)) { | if (CHECK_HEADER_FIELD_BMP(mem)) { | ||||
| /* skip fileheader */ | /* skip fileheader */ | ||||
| mem += BMP_FILEHEADER_SIZE; | mem += BMP_FILEHEADER_SIZE; | ||||
| } | } | ||||
| else { | else { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* for systems where an int needs to be 4 bytes aligned */ | /* for systems where an int needs to be 4 bytes aligned */ | ||||
| memcpy(&bmi, mem, sizeof(bmi)); | memcpy(&bmi, mem, sizeof(bmi)); | ||||
| skip = LITTLE_LONG(bmi.biSize); | skip = LITTLE_LONG(bmi.biSize); | ||||
| x = LITTLE_LONG(bmi.biWidth); | x = LITTLE_LONG(bmi.biWidth); | ||||
| y = LITTLE_LONG(bmi.biHeight); | y = LITTLE_LONG(bmi.biHeight); | ||||
| depth = LITTLE_SHORT(bmi.biBitCount); | depth = LITTLE_SHORT(bmi.biBitCount); | ||||
| xppm = LITTLE_LONG(bmi.biXPelsPerMeter); | xppm = LITTLE_LONG(bmi.biXPelsPerMeter); | ||||
| yppm = LITTLE_LONG(bmi.biYPelsPerMeter); | yppm = LITTLE_LONG(bmi.biYPelsPerMeter); | ||||
| const size_t row_size_in_bytes = imb_bmp_calc_row_size_in_bytes(x, depth); | |||||
| const size_t num_expected_data_bytes = row_size_in_bytes * y; | |||||
| const size_t num_actual_data_bytes = size - pixel_data_offset; | |||||
| if (num_actual_data_bytes < num_expected_data_bytes) { | |||||
| return NULL; | |||||
| } | |||||
| if (depth <= 8) { | if (depth <= 8) { | ||||
| ibuf_depth = 24; | ibuf_depth = 24; | ||||
| } | } | ||||
| else { | else { | ||||
| ibuf_depth = depth; | ibuf_depth = depth; | ||||
| } | } | ||||
| if (y < 0) { | if (y < 0) { | ||||
| Show All 13 Lines | else { | ||||
| ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect); | ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect); | ||||
| if (!ibuf) { | if (!ibuf) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| rect = (uchar *)ibuf->rect; | rect = (uchar *)ibuf->rect; | ||||
| if (depth <= 8) { | if (depth <= 8) { | ||||
| const int rowsize = (depth * x + 31) / 32 * 4; | |||||
| const char(*palette)[4] = (void *)(mem + skip); | const char(*palette)[4] = (void *)(mem + skip); | ||||
| const int startmask = ((1 << depth) - 1) << 8; | const int startmask = ((1 << depth) - 1) << 8; | ||||
| for (size_t i = y; i > 0; i--) { | for (size_t i = y; i > 0; i--) { | ||||
| int index; | int index; | ||||
| int bitoffs = 8; | int bitoffs = 8; | ||||
| int bitmask = startmask; | int bitmask = startmask; | ||||
| int nbytes = 0; | int nbytes = 0; | ||||
| const char *pcol; | const char *pcol; | ||||
| Show All 16 Lines | if (depth <= 8) { | ||||
| /* Advance to the next byte */ | /* Advance to the next byte */ | ||||
| bitoffs = 8; | bitoffs = 8; | ||||
| bitmask = startmask; | bitmask = startmask; | ||||
| nbytes += 1; | nbytes += 1; | ||||
| bmp += 1; | bmp += 1; | ||||
| } | } | ||||
| } | } | ||||
| /* Advance to the next row */ | /* Advance to the next row */ | ||||
| bmp += (rowsize - nbytes); | bmp += (row_size_in_bytes - nbytes); | ||||
| } | } | ||||
| } | } | ||||
| else if (depth == 16) { | else if (depth == 16) { | ||||
| for (size_t i = y; i > 0; i--) { | for (size_t i = y; i > 0; i--) { | ||||
| if (top_to_bottom) { | if (top_to_bottom) { | ||||
| rect = (uchar *)&ibuf->rect[(i - 1) * x]; | rect = (uchar *)&ibuf->rect[(i - 1) * x]; | ||||
| } | } | ||||
| for (size_t j = x; j > 0; j--) { | for (size_t j = x; j > 0; j--) { | ||||
| ▲ Show 20 Lines • Show All 168 Lines • Show Last 20 Lines | |||||