Add more error explanations in the BMP image loader

This closes #32166 and closes #30629.

(cherry picked from commit 40485e2479)
This commit is contained in:
Hugo Locurcio 2020-08-18 16:47:07 +02:00 committed by Rémi Verschelde
parent a6f0810d51
commit f90931c47a
No known key found for this signature in database
GPG Key ID: C3336907360768E1
2 changed files with 20 additions and 14 deletions

View File

@ -7,7 +7,7 @@
[AnimatedTexture] is a resource format for frame-based animations, where multiple textures can be chained automatically with a predefined delay for each frame. Unlike [AnimationPlayer] or [AnimatedSprite], it isn't a [Node], but has the advantage of being usable anywhere a [Texture] resource can be used, e.g. in a [TileSet]. [AnimatedTexture] is a resource format for frame-based animations, where multiple textures can be chained automatically with a predefined delay for each frame. Unlike [AnimationPlayer] or [AnimatedSprite], it isn't a [Node], but has the advantage of being usable anywhere a [Texture] resource can be used, e.g. in a [TileSet].
The playback of the animation is controlled by the [member fps] property as well as each frame's optional delay (see [method set_frame_delay]). The animation loops, i.e. it will restart at frame 0 automatically after playing the last frame. The playback of the animation is controlled by the [member fps] property as well as each frame's optional delay (see [method set_frame_delay]). The animation loops, i.e. it will restart at frame 0 automatically after playing the last frame.
[AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one. [AnimatedTexture] currently requires all frame textures to have the same size, otherwise the bigger ones will be cropped to match the smallest one.
[b]Note:[/b] AnimatedTexture doesn't support using [AtlasTexture]s. Each frame needs to be a separate [Texture2D]. [b]Note:[/b] AnimatedTexture doesn't support using [AtlasTexture]s. Each frame needs to be a separate [Texture].
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>

View File

@ -51,17 +51,20 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
if (bits_per_pixel == 1) { if (bits_per_pixel == 1) {
// Requires bit unpacking... // Requires bit unpacking...
ERR_FAIL_COND_V(width % 8 != 0, ERR_UNAVAILABLE); ERR_FAIL_COND_V_MSG(width % 8 != 0, ERR_UNAVAILABLE,
ERR_FAIL_COND_V(height % 8 != 0, ERR_UNAVAILABLE); vformat("1-bpp BMP images must have a width that is a multiple of 8, but the imported BMP is %d pixels wide.", int(width)));
ERR_FAIL_COND_V_MSG(height % 8 != 0, ERR_UNAVAILABLE,
vformat("1-bpp BMP images must have a height that is a multiple of 8, but the imported BMP is %d pixels tall.", int(height)));
} else if (bits_per_pixel == 4) { } else if (bits_per_pixel == 4) {
// Requires bit unpacking... // Requires bit unpacking...
ERR_FAIL_COND_V(width % 2 != 0, ERR_UNAVAILABLE); ERR_FAIL_COND_V_MSG(width % 2 != 0, ERR_UNAVAILABLE,
ERR_FAIL_COND_V(height % 2 != 0, ERR_UNAVAILABLE); vformat("4-bpp BMP images must have a width that is a multiple of 2, but the imported BMP is %d pixels wide.", int(width)));
ERR_FAIL_COND_V_MSG(height % 2 != 0, ERR_UNAVAILABLE,
vformat("4-bpp BMP images must have a height that is a multiple of 2, but the imported BMP is %d pixels tall.", int(height)));
} else if (bits_per_pixel == 16) { } else if (bits_per_pixel == 16) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "16-bpp BMP images are not supported.");
ERR_FAIL_V(ERR_UNAVAILABLE);
} }
// Image data (might be indexed) // Image data (might be indexed)
@ -73,7 +76,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
} else { // color } else { // color
data_len = width * height * 4; data_len = width * height * 4;
} }
ERR_FAIL_COND_V(data_len == 0, ERR_BUG); ERR_FAIL_COND_V_MSG(data_len == 0, ERR_BUG, "Couldn't parse the BMP image data.");
err = data.resize(data_len); err = data.resize(data_len);
PoolVector<uint8_t>::Write data_w = data.write(); PoolVector<uint8_t>::Write data_w = data.write();
@ -217,13 +220,15 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
// Info Header // Info Header
bmp_header.bmp_info_header.bmp_header_size = f->get_32(); bmp_header.bmp_info_header.bmp_header_size = f->get_32();
ERR_FAIL_COND_V(bmp_header.bmp_info_header.bmp_header_size < BITMAP_INFO_HEADER_MIN_SIZE, ERR_FILE_CORRUPT); ERR_FAIL_COND_V_MSG(bmp_header.bmp_info_header.bmp_header_size < BITMAP_INFO_HEADER_MIN_SIZE, ERR_FILE_CORRUPT,
vformat("Couldn't parse the BMP info header. The file is likely corrupt: %s", f->get_path()));
bmp_header.bmp_info_header.bmp_width = f->get_32(); bmp_header.bmp_info_header.bmp_width = f->get_32();
bmp_header.bmp_info_header.bmp_height = f->get_32(); bmp_header.bmp_info_header.bmp_height = f->get_32();
bmp_header.bmp_info_header.bmp_planes = f->get_16(); bmp_header.bmp_info_header.bmp_planes = f->get_16();
ERR_FAIL_COND_V(bmp_header.bmp_info_header.bmp_planes != 1, ERR_FILE_CORRUPT); ERR_FAIL_COND_V_MSG(bmp_header.bmp_info_header.bmp_planes != 1, ERR_FILE_CORRUPT,
vformat("Couldn't parse the BMP planes. The file is likely corrupt: %s", f->get_path()));
bmp_header.bmp_info_header.bmp_bit_count = f->get_16(); bmp_header.bmp_info_header.bmp_bit_count = f->get_16();
bmp_header.bmp_info_header.bmp_compression = f->get_32(); bmp_header.bmp_info_header.bmp_compression = f->get_32();
@ -238,10 +243,10 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
case BI_RLE4: case BI_RLE4:
case BI_CMYKRLE8: case BI_CMYKRLE8:
case BI_CMYKRLE4: { case BI_CMYKRLE4: {
// Stop parsing // Stop parsing.
String bmp_path = f->get_path();
f->close(); f->close();
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Compressed BMP files are not supported: " + bmp_path + "."); ERR_FAIL_V_MSG(ERR_UNAVAILABLE,
vformat("Compressed BMP files are not supported: %s", f->get_path()));
} break; } break;
} }
// Don't rely on sizeof(bmp_file_header) as structure padding // Don't rely on sizeof(bmp_file_header) as structure padding
@ -257,7 +262,8 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
if (bmp_header.bmp_info_header.bmp_bit_count <= 8) { if (bmp_header.bmp_info_header.bmp_bit_count <= 8) {
// Support 256 colors max // Support 256 colors max
color_table_size = 1 << bmp_header.bmp_info_header.bmp_bit_count; color_table_size = 1 << bmp_header.bmp_info_header.bmp_bit_count;
ERR_FAIL_COND_V(color_table_size == 0, ERR_BUG); ERR_FAIL_COND_V_MSG(color_table_size == 0, ERR_BUG,
vformat("Couldn't parse the BMP color table: %s", f->get_path()));
} }
PoolVector<uint8_t> bmp_color_table; PoolVector<uint8_t> bmp_color_table;