Fix loading of indexed .bmp files
D1173 by @rdb Support for 1,2,4 bit images
This commit is contained in:
@@ -105,7 +105,7 @@ static int checkbmp(unsigned char *mem)
|
|||||||
if (u >= sizeof(BMPINFOHEADER)) {
|
if (u >= sizeof(BMPINFOHEADER)) {
|
||||||
if (bmi.biCompression == 0) {
|
if (bmi.biCompression == 0) {
|
||||||
u = LITTLE_SHORT(bmi.biBitCount);
|
u = LITTLE_SHORT(bmi.biBitCount);
|
||||||
if (u >= 8) {
|
if (u > 0 && u <= 32) {
|
||||||
ret_val = 1;
|
ret_val = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,10 +136,15 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
|
|||||||
|
|
||||||
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));
|
||||||
|
|
||||||
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 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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));
|
||||||
@@ -173,29 +178,43 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect);
|
ibuf = IMB_allocImBuf(x, y, ibuf_depth, IB_rect);
|
||||||
bmp = mem + skip;
|
|
||||||
rect = (unsigned char *) ibuf->rect;
|
rect = (unsigned char *) ibuf->rect;
|
||||||
|
|
||||||
if (depth == 8) {
|
if (depth <= 8) {
|
||||||
const int x_pad = (4 - (x % 4)) % 4;
|
const int rowsize = (depth * x + 31) / 32 * 4;
|
||||||
const char (*palette)[4] = (void *)bmp;
|
const char (*palette)[4] = (void *)(mem + skip);
|
||||||
bmp += bmi.biClrUsed * 4;
|
const int startmask = ((1 << depth) - 1) << 8;
|
||||||
for (i = y; i > 0; i--) {
|
for (i = y; i > 0; i--) {
|
||||||
|
int index;
|
||||||
|
int bitoffs = 8;
|
||||||
|
int bitmask = startmask;
|
||||||
|
int nbytes = 0;
|
||||||
|
const char *pcol;
|
||||||
if (top_to_bottom) {
|
if (top_to_bottom) {
|
||||||
rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
|
rect = (unsigned char *) &ibuf->rect[(i - 1) * x];
|
||||||
}
|
}
|
||||||
for (j = x; j > 0; j--) {
|
for (j = x; j > 0; j--) {
|
||||||
const char *pcol = palette[bmp[0]];
|
bitoffs -= depth;
|
||||||
|
bitmask >>= depth;
|
||||||
|
index = (bmp[0] & bitmask) >> bitoffs;
|
||||||
|
pcol = palette[index];
|
||||||
/* intentionally BGR -> RGB */
|
/* intentionally BGR -> RGB */
|
||||||
rect[0] = pcol[2];
|
rect[0] = pcol[2];
|
||||||
rect[1] = pcol[1];
|
rect[1] = pcol[1];
|
||||||
rect[2] = pcol[0];
|
rect[2] = pcol[0];
|
||||||
|
|
||||||
rect[3] = 255;
|
rect[3] = 255;
|
||||||
rect += 4; bmp += 1;
|
rect += 4;
|
||||||
|
if (bitoffs == 0) {
|
||||||
|
/* Advance to the next byte */
|
||||||
|
bitoffs = 8;
|
||||||
|
bitmask = startmask;
|
||||||
|
nbytes += 1;
|
||||||
|
bmp += 1;
|
||||||
}
|
}
|
||||||
/* rows are padded to multiples of 4 */
|
}
|
||||||
bmp += x_pad;
|
/* Advance to the next row */
|
||||||
|
bmp += (rowsize - nbytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (depth == 16) {
|
else if (depth == 16) {
|
||||||
|
Reference in New Issue
Block a user