// using EtcPack to decode ETC1 void CodecETC1_Decode(TexDecodeTask *task) { byte *data, *stream; int x, y, w, h; size_t size; w = task->image->width; h = task->image->height; size = w * h * task->image->bpp; data = (byte *)mem_alloc(size); stream = task->pixeldata; for (y = 0; y < h / 4; y++) { for (x = 0; x < w / 4; x++) { // etcpack path unsigned int block1, block2; block1 = 0; block1 |= stream[0]; block1 = block1 << 8; block1 |= stream[1]; block1 = block1 << 8; block1 |= stream[2]; block1 = block1 << 8; block1 |= stream[3]; block2 = 0; block2 |= stream[4]; block2 = block2 << 8; block2 |= stream[5]; block2 = block2 << 8; block2 |= stream[6]; block2 = block2 << 8; block2 |= stream[7]; stream += 8; // ETC2 is backwards compatible, which means that an ETC2-capable decompressor // can also handle old ETC1 textures without any problems. etcpack_decompressBlockETC2c(block1, block2, data, w, h, x*4, y*4, task->image->bpp); } } Image_StoreUnalignedData(task->image, data, size); free(data); task->image->colorSwap = false; }
// using EtcPack to decode ETC2 void CodecETC2_Decode(TexDecodeTask *task) { byte *data, *stream, rgba[4*4*4], *lb; unsigned int block1, block2; int x, y, w, h, bpp; int lx, ly, lw, lh; // init w = task->image->width; h = task->image->height; bpp = task->image->bpp; data = (byte *)mem_alloc(w * h * bpp); stream = task->pixeldata; // decode if (task->format->block == &B_ETC2) { for (y = 0; y < h; y+=4) { for (x = 0; x < w; x+=4) { readColorBlockETC(&stream, block1, block2); etcpack_decompressBlockETC2c(block1, block2, rgba, 4, 4, 0, 0, 4); lb = rgba; lh = min(y + 4, h) - y; lw = min(x + 4, w) - x; for (ly = 0; ly < lh; ly++,lb+=4*4) for(lx = 0; lx < lw; lx++) memcpy(data + (w*(y + ly) + x + lx)*bpp, lb + lx*4, 3); } } } else if (task->format->block == &B_ETC2A) { for (y = 0; y < h; y+=4) { for (x = 0; x < w; x+=4) { // EAC block + ETC2 RGB block etcpack_decompressBlockAlphaC(stream, rgba+3, 4, 4, 0, 0, 4); stream += 8; readColorBlockETC(&stream, block1, block2); etcpack_decompressBlockETC2c(block1, block2, rgba, 4, 4, 0, 0, 4); lb = rgba; lh = min(y + 4, h) - y; lw = min(x + 4, w) - x; for (ly = 0; ly < lh; ly++,lb+=4*4) for(lx = 0; lx < lw; lx++) memcpy(data + (w*(y + ly) + x + lx)*bpp, lb + lx*4, 4); } } } else if (task->format->block == &B_ETC2A1) { for (y = 0; y < h; y+=4) { for (x = 0; x < w; x+=4) { // ETC2 RGB/punchthrough alpha block readColorBlockETC(&stream, block1, block2); etcpack_decompressBlockETC21BitAlphaC(block1, block2, rgba, NULL, 4, 4, 0, 0, 4); lb = rgba; lh = min(y + 4, h) - y; lw = min(x + 4, w) - x; for (ly = 0; ly < lh; ly++,lb+=4*4) for(lx = 0; lx < lw; lx++) memcpy(data + (w*(y + ly) + x + lx)*bpp, lb + lx*4, 4); } } } else Error("CodecETC2_Decode: block %s not supported\n", task->format->block->name); // store decoded image Image_StoreUnalignedData(task->image, data, w*h*bpp); free(data); task->image->colorSwap = false; }