1/* etcdec.h - v0.91 
2 provides functions to decompress blocks of ETC/EAC compressed images 
3 written by Sergii "iOrange" Kudlai in 2022 
4 
5 This library does not allocate memory and is trying to use as less stack as possible 
6 
7 The library was never optimized specifically for speed but for the overall size 
8 it has zero external dependencies and is not using any runtime functions 
9 
10 Supported ETC formats: 
11 ETC1 
12 ETC2_RGB 
13 ETC2_RGB_A1 ("punchthrough" alpha) 
14 ETC2_RGBA 
15 EAC_R11 
16 EAC_RG11 
17 
18 ETC1/ETC2_RGB/ETC2_RGB_A1/ETC2_RGBA are expected to decompress into 4*4 RGBA blocks 8bit per component (32bit pixel) 
19 EAC_R11/EAC_RG11 are expected to decompress into 4*4 R/RG blocks of either 32bit float or 16bit unsigned int16 per 
20 component (32/16bit (R11) and 64/32bit (RG11) pixel) 
21 
22 For more info, issues and suggestions please visit https://github.com/iOrange/etcdec 
23 
24 CREDITS: 
25 Vladimir Vondrus (@mosra) - fixes for platforms that define char as unsigned type 
26 
27 LICENSE: See end of file for license information. 
28*/ 
29 
30#ifndef ETCDEC_HEADER_INCLUDED 
31#define ETCDEC_HEADER_INCLUDED 
32#define ETCDEC_VERSION_MAJOR 0 
33#define ETCDEC_VERSION_MINOR 91 
34 
35/* if ETCDEC_STATIC causes problems, try defining ETCDECDEF to 'inline' or 'static inline' */ 
36#ifndef ETCDECDEF 
37#ifdef ETCDEC_STATIC 
38#define ETCDECDEF static 
39#else 
40#ifdef __cplusplus 
41#define ETCDECDEF extern "C" 
42#else 
43#define ETCDECDEF extern 
44#endif 
45#endif 
46#endif 
47 
48 
49/* Used information sources: 
50 
51 ETC1 compression 
52 https://registry.khronos.org/OpenGL/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt 
53 http://www.jacobstrom.com/publications/packman_sketch.pdf 
54 
55 ETC2/EAC compression 
56 https://registry.khronos.org/OpenGL/specs/gl/glspec43.core.pdf 
57*/ 
58 
59 
60#define ETCDEC_ETC_RGB_BLOCK_SIZE 8 
61#define ETCDEC_ETC_RGB_A1_BLOCK_SIZE 8 
62#define ETCDEC_EAC_RGBA_BLOCK_SIZE 16 
63#define ETCDEC_EAC_R11_BLOCK_SIZE 8 
64#define ETCDEC_EAC_RG11_BLOCK_SIZE 16 
65 
66#define ETCDEC_ETC_RGB_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*ETCDEC_ETC_RGB_BLOCK_SIZE) 
67#define ETCDEC_ETC_RGB_A1_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*ETCDEC_ETC_RGB_A1_BLOCK_SIZE) 
68#define ETCDEC_EAC_RGBA_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*ETCDEC_EAC_RGBA_BLOCK_SIZE) 
69#define ETCDEC_EAC_R11_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*ETCDEC_EAC_R11_BLOCK_SIZE) 
70#define ETCDEC_EAC_RG11_COMPRESSED_SIZE(w, h) ((((w)>>2)*((h)>>2))*ETCDEC_EAC_RG11_BLOCK_SIZE) 
71 
72ETCDECDEF void etcdec_etc_rgb(const void* compressedBlock, void* decompressedBlock, int destinationPitch); 
73ETCDECDEF void etcdec_etc_rgb_a1(const void* compressedBlock, void* decompressedBlock, int destinationPitch); 
74ETCDECDEF void etcdec_eac_rgba(const void* compressedBlock, void* decompressedBlock, int destinationPitch); 
75ETCDECDEF void etcdec_eac_r11_u16(const void* compressedBlock, void* decompressedBlock, int destinationPitch); 
76ETCDECDEF void etcdec_eac_rg11_u16(const void* compressedBlock, void* decompressedBlock, int destinationPitch); 
77ETCDECDEF void etcdec_eac_r11_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); 
78ETCDECDEF void etcdec_eac_rg11_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned); 
79 
80 
81#ifdef ETCDEC_IMPLEMENTATION 
82 
83/* http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend */ 
84static int etcdec__extend_sign(int val, int bits) { 
85 return (val << (32 - bits)) >> (32 - bits); 
86
87 
88static int etcdec__clamp_255(int value) { 
89 return value < 0 ? 0 : (value > 255 ? 255 : value); 
90
91static int etcdec__clamp_2047(int value) { 
92 return value < 0 ? 0 : (value > 2047 ? 2047 : value); 
93
94 
95 
96#ifndef ETCDEC_BSWAP64 
97static unsigned long long etcdec__bswap(unsigned long long x) { 
98 return (((x) & 0xFF00000000000000ull) >> 56) | 
99 (((x) & 0x00FF000000000000ull) >> 40) | 
100 (((x) & 0x0000FF0000000000ull) >> 24) | 
101 (((x) & 0x000000FF00000000ull) >> 8) | 
102 (((x) & 0x00000000FF000000ull) << 8) | 
103 (((x) & 0x0000000000FF0000ull) << 24) | 
104 (((x) & 0x000000000000FF00ull) << 40) | 
105 (((x) & 0x00000000000000FFull) << 56); 
106
107 
108#define ETCDEC_BSWAP64(x) etcdec__bswap(x) 
109#endif /* ETCDEC_BSWAP64 */ 
110 
111static void etcdec__decompress_legacy_etc_mode(unsigned long long block, 
112 int r0, int g0, int b0, 
113 int r1, int g1, int b1, 
114 unsigned char* decompressed, 
115 int isOpaque, 
116 int destinationPitch) { 
117 int flipBit, codeWord0, codeWord1; 
118 int i, j, x0, y0, x1, y1, m, idx; 
119 const int (*modifiersTablePtr)[4]; 
120 
121 /* already remapped so we can just use pixel indices "as-is" */ 
122 static int modifierTableRemappedOpaque[8][4] = { 
123 { 2, 8, -2, -8 }, 
124 { 5, 17, -5, -17 }, 
125 { 9, 29, -9, -29 }, 
126 { 13, 42, -13, -42 }, 
127 { 18, 60, -18, -60 }, 
128 { 24, 80, -24, -80 }, 
129 { 33, 106, -33, -106 }, 
130 { 47, 183, -47, -183
131 }; 
132 
133 static int modifierTableRemappedTransparent[8][4] = { 
134 { 0, 8, 0, -8 }, 
135 { 0, 17, 0, -17 }, 
136 { 0, 29, 0, -29 }, 
137 { 0, 42, 0, -42 }, 
138 { 0, 60, 0, -60 }, 
139 { 0, 80, 0, -80 }, 
140 { 0, 106, 0, -106 }, 
141 { 0, 183, 0, -183
142 }; 
143 
144 flipBit = (block & 0x100000000ull) != 0
145 
146 codeWord0 = (block >> 37) & 0x7
147 codeWord1 = (block >> 34) & 0x7
148 
149 modifiersTablePtr = isOpaque ? modifierTableRemappedOpaque : modifierTableRemappedTransparent; 
150 
151 /* now decode both blocks, using proper orientation based on flipBit */ 
152 for (i = 0; i < 2; ++i) { 
153 for (j = 0; j < 4; ++j) { 
154 x0 = flipBit ? i : j; 
155 x1 = flipBit ? (i + 2) : j; 
156 y0 = flipBit ? j : i; 
157 y1 = flipBit ? j : (i + 2); 
158 
159 /* if isOpaque == 0 and idx is "msb=1 & lsb=0" (== 2) -> pixel is completely transparent */ 
160 
161 /* block A */ 
162 m = x0 + y0 * 4
163 idx = (((block >> (m + 16)) & 1) << 1) | ((block >> m) & 1); 
164 m = (x0 * destinationPitch) + (y0 * 4); 
165 if (isOpaque || idx != 2) { 
166 decompressed[m + 0] = (unsigned char)etcdec__clamp_255(r0 + modifiersTablePtr[codeWord0][idx]); 
167 decompressed[m + 1] = (unsigned char)etcdec__clamp_255(g0 + modifiersTablePtr[codeWord0][idx]); 
168 decompressed[m + 2] = (unsigned char)etcdec__clamp_255(b0 + modifiersTablePtr[codeWord0][idx]); 
169 decompressed[m + 3] = 0xFF
170 } else
171 *((unsigned int*)(decompressed + m)) = 0u
172
173 
174 // block B 
175 m = x1 + y1 * 4
176 idx = (((block >> (m + 16)) & 1) << 1) | ((block >> m) & 1); 
177 m = (x1 * destinationPitch) + (y1 * 4); 
178 if (isOpaque || idx != 2) { 
179 decompressed[m + 0] = (unsigned char)etcdec__clamp_255(r1 + modifiersTablePtr[codeWord1][idx]); 
180 decompressed[m + 1] = (unsigned char)etcdec__clamp_255(g1 + modifiersTablePtr[codeWord1][idx]); 
181 decompressed[m + 2] = (unsigned char)etcdec__clamp_255(b1 + modifiersTablePtr[codeWord1][idx]); 
182 decompressed[m + 3] = 0xFF
183 } else
184 *((unsigned int*)(decompressed + m)) = 0u
185
186
187
188
189 
190static void etcdec__decompress_etc_mode_t_h(unsigned long long block, 
191 int mode, 
192 unsigned char* decompressed, 
193 int isOpaque, 
194 int destinationPitch) { 
195 int r0, g0, b0, r1, g1, b1; 
196 int ra, rb, ga, gb, ba, bb, da, db, dist; 
197 int i, j, k, idx; 
198 unsigned int paintColors[4]; /* 0xAABBGGRR */ 
199 
200 static char distanceTable[8] = { 3, 6, 11, 16, 23, 32, 41, 64 }; 
201 
202 if (mode == 1) { /* "T" mode */ 
203 ra = (block >> 59) & 0x3
204 rb = (block >> 56) & 0x3
205 g0 = (block >> 52) & 0xF
206 b0 = (block >> 48) & 0xF
207 r1 = (block >> 44) & 0xF
208 g1 = (block >> 40) & 0xF
209 b1 = (block >> 36) & 0xF
210 da = (block >> 34) & 0x3
211 db = (block >> 32) & 0x1
212 
213 r0 = (ra << 2) | rb; 
214 } else { /* "H" mode */ 
215 r0 = (block >> 59) & 0xF
216 ga = (block >> 56) & 0x7
217 gb = (block >> 52) & 0x1
218 ba = (block >> 51) & 0x1
219 bb = (block >> 47) & 0x7
220 r1 = (block >> 43) & 0xF
221 g1 = (block >> 39) & 0xF
222 b1 = (block >> 35) & 0xF
223 da = (block >> 34) & 0x1
224 db = (block >> 32) & 0x1
225 
226 g0 = (ga << 1) | gb; 
227 b0 = (ba << 3) | bb; 
228
229 
230 /* These four bit values are extended to RGB888 by replicating 
231 the four higher order bits in the four lower order bits. */ 
232 r0 = (r0 << 4) | r0; 
233 g0 = (g0 << 4) | g0; 
234 b0 = (b0 << 4) | b0; 
235 r1 = (r1 << 4) | r1; 
236 g1 = (g1 << 4) | g1; 
237 b1 = (b1 << 4) | b1; 
238 
239 if (mode == 1) { /* "T" mode */ 
240 dist = (da << 1) | db; 
241 dist = distanceTable[dist]; 
242 
243 paintColors[0] = 0xFF000000 | (b0 << 16) | (g0 << 8) | r0; 
244 paintColors[2] = 0xFF000000 | (b1 << 16) | (g1 << 8) | r1; 
245 paintColors[1] = 0xFF000000 | (etcdec__clamp_255(b1 + dist) << 16
246 | (etcdec__clamp_255(g1 + dist) << 8
247 | etcdec__clamp_255(r1 + dist); 
248 paintColors[3] = 0xFF000000 | (etcdec__clamp_255(b1 - dist) << 16
249 | (etcdec__clamp_255(g1 - dist) << 8
250 | etcdec__clamp_255(r1 - dist); 
251 } else { /* "H" mode */ 
252 dist = ((r0 << 16) | (g0 << 8) | b0) >= ((r1 << 16) | (g1 << 8) | b1) ? 1 : 0
253 dist |= (da << 2) | (db << 1); 
254 dist = distanceTable[dist]; 
255 
256 paintColors[0] = 0xFF000000 | (etcdec__clamp_255(b0 + dist) << 16
257 | (etcdec__clamp_255(g0 + dist) << 8
258 | etcdec__clamp_255(r0 + dist); 
259 paintColors[1] = 0xFF000000 | (etcdec__clamp_255(b0 - dist) << 16
260 | (etcdec__clamp_255(g0 - dist) << 8
261 | etcdec__clamp_255(r0 - dist); 
262 paintColors[2] = 0xFF000000 | (etcdec__clamp_255(b1 + dist) << 16
263 | (etcdec__clamp_255(g1 + dist) << 8
264 | etcdec__clamp_255(r1 + dist); 
265 paintColors[3] = 0xFF000000 | (etcdec__clamp_255(b1 - dist) << 16
266 | (etcdec__clamp_255(g1 - dist) << 8
267 | etcdec__clamp_255(r1 - dist); 
268
269 
270 for (i = 0; i < 4; ++i) { 
271 for (j = 0; j < 4; ++j) { 
272 k = i + j * 4
273 idx = (((block >> (k + 16)) & 1) << 1) | ((block >> k) & 1); 
274 /* if isOpaque == 0 and idx is "msb=1 & lsb=0" (== 2) -> pixel is completely transparent */ 
275 if (isOpaque || idx != 2) { 
276 ((unsigned int*)decompressed)[j] = paintColors[idx]; 
277 } else
278 ((unsigned int*)decompressed)[j] = 0u
279
280
281 
282 decompressed += destinationPitch; 
283
284
285 
286static void etcdec__decompress_etc_mode_planar(unsigned long long block, unsigned char* decompressed, int destinationPitch) { 
287 int ro, go, bo, rh, gh, bh, rv, gv, bv; 
288 int go1, go2, bo1, bo2, bo3, rh1, rh2; 
289 int i, j; 
290 
291 ro = (block >> 57) & 0x3F
292 go1 = (block >> 56) & 0x01
293 go2 = (block >> 49) & 0x3F
294 bo1 = (block >> 48) & 0x01
295 bo2 = (block >> 43) & 0x03
296 bo3 = (block >> 39) & 0x07
297 rh1 = (block >> 34) & 0x1F
298 rh2 = (block >> 32) & 0x01
299 gh = (block >> 25) & 0x7F
300 bh = (block >> 19) & 0x3F
301 rv = (block >> 13) & 0x3F
302 gv = (block >> 6) & 0x7F
303 bv = (block >> 0) & 0x3F
304 
305 go = (go1 << 6) | go2; 
306 bo = (bo1 << 5) | (bo2 << 3) | bo3; 
307 rh = (rh1 << 1) | rh2; 
308 
309 ro = (ro << 2) | (ro >> 4); 
310 rh = (rh << 2) | (rh >> 4); 
311 rv = (rv << 2) | (rv >> 4); 
312 go = (go << 1) | (go >> 6); 
313 gh = (gh << 1) | (gh >> 6); 
314 gv = (gv << 1) | (gv >> 6); 
315 bo = (bo << 2) | (bo >> 4); 
316 bh = (bh << 2) | (bh >> 4); 
317 bv = (bv << 2) | (bv >> 4); 
318 
319 /* With three base colors in RGB888 format, the color of each 
320 pixel can then be determined as: 
321 R(x, y) = x * (RH − RO) / 4.0 + y * (RV − RO) / 4.0 + RO 
322 G(x, y) = x * (GH − GO) / 4.0 + y * (GV − GO) / 4.0 + GO 
323 B(x, y) = x * (BH − BO) / 4.0 + y * (BV − BO) / 4.0 + BO */ 
324 for (i = 0; i < 4; ++i) { 
325 for (j = 0; j < 4; ++j) { 
326 decompressed[(j * 4) + 0] = (unsigned char)etcdec__clamp_255((j * (rh - ro) + i * (rv - ro) + (ro << 2) + 2) >> 2); 
327 decompressed[(j * 4) + 1] = (unsigned char)etcdec__clamp_255((j * (gh - go) + i * (gv - go) + (go << 2) + 2) >> 2); 
328 decompressed[(j * 4) + 2] = (unsigned char)etcdec__clamp_255((j * (bh - bo) + i * (bv - bo) + (bo << 2) + 2) >> 2); 
329 decompressed[(j * 4) + 3] = 0xFF
330
331 
332 decompressed += destinationPitch; 
333
334
335 
336static void etcdec__decompress_etc_block(const void* compressedBlock, void* decompressedBlock, int isPunchthrough, int destinationPitch) { 
337 unsigned long long block; 
338 int diffBit, newMode; 
339 int r0, g0, b0, r1, g1, b1; 
340 unsigned char* decompressed; 
341 
342 block = ETCDEC_BSWAP64(((unsigned long long*)compressedBlock)[0]); 
343 decompressed = (unsigned char*)decompressedBlock; 
344 
345 /* if isPunchthrough == TRUE -> this is actually an 'opaque' bit */ 
346 diffBit = (block & 0x200000000ull) != 0
347 
348 newMode = 0; /* assume legacy mode by default */ 
349 
350 if (!isPunchthrough && !diffBit) { /* "individual" mode */ 
351 r0 = (block >> 60) & 0xF
352 r1 = (block >> 56) & 0xF
353 g0 = (block >> 52) & 0xF
354 g1 = (block >> 48) & 0xF
355 b0 = (block >> 44) & 0xF
356 b1 = (block >> 40) & 0xF
357 
358 /* These four bit values are extended to RGB888 by replicating 
359 the four higher order bits in the four lower order bits. */ 
360 r0 = (r0 << 4) | r0; 
361 g0 = (g0 << 4) | g0; 
362 b0 = (b0 << 4) | b0; 
363 r1 = (r1 << 4) | r1; 
364 g1 = (g1 << 4) | g1; 
365 b1 = (b1 << 4) | b1; 
366 } else { /* "differential" mode */ 
367 r0 = (block >> 59) & 0x1F
368 r1 = r0 + etcdec__extend_sign((block >> 56) & 0x7, 3); 
369 g0 = (block >> 51) & 0x1F
370 g1 = g0 + etcdec__extend_sign((block >> 48) & 0x7, 3); 
371 b0 = (block >> 43) & 0x1F
372 b1 = b0 + etcdec__extend_sign((block >> 40) & 0x7, 3); 
373 
374 if (r1 < 0 || r1 > 31) { 
375 /* First, R and dR are added, and if the sum is not 
376 within the interval[0, 31], the "T" mode is selected */ 
377 newMode = 1
378 } else if (g1 < 0 || g1 > 31) { 
379 /* Otherwise, if the sum of Gand dG is outside 
380 the interval[0, 31], the "H" mode is selected */ 
381 newMode = 2
382 } else if (b1 < 0 || b1 > 31) { 
383 /* Otherwise, if the sum of Band dB is outside 
384 of the interval[0, 31], the "planar" mode is selected */ 
385 newMode = 3
386 } else
387 /* Finally the "differential" mode is selected */ 
388 
389 /* These five-bit codewords are extended to RGB888 by replicating 
390 the top three highest order bits to the three lowest order bits. */ 
391 r0 = (r0 << 3) | (r0 >> 2); 
392 g0 = (g0 << 3) | (g0 >> 2); 
393 b0 = (b0 << 3) | (b0 >> 2); 
394 r1 = (r1 << 3) | (r1 >> 2); 
395 g1 = (g1 << 3) | (g1 >> 2); 
396 b1 = (b1 << 3) | (b1 >> 2); 
397
398
399 
400 if (!newMode) { /* legacy mode: ETC1 & ETC2 */ 
401 etcdec__decompress_legacy_etc_mode(block, r0, g0, b0, r1, g1, b1, decompressed, !isPunchthrough || diffBit, destinationPitch); 
402 } else if (newMode < 3) { /* ETC2 "T" and "H" modes */ 
403 etcdec__decompress_etc_mode_t_h(block, newMode, decompressed, !isPunchthrough || diffBit, destinationPitch); 
404 } else { /* ETC2 "planar" mode */ 
405 etcdec__decompress_etc_mode_planar(block, decompressed, destinationPitch); 
406
407
408 
409static void etcdec__decompress_eac_block(const void* compressedBlock, void* decompressedBlock, int is11Bit, int destinationPitch, int pixelSize) { 
410 unsigned long long block; 
411 unsigned char* decompressed; 
412 int baseCodeword, multiplier, modifier, idx; 
413 int i, j, k; 
414 const signed char* modifiersPtr; 
415 
416 static signed char modifierTable[16][8] = { 
417 { -3, -6, -9, -15, 2, 5, 8, 14 }, 
418 { -3, -7, -10, -13, 2, 6, 9, 12 }, 
419 { -2, -5, -8, -13, 1, 4, 7, 12 }, 
420 { -2, -4, -6, -13, 1, 3, 5, 12 }, 
421 { -3, -6, -8, -12, 2, 5, 7, 11 }, 
422 { -3, -7, -9, -11, 2, 6, 8, 10 }, 
423 { -4, -7, -8, -11, 3, 6, 7, 10 }, 
424 { -3, -5, -8, -11, 2, 4, 7, 10 }, 
425 { -2, -6, -8, -10, 1, 5, 7, 9 }, 
426 { -2, -5, -8, -10, 1, 4, 7, 9 }, 
427 { -2, -4, -8, -10, 1, 3, 7, 9 }, 
428 { -2, -5, -7, -10, 1, 4, 6, 9 }, 
429 { -3, -4, -7, -10, 2, 3, 6, 9 }, 
430 { -1, -2, -3, -10, 0, 1, 2, 9 }, 
431 { -4, -6, -8, -9, 3, 5, 7, 8 }, 
432 { -3, -5, -7, -9, 2, 4, 6, 8
433 }; 
434 
435 block = ETCDEC_BSWAP64(((unsigned long long*)compressedBlock)[0]); 
436 decompressed = (unsigned char*)decompressedBlock; 
437 baseCodeword = (block >> 56) & 0xFF
438 multiplier = (block >> 52) & 0xF
439 modifiersPtr = modifierTable[(block >> 48) & 0xF]; 
440 
441 for (i = 0; i < 4; ++i) { 
442 for (j = 0; j < 4; ++j) { 
443 idx = (block >> ((15 - (j * 4 + i)) * 3)) & 0x7
444 modifier = modifiersPtr[idx]; 
445 
446 if (is11Bit) { 
447 /* EAC R11/RG11 */ 
448 /* If the multiplier value is zero, we should set the multiplier to 1.0/8.0 */ 
449 /* so that the "multiplier * 8" will resolve to 1 */ 
450 k = etcdec__clamp_2047((baseCodeword * 8 + 4) + (modifier * (multiplier ? multiplier * 8 : 1))); 
451 
452 /* Now just extending the 11-bits value to 16-bits for convenience */ 
453 *((unsigned short*)(decompressed + (j * pixelSize))) = (unsigned short)((k << 5) | (k >> 6)); 
454 } else
455 /* EAC ETC2 Alpha channel */ 
456 decompressed[j * pixelSize] = (unsigned char)etcdec__clamp_255(baseCodeword + (modifier * multiplier)); 
457
458
459 
460 decompressed += destinationPitch; 
461
462
463 
464 
465ETCDECDEF void etcdec_etc_rgb(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { 
466 etcdec__decompress_etc_block(compressedBlock, decompressedBlock, 0, destinationPitch); 
467
468 
469ETCDECDEF void etcdec_etc_rgb_a1(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { 
470 etcdec__decompress_etc_block(compressedBlock, decompressedBlock, 1, destinationPitch); 
471
472 
473ETCDECDEF void etcdec_eac_rgba(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { 
474 /* first half of the block (64 bits) is an Alpha (EAC 8 bits) compressed data */ 
475 /* second half of the block (64 bits) is just an ETC2_RGB compressed data */ 
476 etcdec__decompress_etc_block(((char*)compressedBlock) + 8, decompressedBlock, 0, destinationPitch); 
477 etcdec__decompress_eac_block(compressedBlock, ((char*)decompressedBlock) + 3, 0, destinationPitch, 4); 
478
479 
480ETCDECDEF void etcdec_eac_r11_u16(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { 
481 etcdec__decompress_eac_block(compressedBlock, decompressedBlock, 1, destinationPitch, 2); 
482
483 
484ETCDECDEF void etcdec_eac_rg11_u16(const void* compressedBlock, void* decompressedBlock, int destinationPitch) { 
485 etcdec__decompress_eac_block(compressedBlock, decompressedBlock, 1, destinationPitch, 4); 
486 etcdec__decompress_eac_block(((char*)compressedBlock) + 8, ((char*)decompressedBlock) + 2, 1, destinationPitch, 4); 
487
488 
489ETCDECDEF void etcdec_eac_r11_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { 
490 unsigned short block[16]; 
491 unsigned char* decompressed; 
492 const unsigned short* b; 
493 int i, j; 
494 short s; 
495 
496 etcdec_eac_r11_u16(compressedBlock, block, 4 * 2); 
497 b = block; 
498 decompressed = (unsigned char*)decompressedBlock; 
499 for (i = 0; i < 4; ++i) { 
500 for (j = 0; j < 4; ++j, ++b) { 
501 if (isSigned) { 
502 s = (short)b[0]; 
503 *((float*)(decompressed + j * 4)) = (s < 0 ? ((float)s / 32768.0f) : ((float)s / 32767.0f)); 
504 } else
505 *((float*)(decompressed + j * 4)) = (float)b[0] / 65535.0f
506
507
508 decompressed += destinationPitch; 
509
510
511 
512ETCDECDEF void etcdec_eac_rg11_float(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int isSigned) { 
513 unsigned short block[16*2]; 
514 unsigned char* decompressed; 
515 const unsigned short* b; 
516 int i, j; 
517 short sr, sg; 
518 
519 etcdec_eac_rg11_u16(compressedBlock, block, 4 * 4); 
520 b = block; 
521 decompressed = (unsigned char*)decompressedBlock; 
522 for (i = 0; i < 4; ++i) { 
523 for (j = 0; j < 4; ++j, b += 2) { 
524 if (isSigned) { 
525 sr = (short)b[0]; 
526 sg = (short)b[1]; 
527 *((float*)(decompressed + j * 8 + 0)) = (sr < 0 ? ((float)sr / 32768.0f) : ((float)sr / 32767.0f)); 
528 *((float*)(decompressed + j * 8 + 4)) = (sg < 0 ? ((float)sg / 32768.0f) : ((float)sg / 32767.0f)); 
529
530 else
531 *((float*)(decompressed + j * 8 + 0)) = (float)b[0] / 65535.0f
532 *((float*)(decompressed + j * 8 + 4)) = (float)b[1] / 65535.0f
533
534
535 decompressed += destinationPitch; 
536
537
538 
539#endif /* ETCDEC_IMPLEMENTATION */ 
540 
541#endif /* ETCDEC_HEADER_INCLUDED */ 
542 
543/* LICENSE: 
544 
545This software is available under 2 licenses -- choose whichever you prefer. 
546 
547------------------------------------------------------------------------------ 
548ALTERNATIVE A - MIT License 
549 
550Copyright (c) 2022 Sergii Kudlai 
551 
552Permission is hereby granted, free of charge, to any person obtaining a copy of 
553this software and associated documentation files (the "Software"), to deal in 
554the Software without restriction, including without limitation the rights to 
555use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
556of the Software, and to permit persons to whom the Software is furnished to do 
557so, subject to the following conditions: 
558 
559The above copyright notice and this permission notice shall be included in all 
560copies or substantial portions of the Software. 
561 
562THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
563IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
564FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
565AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
566LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
567OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
568SOFTWARE. 
569 
570------------------------------------------------------------------------------ 
571ALTERNATIVE B - The Unlicense 
572 
573This is free and unencumbered software released into the public domain. 
574 
575Anyone is free to copy, modify, publish, use, compile, sell, or 
576distribute this software, either in source code form or as a compiled 
577binary, for any purpose, commercial or non-commercial, and by any 
578means. 
579 
580In jurisdictions that recognize copyright laws, the author or authors 
581of this software dedicate any and all copyright interest in the 
582software to the public domain. We make this dedication for the benefit 
583of the public at large and to the detriment of our heirs and 
584successors. We intend this dedication to be an overt act of 
585relinquishment in perpetuity of all present and future rights to this 
586software under copyright law. 
587 
588THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
589EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
590MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
591IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 
592OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
593ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
594OTHER DEALINGS IN THE SOFTWARE. 
595 
596For more information, please refer to <https://unlicense.org> 
597 
598*/ 
599