Skip to content

Commit e857e81

Browse files
committed
Merge pull request godotengine#97873 from BlueCube3310/image-decompress-4-fix
Fix decompressing textures with dimensions that are not multiples of 4
2 parents bb20444 + a60195e commit e857e81

File tree

1 file changed

+22
-13
lines changed

1 file changed

+22
-13
lines changed

modules/bcdec/image_decompress_bcdec.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,20 @@ static void decompress_image(BCdecFormat format, const void *src, void *dst, con
9292
void image_decompress_bcdec(Image *p_image) {
9393
uint64_t start_time = OS::get_singleton()->get_ticks_msec();
9494

95-
int w = p_image->get_width();
96-
int h = p_image->get_height();
95+
int width = p_image->get_width();
96+
int height = p_image->get_height();
97+
98+
// Compressed images' dimensions should be padded to the upper multiple of 4.
99+
// If they aren't, they need to be realigned (the actual data is correctly padded though).
100+
if (width % 4 != 0 || height % 4 != 0) {
101+
int new_width = width + (4 - (width % 4));
102+
int new_height = height + (4 - (height % 4));
103+
104+
print_verbose(vformat("Compressed image's dimensions are not multiples of 4 (%dx%d), aligning to (%dx%d)", width, height, new_width, new_height));
105+
106+
width = new_width;
107+
height = new_height;
108+
}
97109

98110
Image::Format source_format = p_image->get_format();
99111
Image::Format target_format = Image::FORMAT_MAX;
@@ -148,30 +160,27 @@ void image_decompress_bcdec(Image *p_image) {
148160
}
149161

150162
int mm_count = p_image->get_mipmap_count();
151-
int64_t target_size = Image::get_image_data_size(w, h, target_format, p_image->has_mipmaps());
163+
int64_t target_size = Image::get_image_data_size(width, height, target_format, p_image->has_mipmaps());
152164

165+
// Decompressed data.
153166
Vector<uint8_t> data;
154167
data.resize(target_size);
168+
uint8_t *wb = data.ptrw();
155169

170+
// Source data.
156171
const uint8_t *rb = p_image->get_data().ptr();
157-
uint8_t *wb = data.ptrw();
158172

159173
// Decompress mipmaps.
160174
for (int i = 0; i <= mm_count; i++) {
161-
int64_t src_ofs = 0, mipmap_size = 0;
162175
int mipmap_w = 0, mipmap_h = 0;
163-
p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h);
164-
165-
int64_t dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i);
176+
int64_t src_ofs = Image::get_image_mipmap_offset_and_dimensions(width, height, source_format, i, mipmap_w, mipmap_h);
177+
int64_t dst_ofs = Image::get_image_mipmap_offset(width, height, target_format, i);
166178
decompress_image(bcdec_format, rb + src_ofs, wb + dst_ofs, mipmap_w, mipmap_h);
167-
168-
w >>= 1;
169-
h >>= 1;
170179
}
171180

172-
p_image->set_data(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);
181+
p_image->set_data(width, height, p_image->has_mipmaps(), target_format, data);
173182

174-
// Swap channels if necessary.
183+
// Swap channels if the format is using a channel swizzle.
175184
if (source_format == Image::FORMAT_DXT5_RA_AS_RG) {
176185
p_image->convert_ra_rgba8_to_rg();
177186
}

0 commit comments

Comments
 (0)