|
|
@ -4598,19 +4598,22 @@ static int stbi__shiftsigned(int v, int shift, int bits) |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) |
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
{ |
|
|
|
stbi_uc *out; |
|
|
|
int bpp, offset, hsz; |
|
|
|
unsigned int mr=0,mg=0,mb=0,ma=0, all_a=255; |
|
|
|
unsigned int mr,mg,mb,ma, all_a; |
|
|
|
stbi_uc pal[256][4]; |
|
|
|
} stbi__bmp_data; |
|
|
|
int psize=0,i,j,compress=0,width; |
|
|
|
|
|
|
|
int bpp, flip_vertically, pad, target, offset, hsz; |
|
|
|
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int hsz; |
|
|
|
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); |
|
|
|
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); |
|
|
|
stbi__get32le(s); // discard filesize
|
|
|
|
stbi__get32le(s); // discard filesize
|
|
|
|
stbi__get16le(s); // discard reserved
|
|
|
|
stbi__get16le(s); // discard reserved
|
|
|
|
stbi__get16le(s); // discard reserved
|
|
|
|
stbi__get16le(s); // discard reserved
|
|
|
|
offset = stbi__get32le(s); |
|
|
|
info->offset = stbi__get32le(s); |
|
|
|
hsz = stbi__get32le(s); |
|
|
|
info->hsz = hsz = stbi__get32le(s); |
|
|
|
|
|
|
|
|
|
|
|
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); |
|
|
|
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); |
|
|
|
if (hsz == 12) { |
|
|
|
if (hsz == 12) { |
|
|
|
s->img_x = stbi__get16le(s); |
|
|
|
s->img_x = stbi__get16le(s); |
|
|
@ -4620,15 +4623,10 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
s->img_y = stbi__get32le(s); |
|
|
|
s->img_y = stbi__get32le(s); |
|
|
|
} |
|
|
|
} |
|
|
|
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
bpp = stbi__get16le(s); |
|
|
|
info->bpp = stbi__get16le(s); |
|
|
|
if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); |
|
|
|
if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); |
|
|
|
flip_vertically = ((int) s->img_y) > 0; |
|
|
|
if (hsz != 12) { |
|
|
|
s->img_y = abs((int) s->img_y); |
|
|
|
int compress = stbi__get32le(s); |
|
|
|
if (hsz == 12) { |
|
|
|
|
|
|
|
if (bpp < 24) |
|
|
|
|
|
|
|
psize = (offset - 14 - 24) / 3; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
compress = stbi__get32le(s); |
|
|
|
|
|
|
|
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); |
|
|
|
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); |
|
|
|
stbi__get32le(s); // discard sizeof
|
|
|
|
stbi__get32le(s); // discard sizeof
|
|
|
|
stbi__get32le(s); // discard hres
|
|
|
|
stbi__get32le(s); // discard hres
|
|
|
@ -4642,26 +4640,26 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
stbi__get32le(s); |
|
|
|
stbi__get32le(s); |
|
|
|
stbi__get32le(s); |
|
|
|
stbi__get32le(s); |
|
|
|
} |
|
|
|
} |
|
|
|
if (bpp == 16 || bpp == 32) { |
|
|
|
if (info->bpp == 16 || info->bpp == 32) { |
|
|
|
mr = mg = mb = 0; |
|
|
|
info->mr = info->mg = info->mb = 0; |
|
|
|
if (compress == 0) { |
|
|
|
if (compress == 0) { |
|
|
|
if (bpp == 32) { |
|
|
|
if (info->bpp == 32) { |
|
|
|
mr = 0xffu << 16; |
|
|
|
info->mr = 0xffu << 16; |
|
|
|
mg = 0xffu << 8; |
|
|
|
info->mg = 0xffu << 8; |
|
|
|
mb = 0xffu << 0; |
|
|
|
info->mb = 0xffu << 0; |
|
|
|
ma = 0xffu << 24; |
|
|
|
info->ma = 0xffu << 24; |
|
|
|
all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
|
|
|
info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
mr = 31u << 10; |
|
|
|
info->mr = 31u << 10; |
|
|
|
mg = 31u << 5; |
|
|
|
info->mg = 31u << 5; |
|
|
|
mb = 31u << 0; |
|
|
|
info->mb = 31u << 0; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (compress == 3) { |
|
|
|
} else if (compress == 3) { |
|
|
|
mr = stbi__get32le(s); |
|
|
|
info->mr = stbi__get32le(s); |
|
|
|
mg = stbi__get32le(s); |
|
|
|
info->mg = stbi__get32le(s); |
|
|
|
mb = stbi__get32le(s); |
|
|
|
info->mb = stbi__get32le(s); |
|
|
|
// not documented, but generated by photoshop and handled by mspaint
|
|
|
|
// not documented, but generated by photoshop and handled by mspaint
|
|
|
|
if (mr == mg && mg == mb) { |
|
|
|
if (info->mr == info->mg && info->mg == info->mb) { |
|
|
|
// ?!?!?
|
|
|
|
// ?!?!?
|
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
} |
|
|
|
} |
|
|
@ -4669,11 +4667,13 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
STBI_ASSERT(hsz == 108 || hsz == 124); |
|
|
|
int i; |
|
|
|
mr = stbi__get32le(s); |
|
|
|
if (hsz != 108 && hsz != 124) |
|
|
|
mg = stbi__get32le(s); |
|
|
|
return stbi__errpuc("bad BMP", "bad BMP"); |
|
|
|
mb = stbi__get32le(s); |
|
|
|
info->mr = stbi__get32le(s); |
|
|
|
ma = stbi__get32le(s); |
|
|
|
info->mg = stbi__get32le(s); |
|
|
|
|
|
|
|
info->mb = stbi__get32le(s); |
|
|
|
|
|
|
|
info->ma = stbi__get32le(s); |
|
|
|
stbi__get32le(s); // discard color space
|
|
|
|
stbi__get32le(s); // discard color space
|
|
|
|
for (i=0; i < 12; ++i) |
|
|
|
for (i=0; i < 12; ++i) |
|
|
|
stbi__get32le(s); // discard color space parameters
|
|
|
|
stbi__get32le(s); // discard color space parameters
|
|
|
@ -4684,35 +4684,68 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
stbi__get32le(s); // discard reserved
|
|
|
|
stbi__get32le(s); // discard reserved
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (bpp < 16) |
|
|
|
|
|
|
|
psize = (offset - 14 - hsz) >> 2; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return (void *) 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
stbi_uc *out; |
|
|
|
|
|
|
|
unsigned int mr=0,mg=0,mb=0,ma=0, all_a; |
|
|
|
|
|
|
|
stbi_uc pal[256][4]; |
|
|
|
|
|
|
|
int psize=0,i,j,width; |
|
|
|
|
|
|
|
int flip_vertically, pad, target; |
|
|
|
|
|
|
|
stbi__bmp_data info; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info.all_a = 255;
|
|
|
|
|
|
|
|
if (stbi__bmp_parse_header(s, &info) == NULL) |
|
|
|
|
|
|
|
return NULL; // error code already set
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
flip_vertically = ((int) s->img_y) > 0; |
|
|
|
|
|
|
|
s->img_y = abs((int) s->img_y); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mr = info.mr; |
|
|
|
|
|
|
|
mg = info.mg; |
|
|
|
|
|
|
|
mb = info.mb; |
|
|
|
|
|
|
|
ma = info.ma; |
|
|
|
|
|
|
|
all_a = info.all_a; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (info.hsz == 12) { |
|
|
|
|
|
|
|
if (info.bpp < 24) |
|
|
|
|
|
|
|
psize = (info.offset - 14 - 24) / 3; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (info.bpp < 16) |
|
|
|
|
|
|
|
psize = (info.offset - 14 - info.hsz) >> 2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
s->img_n = ma ? 4 : 3; |
|
|
|
s->img_n = ma ? 4 : 3; |
|
|
|
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
|
|
|
|
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
|
|
|
|
target = req_comp; |
|
|
|
target = req_comp; |
|
|
|
else |
|
|
|
else |
|
|
|
target = s->img_n; // if they want monochrome, we'll post-convert
|
|
|
|
target = s->img_n; // if they want monochrome, we'll post-convert
|
|
|
|
|
|
|
|
|
|
|
|
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); |
|
|
|
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); |
|
|
|
if (!out) return stbi__errpuc("outofmem", "Out of memory"); |
|
|
|
if (!out) return stbi__errpuc("outofmem", "Out of memory"); |
|
|
|
if (bpp < 16) { |
|
|
|
if (info.bpp < 16) { |
|
|
|
int z=0; |
|
|
|
int z=0; |
|
|
|
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } |
|
|
|
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } |
|
|
|
for (i=0; i < psize; ++i) { |
|
|
|
for (i=0; i < psize; ++i) { |
|
|
|
pal[i][2] = stbi__get8(s); |
|
|
|
pal[i][2] = stbi__get8(s); |
|
|
|
pal[i][1] = stbi__get8(s); |
|
|
|
pal[i][1] = stbi__get8(s); |
|
|
|
pal[i][0] = stbi__get8(s); |
|
|
|
pal[i][0] = stbi__get8(s); |
|
|
|
if (hsz != 12) stbi__get8(s); |
|
|
|
if (info.hsz != 12) stbi__get8(s); |
|
|
|
pal[i][3] = 255; |
|
|
|
pal[i][3] = 255; |
|
|
|
} |
|
|
|
} |
|
|
|
stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); |
|
|
|
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); |
|
|
|
if (bpp == 4) width = (s->img_x + 1) >> 1; |
|
|
|
if (info.bpp == 4) width = (s->img_x + 1) >> 1; |
|
|
|
else if (bpp == 8) width = s->img_x; |
|
|
|
else if (info.bpp == 8) width = s->img_x; |
|
|
|
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } |
|
|
|
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } |
|
|
|
pad = (-width)&3; |
|
|
|
pad = (-width)&3; |
|
|
|
for (j=0; j < (int) s->img_y; ++j) { |
|
|
|
for (j=0; j < (int) s->img_y; ++j) { |
|
|
|
for (i=0; i < (int) s->img_x; i += 2) { |
|
|
|
for (i=0; i < (int) s->img_x; i += 2) { |
|
|
|
int v=stbi__get8(s),v2=0; |
|
|
|
int v=stbi__get8(s),v2=0; |
|
|
|
if (bpp == 4) { |
|
|
|
if (info.bpp == 4) { |
|
|
|
v2 = v & 15; |
|
|
|
v2 = v & 15; |
|
|
|
v >>= 4; |
|
|
|
v >>= 4; |
|
|
|
} |
|
|
|
} |
|
|
@ -4721,7 +4754,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
out[z++] = pal[v][2]; |
|
|
|
out[z++] = pal[v][2]; |
|
|
|
if (target == 4) out[z++] = 255; |
|
|
|
if (target == 4) out[z++] = 255; |
|
|
|
if (i+1 == (int) s->img_x) break; |
|
|
|
if (i+1 == (int) s->img_x) break; |
|
|
|
v = (bpp == 8) ? stbi__get8(s) : v2; |
|
|
|
v = (info.bpp == 8) ? stbi__get8(s) : v2; |
|
|
|
out[z++] = pal[v][0]; |
|
|
|
out[z++] = pal[v][0]; |
|
|
|
out[z++] = pal[v][1]; |
|
|
|
out[z++] = pal[v][1]; |
|
|
|
out[z++] = pal[v][2]; |
|
|
|
out[z++] = pal[v][2]; |
|
|
@ -4733,14 +4766,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; |
|
|
|
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; |
|
|
|
int z = 0; |
|
|
|
int z = 0; |
|
|
|
int easy=0; |
|
|
|
int easy=0; |
|
|
|
stbi__skip(s, offset - 14 - hsz); |
|
|
|
stbi__skip(s, info.offset - 14 - info.hsz); |
|
|
|
if (bpp == 24) width = 3 * s->img_x; |
|
|
|
if (info.bpp == 24) width = 3 * s->img_x; |
|
|
|
else if (bpp == 16) width = 2*s->img_x; |
|
|
|
else if (info.bpp == 16) width = 2*s->img_x; |
|
|
|
else /* bpp = 32 and pad = 0 */ width=0; |
|
|
|
else /* bpp = 32 and pad = 0 */ width=0; |
|
|
|
pad = (-width) & 3; |
|
|
|
pad = (-width) & 3; |
|
|
|
if (bpp == 24) { |
|
|
|
if (info.bpp == 24) { |
|
|
|
easy = 1; |
|
|
|
easy = 1; |
|
|
|
} else if (bpp == 32) { |
|
|
|
} else if (info.bpp == 32) { |
|
|
|
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) |
|
|
|
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) |
|
|
|
easy = 2; |
|
|
|
easy = 2; |
|
|
|
} |
|
|
|
} |
|
|
@ -4765,6 +4798,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int |
|
|
|
if (target == 4) out[z++] = a; |
|
|
|
if (target == 4) out[z++] = a; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
int bpp = info.bpp; |
|
|
|
for (i=0; i < (int) s->img_x; ++i) { |
|
|
|
for (i=0; i < (int) s->img_x; ++i) { |
|
|
|
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); |
|
|
|
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); |
|
|
|
int a; |
|
|
|
int a; |
|
|
|