@@ -47,7 +47,6 @@ inline void bcdec_bc6h_half_u(const void *compressedBlock, void *decompressedBlo
4747static void decompress_image (BCdecFormat format, const void *src, void *dst, const uint64_t width, const uint64_t height) {
4848 const uint8_t *src_blocks = reinterpret_cast <const uint8_t *>(src);
4949 uint8_t *dec_blocks = reinterpret_cast <uint8_t *>(dst);
50- uint64_t src_pos = 0 , dst_pos = 0 ;
5150
5251#define DECOMPRESS_LOOP (func, block_size, color_bytesize, color_components ) \
5352 for (uint64_t y = 0 ; y < height; y += 4 ) { \
@@ -59,34 +58,96 @@ static void decompress_image(BCdecFormat format, const void *src, void *dst, con
5958 dst_pos += 3 * width * color_bytesize; \
6059 }
6160
62- switch (format) {
63- case BCdec_BC1: {
64- DECOMPRESS_LOOP (bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4 , 4 )
65- } break ;
66- case BCdec_BC2: {
67- DECOMPRESS_LOOP (bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4 , 4 )
68- } break ;
69- case BCdec_BC3: {
70- DECOMPRESS_LOOP (bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4 , 4 )
71- } break ;
72- case BCdec_BC4: {
73- DECOMPRESS_LOOP (bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1 , 1 )
74- } break ;
75- case BCdec_BC5: {
76- DECOMPRESS_LOOP (bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2 , 2 )
77- } break ;
78- case BCdec_BC6U: {
79- DECOMPRESS_LOOP (bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 )
80- } break ;
81- case BCdec_BC6S: {
82- DECOMPRESS_LOOP (bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 )
83- } break ;
84- case BCdec_BC7: {
85- DECOMPRESS_LOOP (bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4 , 4 )
86- } break ;
61+ #define DECOMPRESS_LOOP_SAFE (func, block_size, color_bytesize, color_components, output ) \
62+ for (uint64_t y = 0 ; y < height; y += 4 ) { \
63+ for (uint64_t x = 0 ; x < width; x += 4 ) { \
64+ const uint32_t yblock = MIN (height - y, 4ul ); \
65+ const uint32_t xblock = MIN (width - x, 4ul ); \
66+ \
67+ const bool incomplete = yblock < 4 && xblock < 4 ; \
68+ uint8_t *dec_out = incomplete ? output : &dec_blocks[y * 4 * width + x * color_bytesize]; \
69+ \
70+ func (&src_blocks[src_pos], dec_out, 4 * color_components); \
71+ src_pos += block_size; \
72+ \
73+ if (incomplete) { \
74+ for (uint32_t cy = 0 ; cy < yblock; cy++) { \
75+ for (uint32_t cx = 0 ; cx < xblock; cx++) { \
76+ memcpy (&dec_blocks[(y + cy) * 4 * width + (x + cx) * color_bytesize], &output[cy * 4 + cx * color_bytesize], color_bytesize); \
77+ } \
78+ } \
79+ } \
80+ } \
81+ }
82+
83+ if (width % 4 != 0 || height % 4 != 0 ) {
84+ uint64_t src_pos = 0 ;
85+
86+ uint8_t r8_output[4 * 4 ];
87+ uint8_t rg8_output[4 * 4 * 2 ];
88+ uint8_t rgba8_output[4 * 4 * 4 ];
89+ uint8_t rgbh_output[4 * 4 * 6 ];
90+
91+ switch (format) {
92+ case BCdec_BC1: {
93+ DECOMPRESS_LOOP_SAFE (bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4 , 4 , rgba8_output)
94+ } break ;
95+ case BCdec_BC2: {
96+ DECOMPRESS_LOOP_SAFE (bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4 , 4 , rgba8_output)
97+ } break ;
98+ case BCdec_BC3: {
99+ DECOMPRESS_LOOP_SAFE (bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4 , 4 , rgba8_output)
100+ } break ;
101+ case BCdec_BC4: {
102+ DECOMPRESS_LOOP_SAFE (bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1 , 1 , r8_output)
103+ } break ;
104+ case BCdec_BC5: {
105+ DECOMPRESS_LOOP_SAFE (bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2 , 2 , rg8_output)
106+ } break ;
107+ case BCdec_BC6U: {
108+ DECOMPRESS_LOOP_SAFE (bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 , rgbh_output)
109+ } break ;
110+ case BCdec_BC6S: {
111+ DECOMPRESS_LOOP_SAFE (bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 , rgbh_output)
112+ } break ;
113+ case BCdec_BC7: {
114+ DECOMPRESS_LOOP_SAFE (bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4 , 4 , rgba8_output)
115+ } break ;
116+ }
117+
118+ } else {
119+ uint64_t src_pos = 0 , dst_pos = 0 ;
120+
121+ switch (format) {
122+ case BCdec_BC1: {
123+ DECOMPRESS_LOOP (bcdec_bc1, BCDEC_BC1_BLOCK_SIZE, 4 , 4 )
124+ } break ;
125+ case BCdec_BC2: {
126+ DECOMPRESS_LOOP (bcdec_bc2, BCDEC_BC2_BLOCK_SIZE, 4 , 4 )
127+ } break ;
128+ case BCdec_BC3: {
129+ DECOMPRESS_LOOP (bcdec_bc3, BCDEC_BC3_BLOCK_SIZE, 4 , 4 )
130+ } break ;
131+ case BCdec_BC4: {
132+ DECOMPRESS_LOOP (bcdec_bc4, BCDEC_BC4_BLOCK_SIZE, 1 , 1 )
133+ } break ;
134+ case BCdec_BC5: {
135+ DECOMPRESS_LOOP (bcdec_bc5, BCDEC_BC5_BLOCK_SIZE, 2 , 2 )
136+ } break ;
137+ case BCdec_BC6U: {
138+ DECOMPRESS_LOOP (bcdec_bc6h_half_u, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 )
139+ } break ;
140+ case BCdec_BC6S: {
141+ DECOMPRESS_LOOP (bcdec_bc6h_half_s, BCDEC_BC6H_BLOCK_SIZE, 6 , 3 )
142+ } break ;
143+ case BCdec_BC7: {
144+ DECOMPRESS_LOOP (bcdec_bc7, BCDEC_BC7_BLOCK_SIZE, 4 , 4 )
145+ } break ;
146+ }
87147 }
88148
89149#undef DECOMPRESS_LOOP
150+ #undef DECOMPRESS_LOOP_SAFE
90151}
91152
92153void image_decompress_bcdec (Image *p_image) {
0 commit comments