Have std/bmp decode OS/2 BMP files
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index ec528c8..4cc5d6e 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -16470,358 +16470,437 @@
goto exit;
}
self->private_impl.f_padding -= self->private_impl.f_bitmap_info_len;
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
- uint32_t t_3;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_3 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
+ if (self->private_impl.f_bitmap_info_len == 12) {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+ uint32_t t_3;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_3 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
+ if (num_bits_3 == 8) {
+ t_3 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_3 += 8;
+ *scratch |= ((uint64_t)(num_bits_3)) << 56;
}
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
- if (num_bits_3 == 24) {
- t_3 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_3 += 8;
- *scratch |= ((uint64_t)(num_bits_3)) << 56;
}
+ self->private_impl.f_width = t_3;
}
- v_width = t_3;
- }
- if (v_width >= 2147483648) {
- status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
- goto exit;
- }
- self->private_impl.f_width = v_width;
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
- uint32_t t_4;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_4 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
+ uint32_t t_4;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_4 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
+ if (num_bits_4 == 8) {
+ t_4 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_4 += 8;
+ *scratch |= ((uint64_t)(num_bits_4)) << 56;
}
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
- if (num_bits_4 == 24) {
- t_4 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_4 += 8;
- *scratch |= ((uint64_t)(num_bits_4)) << 56;
}
+ self->private_impl.f_height = t_4;
}
- v_height = t_4;
- }
- if (v_height == 2147483648) {
- status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
- goto exit;
- } else if (v_height >= 2147483648) {
- self->private_impl.f_height = ((0 - v_height) & 2147483647);
- self->private_impl.f_top_down = true;
- } else {
- self->private_impl.f_height = v_height;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
- uint32_t t_5;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
- t_5 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
- iop_a_src += 2;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
+ uint32_t t_5;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_5 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5;
+ if (num_bits_5 == 8) {
+ t_5 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_5 += 8;
+ *scratch |= ((uint64_t)(num_bits_5)) << 56;
}
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5;
- if (num_bits_5 == 8) {
- t_5 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_5 += 8;
- *scratch |= ((uint64_t)(num_bits_5)) << 56;
}
+ v_planes = t_5;
}
- v_planes = t_5;
- }
- if (v_planes != 1) {
- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
- goto exit;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
- uint32_t t_6;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
- t_6 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
- iop_a_src += 2;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
+ if (v_planes != 1) {
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
+ uint32_t t_6;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_6 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6;
+ if (num_bits_6 == 8) {
+ t_6 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_6 += 8;
+ *scratch |= ((uint64_t)(num_bits_6)) << 56;
}
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6;
- if (num_bits_6 == 8) {
- t_6 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_6 += 8;
- *scratch |= ((uint64_t)(num_bits_6)) << 56;
}
+ self->private_impl.f_bits_per_pixel = t_6;
}
- self->private_impl.f_bits_per_pixel = t_6;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
- uint32_t t_7;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_7 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
+ } else if (self->private_impl.f_bitmap_info_len == 16) {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
+ uint32_t t_7;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_7 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7;
+ if (num_bits_7 == 24) {
+ t_7 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_7 += 8;
+ *scratch |= ((uint64_t)(num_bits_7)) << 56;
}
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7;
- if (num_bits_7 == 24) {
- t_7 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_7 += 8;
- *scratch |= ((uint64_t)(num_bits_7)) << 56;
}
+ v_width = t_7;
}
- self->private_impl.f_compression = t_7;
- }
- if (self->private_impl.f_bits_per_pixel == 0) {
- if (self->private_impl.f_compression == 4) {
- self->private_impl.f_io_redirect_fourcc = 1246774599;
- status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
- goto ok;
- } else if (self->private_impl.f_compression == 5) {
- self->private_impl.f_io_redirect_fourcc = 1347307296;
- status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
- goto ok;
+ if (v_width >= 2147483648) {
+ status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
+ goto exit;
}
- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
- goto exit;
- }
- self->private_data.s_decode_image_config[0].scratch = 20;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18);
- if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
- self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
- iop_a_src = io2_a_src;
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- iop_a_src += self->private_data.s_decode_image_config[0].scratch;
- if (self->private_impl.f_bitmap_info_len == 40) {
- if (self->private_impl.f_bits_per_pixel >= 16) {
- if (self->private_impl.f_padding >= 16) {
- self->private_impl.f_bitmap_info_len = 56;
- self->private_impl.f_padding -= 16;
- } else if (self->private_impl.f_padding >= 12) {
- self->private_impl.f_bitmap_info_len = 52;
- self->private_impl.f_padding -= 12;
- }
- }
- } else if ((self->private_impl.f_bitmap_info_len != 52) &&
- (self->private_impl.f_bitmap_info_len != 56) &&
- (self->private_impl.f_bitmap_info_len != 108) &&
- (self->private_impl.f_bitmap_info_len != 124)) {
- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
- goto exit;
- }
- if (self->private_impl.f_compression == 6) {
- self->private_impl.f_compression = 3;
- }
- if (self->private_impl.f_compression == 3) {
- if (self->private_impl.f_bitmap_info_len >= 52) {
- {
+ self->private_impl.f_width = v_width;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18);
+ uint32_t t_8;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_8 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19);
- uint32_t t_8;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_8 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
- if (num_bits_8 == 24) {
- t_8 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_8 += 8;
- *scratch |= ((uint64_t)(num_bits_8)) << 56;
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
}
- }
- self->private_impl.f_channel_masks[2] = t_8;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21);
- uint32_t t_9;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_9 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
- if (num_bits_9 == 24) {
- t_9 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_9 += 8;
- *scratch |= ((uint64_t)(num_bits_9)) << 56;
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
+ if (num_bits_8 == 24) {
+ t_8 = ((uint32_t)(*scratch));
+ break;
}
- }
- self->private_impl.f_channel_masks[1] = t_9;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
- uint32_t t_10;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_10 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10;
- if (num_bits_10 == 24) {
- t_10 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_10 += 8;
- *scratch |= ((uint64_t)(num_bits_10)) << 56;
- }
- }
- self->private_impl.f_channel_masks[0] = t_10;
- }
- if (self->private_impl.f_bitmap_info_len >= 56) {
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25);
- uint32_t t_11;
- if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
- t_11 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
- iop_a_src += 4;
- } else {
- self->private_data.s_decode_image_config[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
- uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11;
- if (num_bits_11 == 24) {
- t_11 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_11 += 8;
- *scratch |= ((uint64_t)(num_bits_11)) << 56;
- }
- }
- self->private_impl.f_channel_masks[3] = t_11;
- }
- self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 56);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27);
- if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
- self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
- iop_a_src = io2_a_src;
- status = wuffs_base__make_status(wuffs_base__suspension__short_read);
- goto suspend;
- }
- iop_a_src += self->private_data.s_decode_image_config[0].scratch;
- }
- if ((self->private_impl.f_channel_masks[0] == 255) && (self->private_impl.f_channel_masks[1] == 65280) && (self->private_impl.f_channel_masks[2] == 16711680)) {
- if (self->private_impl.f_bits_per_pixel == 24) {
- self->private_impl.f_compression = 0;
- } else if (self->private_impl.f_bits_per_pixel == 32) {
- if ((self->private_impl.f_channel_masks[3] == 0) || (self->private_impl.f_channel_masks[3] == 4278190080)) {
- self->private_impl.f_compression = 0;
- }
+ num_bits_8 += 8;
+ *scratch |= ((uint64_t)(num_bits_8)) << 56;
}
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28);
- status = wuffs_bmp__decoder__process_masks(self);
- if (status.repr) {
- goto suspend;
- }
+ v_height = t_8;
}
- } else if (self->private_impl.f_bitmap_info_len >= 40) {
- self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 40);
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29);
+ if (v_height >= 2147483648) {
+ status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
+ goto exit;
+ }
+ self->private_impl.f_height = v_height;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20);
+ uint32_t t_9;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_9 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
+ if (num_bits_9 == 8) {
+ t_9 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_9 += 8;
+ *scratch |= ((uint64_t)(num_bits_9)) << 56;
+ }
+ }
+ v_planes = t_9;
+ }
+ if (v_planes != 1) {
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
+ uint32_t t_10;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_10 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10;
+ if (num_bits_10 == 8) {
+ t_10 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_10 += 8;
+ *scratch |= ((uint64_t)(num_bits_10)) << 56;
+ }
+ }
+ self->private_impl.f_bits_per_pixel = t_10;
+ }
+ } else {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
+ uint32_t t_11;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_11 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11;
+ if (num_bits_11 == 24) {
+ t_11 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_11 += 8;
+ *scratch |= ((uint64_t)(num_bits_11)) << 56;
+ }
+ }
+ v_width = t_11;
+ }
+ if (v_width >= 2147483648) {
+ status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
+ goto exit;
+ }
+ self->private_impl.f_width = v_width;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26);
+ uint32_t t_12;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_12 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12;
+ if (num_bits_12 == 24) {
+ t_12 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_12 += 8;
+ *scratch |= ((uint64_t)(num_bits_12)) << 56;
+ }
+ }
+ v_height = t_12;
+ }
+ if (v_height == 2147483648) {
+ status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
+ goto exit;
+ } else if (v_height >= 2147483648) {
+ self->private_impl.f_height = ((0 - v_height) & 2147483647);
+ self->private_impl.f_top_down = true;
+ } else {
+ self->private_impl.f_height = v_height;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28);
+ uint32_t t_13;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_13 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_13 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_13;
+ if (num_bits_13 == 8) {
+ t_13 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_13 += 8;
+ *scratch |= ((uint64_t)(num_bits_13)) << 56;
+ }
+ }
+ v_planes = t_13;
+ }
+ if (v_planes != 1) {
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30);
+ uint32_t t_14;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_14 = ((uint32_t)(wuffs_base__load_u16le__no_bounds_check(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_14 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_14;
+ if (num_bits_14 == 8) {
+ t_14 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_14 += 8;
+ *scratch |= ((uint64_t)(num_bits_14)) << 56;
+ }
+ }
+ self->private_impl.f_bits_per_pixel = t_14;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32);
+ uint32_t t_15;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_15 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15;
+ if (num_bits_15 == 24) {
+ t_15 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_15 += 8;
+ *scratch |= ((uint64_t)(num_bits_15)) << 56;
+ }
+ }
+ self->private_impl.f_compression = t_15;
+ }
+ if (self->private_impl.f_bits_per_pixel == 0) {
+ if (self->private_impl.f_compression == 4) {
+ self->private_impl.f_io_redirect_fourcc = 1246774599;
+ status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
+ goto ok;
+ } else if (self->private_impl.f_compression == 5) {
+ self->private_impl.f_io_redirect_fourcc = 1347307296;
+ status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
+ goto ok;
+ }
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ self->private_data.s_decode_image_config[0].scratch = 20;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(34);
if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
iop_a_src = io2_a_src;
@@ -16829,11 +16908,192 @@
goto suspend;
}
iop_a_src += self->private_data.s_decode_image_config[0].scratch;
+ if (self->private_impl.f_bitmap_info_len == 40) {
+ if (self->private_impl.f_bits_per_pixel >= 16) {
+ if (self->private_impl.f_padding >= 16) {
+ self->private_impl.f_bitmap_info_len = 56;
+ self->private_impl.f_padding -= 16;
+ } else if (self->private_impl.f_padding >= 12) {
+ self->private_impl.f_bitmap_info_len = 52;
+ self->private_impl.f_padding -= 12;
+ }
+ }
+ } else if ((self->private_impl.f_bitmap_info_len != 52) &&
+ (self->private_impl.f_bitmap_info_len != 56) &&
+ (self->private_impl.f_bitmap_info_len != 64) &&
+ (self->private_impl.f_bitmap_info_len != 108) &&
+ (self->private_impl.f_bitmap_info_len != 124)) {
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ if (self->private_impl.f_compression == 6) {
+ self->private_impl.f_compression = 3;
+ }
+ if (self->private_impl.f_compression == 3) {
+ if (self->private_impl.f_bitmap_info_len >= 52) {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(35);
+ uint32_t t_16;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_16 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(36);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16;
+ if (num_bits_16 == 24) {
+ t_16 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_16 += 8;
+ *scratch |= ((uint64_t)(num_bits_16)) << 56;
+ }
+ }
+ self->private_impl.f_channel_masks[2] = t_16;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(37);
+ uint32_t t_17;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_17 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(38);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_17 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_17;
+ if (num_bits_17 == 24) {
+ t_17 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_17 += 8;
+ *scratch |= ((uint64_t)(num_bits_17)) << 56;
+ }
+ }
+ self->private_impl.f_channel_masks[1] = t_17;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(39);
+ uint32_t t_18;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_18 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(40);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18;
+ if (num_bits_18 == 24) {
+ t_18 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_18 += 8;
+ *scratch |= ((uint64_t)(num_bits_18)) << 56;
+ }
+ }
+ self->private_impl.f_channel_masks[0] = t_18;
+ }
+ if (self->private_impl.f_bitmap_info_len >= 56) {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(41);
+ uint32_t t_19;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
+ t_19 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+ iop_a_src += 4;
+ } else {
+ self->private_data.s_decode_image_config[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(42);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
+ uint32_t num_bits_19 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_19;
+ if (num_bits_19 == 24) {
+ t_19 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_19 += 8;
+ *scratch |= ((uint64_t)(num_bits_19)) << 56;
+ }
+ }
+ self->private_impl.f_channel_masks[3] = t_19;
+ }
+ self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 56);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(43);
+ if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ iop_a_src += self->private_data.s_decode_image_config[0].scratch;
+ }
+ if ((self->private_impl.f_channel_masks[0] == 255) && (self->private_impl.f_channel_masks[1] == 65280) && (self->private_impl.f_channel_masks[2] == 16711680)) {
+ if (self->private_impl.f_bits_per_pixel == 24) {
+ self->private_impl.f_compression = 0;
+ } else if (self->private_impl.f_bits_per_pixel == 32) {
+ if ((self->private_impl.f_channel_masks[3] == 0) || (self->private_impl.f_channel_masks[3] == 4278190080)) {
+ self->private_impl.f_compression = 0;
+ }
+ }
+ }
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(44);
+ status = wuffs_bmp__decoder__process_masks(self);
+ if (status.repr) {
+ goto suspend;
+ }
+ }
+ } else if (self->private_impl.f_bitmap_info_len >= 40) {
+ self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 40);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(45);
+ if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
+ status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+ goto suspend;
+ }
+ iop_a_src += self->private_data.s_decode_image_config[0].scratch;
+ } else {
+ status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
+ goto exit;
+ }
+ }
+ if (self->private_impl.f_compression != 3) {
if (self->private_impl.f_bits_per_pixel < 16) {
if (a_src) {
a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(46);
status = wuffs_bmp__decoder__read_palette(self, a_src);
if (a_src) {
iop_a_src = a_src->data.ptr + a_src->meta.ri;
@@ -16842,9 +17102,6 @@
goto suspend;
}
}
- } else {
- status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
- goto exit;
}
if (self->private_impl.f_compression == 0) {
if ((self->private_impl.f_bits_per_pixel == 1) || (self->private_impl.f_bits_per_pixel == 2) || (self->private_impl.f_bits_per_pixel == 4)) {
@@ -16858,7 +17115,7 @@
self->private_impl.f_channel_masks[1] = 992;
self->private_impl.f_channel_masks[2] = 31744;
self->private_impl.f_channel_masks[3] = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(47);
status = wuffs_bmp__decoder__process_masks(self);
if (status.repr) {
goto suspend;
@@ -16901,6 +17158,14 @@
status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
goto exit;
}
+ if (((self->private_impl.f_bitmap_info_len < 40) || (self->private_impl.f_bitmap_info_len == 64)) &&
+ (self->private_impl.f_bits_per_pixel != 1) &&
+ (self->private_impl.f_bits_per_pixel != 4) &&
+ (self->private_impl.f_bits_per_pixel != 8) &&
+ (self->private_impl.f_bits_per_pixel != 24)) {
+ status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
+ goto exit;
+ }
if (self->private_impl.f_bits_per_pixel == 1) {
v_byte_width = ((self->private_impl.f_width >> 3) + (((self->private_impl.f_width & 7) + 7) >> 3));
self->private_impl.f_bytes_per_row = ((((((uint64_t)(v_byte_width)) * 1) + 3) >> 2) << 2);
@@ -18197,7 +18462,7 @@
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
- if (self->private_impl.f_bitmap_info_len < 40) {
+ if (self->private_impl.f_bitmap_info_len == 12) {
while ((v_i < 256) && (self->private_impl.f_padding >= 3)) {
self->private_impl.f_padding -= 3;
{
diff --git a/std/bmp/decode_bmp.wuffs b/std/bmp/decode_bmp.wuffs
index de2b816..eb9eab9 100644
--- a/std/bmp/decode_bmp.wuffs
+++ b/std/bmp/decode_bmp.wuffs
@@ -113,7 +113,9 @@
this.padding -= 14
this.io_redirect_pos = (this.padding as base.u64) ~sat+ args.src.position()
- // Read the BITMAPINFOHEADER (version 3 / 4 / 5 is 40 / 108 / 124 bytes).
+ // Read the BITMAPINFOHEADER:
+ // - OS/2 is 12, 16 or 64 bytes.
+ // - Windows is 40, 108 or 124 bytes.
this.bitmap_info_len = args.src.read_u32le?()
if this.padding < this.bitmap_info_len {
@@ -121,105 +123,140 @@
}
this.padding -= this.bitmap_info_len
- width = args.src.read_u32le?()
- if width >= 0x8000_0000 {
- return "#bad header"
- }
- this.width = width
+ if this.bitmap_info_len == 12 {
+ this.width = args.src.read_u16le_as_u32?()
+ this.height = args.src.read_u16le_as_u32?()
+ planes = args.src.read_u16le_as_u32?()
+ if planes <> 1 {
+ return "#unsupported BMP file"
+ }
+ this.bits_per_pixel = args.src.read_u16le_as_u32?()
- height = args.src.read_u32le?()
- if height == 0x8000_0000 {
- return "#bad header"
- } else if height >= 0x8000_0000 {
- // The &0x7FFF_FFFF is redundant, but proves to the compiler that the
- // result is within this.height's refined bounds.
- this.height = (0 ~mod- height) & 0x7FFF_FFFF
- this.top_down = true
- } else {
+ } else if this.bitmap_info_len == 16 {
+ width = args.src.read_u32le?()
+ if width >= 0x8000_0000 {
+ return "#bad header"
+ }
+ this.width = width
+ height = args.src.read_u32le?()
+ if height >= 0x8000_0000 {
+ return "#bad header"
+ }
this.height = height
- }
-
- planes = args.src.read_u16le_as_u32?()
- if planes <> 1 {
- return "#unsupported BMP file"
- }
-
- this.bits_per_pixel = args.src.read_u16le_as_u32?()
- this.compression = args.src.read_u32le?()
- if this.bits_per_pixel == 0 {
- if this.compression == COMPRESSION_JPEG {
- this.io_redirect_fourcc = 'JPEG'be
- return base."@I/O redirect"
- } else if this.compression == COMPRESSION_PNG {
- this.io_redirect_fourcc = 'PNG 'be
- return base."@I/O redirect"
+ planes = args.src.read_u16le_as_u32?()
+ if planes <> 1 {
+ return "#unsupported BMP file"
}
- return "#unsupported BMP file"
- }
+ this.bits_per_pixel = args.src.read_u16le_as_u32?()
- // We've already read 20 bytes from the BITMAPINFOHEADER: size (4), width
- // (4), height (4), planes (2), bpp (2), compression (4). Skip the rest of
- // the version 3 BITMAPINFOHEADER (whose total size is 40).
- args.src.skip_u32?(n: 40 - 20)
-
- if this.bitmap_info_len == 40 {
- if this.bits_per_pixel >= 16 {
- // It's poorly documented, but "length 40" data can be silently
- // augmented with RGB or RGBA channel_masks (12 or 16 bytes).
- if this.padding >= 16 {
- this.bitmap_info_len = 56
- this.padding -= 16
- } else if this.padding >= 12 {
- this.bitmap_info_len = 52
- this.padding -= 12
- }
+ } else {
+ width = args.src.read_u32le?()
+ if width >= 0x8000_0000 {
+ return "#bad header"
}
- } else if (this.bitmap_info_len <> 52) and (this.bitmap_info_len <> 56) and
- (this.bitmap_info_len <> 108) and (this.bitmap_info_len <> 124) {
- return "#unsupported BMP file"
- }
+ this.width = width
- // Treat COMPRESSION_ALPHABITFIELDS the same as COMPRESSION_BITFIELDS.
- if this.compression == COMPRESSION_ALPHABITFIELDS {
- this.compression = COMPRESSION_BITFIELDS
- }
+ height = args.src.read_u32le?()
+ if height == 0x8000_0000 {
+ return "#bad header"
+ } else if height >= 0x8000_0000 {
+ // The &0x7FFF_FFFF is redundant, but proves to the compiler that
+ // the result is within this.height's refined bounds.
+ this.height = (0 ~mod- height) & 0x7FFF_FFFF
+ this.top_down = true
+ } else {
+ this.height = height
+ }
- // Read the channel_masks when this.compression is COMPRESSION_BITFIELDS.
- if this.compression == COMPRESSION_BITFIELDS {
- if this.bitmap_info_len >= 52 {
- this.channel_masks[2] = args.src.read_u32le?()
- this.channel_masks[1] = args.src.read_u32le?()
- this.channel_masks[0] = args.src.read_u32le?()
- if this.bitmap_info_len >= 56 {
- this.channel_masks[3] = args.src.read_u32le?()
- // Skip the rest of the BITMAPINFOHEADER.
- args.src.skip_u32?(n: this.bitmap_info_len ~mod- 56)
+ planes = args.src.read_u16le_as_u32?()
+ if planes <> 1 {
+ return "#unsupported BMP file"
+ }
+
+ this.bits_per_pixel = args.src.read_u16le_as_u32?()
+ this.compression = args.src.read_u32le?()
+ if this.bits_per_pixel == 0 {
+ if this.compression == COMPRESSION_JPEG {
+ this.io_redirect_fourcc = 'JPEG'be
+ return base."@I/O redirect"
+ } else if this.compression == COMPRESSION_PNG {
+ this.io_redirect_fourcc = 'PNG 'be
+ return base."@I/O redirect"
}
- // If the explicit channel_masks are what the implicit ones would
- // be for no compression, treat it as no compression.
- if (this.channel_masks[0] == 0x0000_00FF) and
- (this.channel_masks[1] == 0x0000_FF00) and
- (this.channel_masks[2] == 0x00FF_0000) {
- if this.bits_per_pixel == 24 {
- this.compression = COMPRESSION_NONE
- } else if this.bits_per_pixel == 32 {
- if (this.channel_masks[3] == 0) or
- (this.channel_masks[3] == 0xFF00_0000) {
- this.compression = COMPRESSION_NONE
- }
+ return "#unsupported BMP file"
+ }
+
+ // We've already read 20 bytes from the BITMAPINFOHEADER: size (4),
+ // width (4), height (4), planes (2), bpp (2), compression (4). Skip
+ // the rest of the version 3 BITMAPINFOHEADER (whose total size is 40).
+ args.src.skip_u32?(n: 40 - 20)
+
+ if this.bitmap_info_len == 40 {
+ if this.bits_per_pixel >= 16 {
+ // It's poorly documented, but "length 40" data can be silently
+ // augmented with RGB or RGBA channel_masks (12 or 16 bytes).
+ if this.padding >= 16 {
+ this.bitmap_info_len = 56
+ this.padding -= 16
+ } else if this.padding >= 12 {
+ this.bitmap_info_len = 52
+ this.padding -= 12
}
}
- this.process_masks?()
+ } else if (this.bitmap_info_len <> 52) and
+ (this.bitmap_info_len <> 56) and
+ (this.bitmap_info_len <> 64) and
+ (this.bitmap_info_len <> 108) and
+ (this.bitmap_info_len <> 124) {
+ return "#unsupported BMP file"
}
- } else if this.bitmap_info_len >= 40 {
- // Skip the rest of the BITMAPINFOHEADER.
- args.src.skip_u32?(n: this.bitmap_info_len - 40)
+
+ // Treat COMPRESSION_ALPHABITFIELDS the same as COMPRESSION_BITFIELDS.
+ if this.compression == COMPRESSION_ALPHABITFIELDS {
+ this.compression = COMPRESSION_BITFIELDS
+ }
+
+ // Read the channel_masks when this.compression is
+ // COMPRESSION_BITFIELDS.
+ if this.compression == COMPRESSION_BITFIELDS {
+ if this.bitmap_info_len >= 52 {
+ this.channel_masks[2] = args.src.read_u32le?()
+ this.channel_masks[1] = args.src.read_u32le?()
+ this.channel_masks[0] = args.src.read_u32le?()
+ if this.bitmap_info_len >= 56 {
+ this.channel_masks[3] = args.src.read_u32le?()
+ // Skip the rest of the BITMAPINFOHEADER.
+ args.src.skip_u32?(n: this.bitmap_info_len ~mod- 56)
+ }
+ // If the explicit channel_masks are what the implicit ones
+ // would be for no compression, treat it as no compression.
+ if (this.channel_masks[0] == 0x0000_00FF) and
+ (this.channel_masks[1] == 0x0000_FF00) and
+ (this.channel_masks[2] == 0x00FF_0000) {
+ if this.bits_per_pixel == 24 {
+ this.compression = COMPRESSION_NONE
+ } else if this.bits_per_pixel == 32 {
+ if (this.channel_masks[3] == 0) or
+ (this.channel_masks[3] == 0xFF00_0000) {
+ this.compression = COMPRESSION_NONE
+ }
+ }
+ }
+ this.process_masks?()
+ }
+ } else if this.bitmap_info_len >= 40 {
+ // Skip the rest of the BITMAPINFOHEADER.
+ args.src.skip_u32?(n: this.bitmap_info_len - 40)
+ } else {
+ return "#unsupported BMP file"
+ }
+ }
+
+ if this.compression <> COMPRESSION_BITFIELDS {
// The palette follows the BITMAPINFOHEADER.
if this.bits_per_pixel < 16 {
this.read_palette?(src: args.src)
}
- } else {
- return "#unsupported BMP file"
}
if this.compression == COMPRESSION_NONE {
@@ -276,6 +313,15 @@
return "#unsupported BMP file"
}
+ // OS/2 BMP files have fewer valid bits_per_pixel values.
+ if ((this.bitmap_info_len < 40) or (this.bitmap_info_len == 64)) and
+ (this.bits_per_pixel <> 1) and
+ (this.bits_per_pixel <> 4) and
+ (this.bits_per_pixel <> 8) and
+ (this.bits_per_pixel <> 24) {
+ return "#bad header"
+ }
+
// The "((x + 3) >> 2) << 2" dance rounds x up to a multiple of 4.
if this.bits_per_pixel == 1 {
// byte_width is this.width divided by 8, rounding up.
@@ -1098,7 +1144,7 @@
var i : base.u32
var argb : base.u32
- if this.bitmap_info_len < 40 {
+ if this.bitmap_info_len == 12 {
while (i < 256) and (this.padding >= 3) {
this.padding -= 3
argb = args.src.read_u24le_as_u32?()