From 8db1a9b9ca81e07a2c784c55848f6106a4069277 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 11 Mar 2021 22:40:01 +0100 Subject: [PATCH] Add support for exporting compressed textures in Editor on Linux using detex lib --- .../Tools/TextureTool/TextureTool.Build.cs | 5 + .../Tools/TextureTool/TextureTool.stb.cpp | 134 +- Source/ThirdParty/detex/LICENSE | 14 + Source/ThirdParty/detex/decompress-bc.cpp | 241 ++++ Source/ThirdParty/detex/detex.Build.cs | 21 + Source/ThirdParty/detex/detex.h | 1194 +++++++++++++++++ Source/ThirdParty/detex/division-tables.cpp | 512 +++++++ 7 files changed, 2105 insertions(+), 16 deletions(-) create mode 100644 Source/ThirdParty/detex/LICENSE create mode 100644 Source/ThirdParty/detex/decompress-bc.cpp create mode 100644 Source/ThirdParty/detex/detex.Build.cs create mode 100644 Source/ThirdParty/detex/detex.h create mode 100644 Source/ThirdParty/detex/division-tables.cpp diff --git a/Source/Engine/Tools/TextureTool/TextureTool.Build.cs b/Source/Engine/Tools/TextureTool/TextureTool.Build.cs index fe5862318..55da51bf5 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.Build.cs +++ b/Source/Engine/Tools/TextureTool/TextureTool.Build.cs @@ -47,6 +47,11 @@ public class TextureTool : EngineModule { options.PrivateDependencies.Add("stb"); options.SourceFiles.Add(Path.Combine(FolderPath, "TextureTool.stb.cpp")); + if (options.Target.IsEditor) + { + // Use helper lib for decompression + options.PrivateDependencies.Add("detex"); + } } options.PublicDefinitions.Add("COMPILE_WITH_TEXTURE_TOOL"); diff --git a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp index 7e7229048..cf018776e 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp @@ -44,6 +44,12 @@ #define STB_DXT_IMPLEMENTATION #include +#if USE_EDITOR + +#include + +#endif + static void stbWrite(void* context, void* data, int size) { auto file = (FileWriteStream*)context; @@ -57,46 +63,142 @@ bool TextureTool::ExportTextureStb(ImageType type, const StringView& path, const LOG(Warning, "Exporting texture arrays and cubemaps is not supported by stb library."); } + TextureData const* texture = &textureData; + +#if USE_EDITOR + // Handle compressed textures + TextureData decompressed; + if (PixelFormatExtensions::IsCompressed(textureData.Format)) + { + decompressed.Format = PixelFormatExtensions::IsSRGB(textureData.Format) ? PixelFormat::R8G8B8A8_UNorm_sRGB : PixelFormat::R8G8B8A8_UNorm; + decompressed.Width = textureData.Width; + decompressed.Height = textureData.Height; + decompressed.Depth = textureData.Depth; + decompressed.Items.Resize(1); + decompressed.Items[0].Mips.Resize(1); + + auto decompressedData = decompressed.GetData(0, 0); + decompressedData->RowPitch = textureData.Width * sizeof(Color32); + decompressedData->Lines = textureData.Height; + decompressedData->DepthPitch = decompressedData->RowPitch * decompressedData->Lines; + decompressedData->Data.Allocate(decompressedData->DepthPitch); + + Color32 colors[16]; + int32 blocksWidth = textureData.Width / 4; + int32 blocksHeight = textureData.Height / 4; + const auto blocksData = texture->GetData(0, 0); + byte* decompressedBytes = decompressedData->Data.Get(); + + switch (textureData.Format) + { + case PixelFormat::BC1_UNorm: + case PixelFormat::BC1_UNorm_sRGB: + { + for (int32 yBlock = 0; yBlock < blocksHeight; yBlock++) + { + for (int32 xBlock = 0; xBlock < blocksWidth; xBlock++) + { + const byte* block = blocksData->Data.Get() + yBlock * 4 * blocksData->RowPitch + xBlock * 8; + detexDecompressBlockBC1(block, 0, 0, (byte*)&colors); + for (int32 y = 0; y < 4; y++) + { + for (int32 x = 0; x < 4; x++) + { + *((Color32*)decompressedBytes + (yBlock * 4 + y) * textureData.Width + (xBlock * 4 + x)) = colors[y * 4 + x]; + } + } + } + } + break; + } + case PixelFormat::BC2_UNorm: + case PixelFormat::BC2_UNorm_sRGB: + { + for (int32 yBlock = 0; yBlock < blocksHeight; yBlock++) + { + for (int32 xBlock = 0; xBlock < blocksWidth; xBlock++) + { + const byte* block = blocksData->Data.Get() + yBlock * 4 * blocksData->RowPitch + xBlock * 16; + detexDecompressBlockBC2(block, 0, 0, (byte*)&colors); + for (int32 y = 0; y < 4; y++) + { + for (int32 x = 0; x < 4; x++) + { + *((Color32*)decompressedBytes + (yBlock * 4 + y) * textureData.Width + (xBlock * 4 + x)) = colors[y * 4 + x]; + } + } + } + } + break; + } + case PixelFormat::BC3_UNorm: + case PixelFormat::BC3_UNorm_sRGB: + { + for (int32 yBlock = 0; yBlock < blocksHeight; yBlock++) + { + for (int32 xBlock = 0; xBlock < blocksWidth; xBlock++) + { + const byte* block = blocksData->Data.Get() + yBlock * 4 * blocksData->RowPitch + xBlock * 16; + detexDecompressBlockBC3(block, 0, 0, (byte*)&colors); + for (int32 y = 0; y < 4; y++) + { + for (int32 x = 0; x < 4; x++) + { + *((Color32*)decompressedBytes + (yBlock * 4 + y) * textureData.Width + (xBlock * 4 + x)) = colors[y * 4 + x]; + } + } + } + } + break; + } + default: + LOG(Warning, "Texture data format {0} is not supported by stb library.", (int32)textureData.Format); + return true; + } + texture = &decompressed; + } +#endif + // Convert into RGBA8 - const auto sampler = GetSampler(textureData.Format); + const auto sampler = GetSampler(texture->Format); if (sampler == nullptr) { LOG(Warning, "Texture data format {0} is not supported by stb library.", (int32)textureData.Format); return true; } - const auto srcData = textureData.GetData(0, 0); + const auto srcData = texture->GetData(0, 0); const int comp = 4; Array data; - bool sRGB = PixelFormatExtensions::IsSRGB(textureData.Format); + bool sRGB = PixelFormatExtensions::IsSRGB(texture->Format); if (type == ImageType::HDR) { - data.Resize(sizeof(float) * comp * textureData.Width * textureData.Height); + data.Resize(sizeof(float) * comp * texture->Width * texture->Height); auto ptr = (Vector4*)data.Get(); - for (int32 y = 0; y < textureData.Height; y++) + for (int32 y = 0; y < texture->Height; y++) { - for (int32 x = 0; x < textureData.Width; x++) + for (int32 x = 0; x < texture->Width; x++) { Color color = SamplePoint(sampler, x, y, srcData->Data.Get(), srcData->RowPitch); if (sRGB) color = Color::SrgbToLinear(color); - *(ptr + x + y * textureData.Width) = color.ToVector4(); + *(ptr + x + y * texture->Width) = color.ToVector4(); } } } else { - data.Resize(sizeof(Color32) * comp * textureData.Width * textureData.Height); + data.Resize(sizeof(Color32) * comp * texture->Width * texture->Height); auto ptr = (Color32*)data.Get(); - for (int32 y = 0; y < textureData.Height; y++) + for (int32 y = 0; y < texture->Height; y++) { - for (int32 x = 0; x < textureData.Width; x++) + for (int32 x = 0; x < texture->Width; x++) { Color color = SamplePoint(sampler, x, y, srcData->Data.Get(), srcData->RowPitch); if (sRGB) color = Color::SrgbToLinear(color); - *(ptr + x + y * textureData.Width) = Color32(color); + *(ptr + x + y * texture->Width) = Color32(color); } } } @@ -116,21 +218,21 @@ bool TextureTool::ExportTextureStb(ImageType type, const StringView& path, const switch (type) { case ImageType::BMP: - result = stbi_write_bmp_core(&s, textureData.Width, textureData.Height, comp, data.Get()); + result = stbi_write_bmp_core(&s, texture->Width, texture->Height, comp, data.Get()); break; case ImageType::JPEG: - result = stbi_write_jpg_core(&s, textureData.Width, textureData.Height, comp, data.Get(), 90); + result = stbi_write_jpg_core(&s, texture->Width, texture->Height, comp, data.Get(), 90); break; case ImageType::TGA: - result = stbi_write_tga_core(&s, textureData.Width, textureData.Height, comp, data.Get()); + result = stbi_write_tga_core(&s, texture->Width, texture->Height, comp, data.Get()); break; case ImageType::HDR: - result = stbi_write_hdr_core(&s, textureData.Width, textureData.Height, comp, (float*)data.Get()); + result = stbi_write_hdr_core(&s, texture->Width, texture->Height, comp, (float*)data.Get()); break; case ImageType::PNG: { int32 ptrSize = 0; - const auto ptr = stbi_write_png_to_mem(data.Get(), 0, textureData.Width, textureData.Height, comp, &ptrSize); + const auto ptr = stbi_write_png_to_mem(data.Get(), 0, texture->Width, texture->Height, comp, &ptrSize); if (ptr) { file->WriteBytes(ptr, ptrSize); diff --git a/Source/ThirdParty/detex/LICENSE b/Source/ThirdParty/detex/LICENSE new file mode 100644 index 000000000..8998ccac5 --- /dev/null +++ b/Source/ThirdParty/detex/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2015 Harm Hanemaaijer + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + diff --git a/Source/ThirdParty/detex/decompress-bc.cpp b/Source/ThirdParty/detex/decompress-bc.cpp new file mode 100644 index 000000000..82f89b54d --- /dev/null +++ b/Source/ThirdParty/detex/decompress-bc.cpp @@ -0,0 +1,241 @@ +/* + +Copyright (c) 2015 Harm Hanemaaijer + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include "detex.h" + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC1 */ +/* format. */ +bool detexDecompressBlockBC1(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, +uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__) + uint32_t colors = *(uint32_t *)&bitstring[0]; +#else + uint32_t colors = ((uint32_t)bitstring[0] << 24) | + ((uint32_t)bitstring[1] << 16) | + ((uint32_t)bitstring[2] << 8) | bitstring[3]; +#endif + // Decode the two 5-6-5 RGB colors. + int color_r[4], color_g[4], color_b[4]; + color_b[0] = (colors & 0x0000001F) << 3; + color_g[0] = (colors & 0x000007E0) >> (5 - 2); + color_r[0] = (colors & 0x0000F800) >> (11 - 3); + color_b[1] = (colors & 0x001F0000) >> (16 - 3); + color_g[1] = (colors & 0x07E00000) >> (21 - 2); + color_r[1] = (colors & 0xF8000000) >> (27 - 3); + if ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16)) { + color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]); + color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]); + color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]); + color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]); + color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]); + color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]); + } + else { + color_r[2] = (color_r[0] + color_r[1]) / 2; + color_g[2] = (color_g[0] + color_g[1]) / 2; + color_b[2] = (color_b[0] + color_b[1]) / 2; + color_r[3] = color_g[3] = color_b[3] = 0; + } + uint32_t pixels = *(uint32_t *)&bitstring[4]; + for (int i = 0; i < 16; i++) { + int pixel = (pixels >> (i * 2)) & 0x3; + *(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGB8Alpha0xFF( + color_r[pixel], color_g[pixel], color_b[pixel]); + } + return true; +} + +uint32_t detexGetModeBC1(const uint8_t *bitstring) { + uint32_t colors = *(uint32_t *)bitstring; + if ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16)) + return 0; + else + return 1; +} + +void detexSetModeBC1(uint8_t *bitstring, uint32_t mode, uint32_t flags, +uint32_t *colors) { + uint32_t colorbits = *(uint32_t *)bitstring; + uint32_t current_mode; + if ((colorbits & 0xFFFF) > ((colorbits & 0xFFFF0000) >> 16)) + current_mode = 0; + else + current_mode = 1; + if (current_mode != mode) { + colorbits = ((colorbits & 0xFFFF) << 16) | (colorbits >> 16); + *(uint32_t *)bitstring = colorbits; + } +} + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC1A */ +/* format. */ +bool detexDecompressBlockBC1A(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, +uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__) + uint32_t colors = *(uint32_t *)&bitstring[0]; +#else + uint32_t colors = ((uint32_t)bitstring[0] << 24) | + ((uint32_t)bitstring[1] << 16) | + ((uint32_t)bitstring[2] << 8) | bitstring[3]; +#endif + bool opaque = ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16)); + if (opaque && (flags & DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY)) + return false; + if (!opaque && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY)) + return false; + // Decode the two 5-6-5 RGB colors. + int color_r[4], color_g[4], color_b[4], color_a[4]; + color_b[0] = (colors & 0x0000001F) << 3; + color_g[0] = (colors & 0x000007E0) >> (5 - 2); + color_r[0] = (colors & 0x0000F800) >> (11 - 3); + color_b[1] = (colors & 0x001F0000) >> (16 - 3); + color_g[1] = (colors & 0x07E00000) >> (21 - 2); + color_r[1] = (colors & 0xF8000000) >> (27 - 3); + color_a[0] = color_a[1] = color_a[2] = color_a[3] = 0xFF; + if (opaque) { + color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]); + color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]); + color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]); + color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]); + color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]); + color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]); + } + else { + color_r[2] = (color_r[0] + color_r[1]) / 2; + color_g[2] = (color_g[0] + color_g[1]) / 2; + color_b[2] = (color_b[0] + color_b[1]) / 2; + color_r[3] = color_g[3] = color_b[3] = color_a[3] = 0; + } + uint32_t pixels = *(uint32_t *)&bitstring[4]; + for (int i = 0; i < 16; i++) { + int pixel = (pixels >> (i * 2)) & 0x3; + *(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8( + color_r[pixel], color_g[pixel], color_b[pixel], + color_a[pixel]); + } + return true; +} + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC2 */ +/* format. */ +bool detexDecompressBlockBC2(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, +uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__) + uint32_t colors = *(uint32_t *)&bitstring[8]; +#else + uint32_t colors = ((uint32_t)bitstring[8] << 24) | + ((uint32_t)bitstring[9] << 16) | + ((uint32_t)bitstring[10] << 8) | bitstring[11]; +#endif + if ((colors & 0xFFFF) <= ((colors & 0xFFFF0000) >> 16) && + (flags & DETEX_DECOMPRESS_FLAG_ENCODE)) + // GeForce 6 and 7 series produce wrong result in this case. + return false; + int color_r[4], color_g[4], color_b[4]; + color_b[0] = (colors & 0x0000001F) << 3; + color_g[0] = (colors & 0x000007E0) >> (5 - 2); + color_r[0] = (colors & 0x0000F800) >> (11 - 3); + color_b[1] = (colors & 0x001F0000) >> (16 - 3); + color_g[1] = (colors & 0x07E00000) >> (21 - 2); + color_r[1] = (colors & 0xF8000000) >> (27 - 3); + color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]); + color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]); + color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]); + color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]); + color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]); + color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]); + uint32_t pixels = *(uint32_t *)&bitstring[12]; + uint64_t alpha_pixels = *(uint64_t *)&bitstring[0]; + for (int i = 0; i < 16; i++) { + int pixel = (pixels >> (i * 2)) & 0x3; + int alpha = ((alpha_pixels >> (i * 4)) & 0xF) * 255 / 15; + *(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8( + color_r[pixel], color_g[pixel], color_b[pixel], alpha); + } + return true; +} + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC3 */ +/* format. */ +bool detexDecompressBlockBC3(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, +uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer) { + int alpha0 = bitstring[0]; + int alpha1 = bitstring[1]; + if (alpha0 > alpha1 && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY)) + return false; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__) + uint32_t colors = *(uint32_t *)&bitstring[8]; +#else + uint32_t colors = ((uint32_t)bitstring[8] << 24) | + ((uint32_t)bitstring[9] << 16) | + ((uint32_t)bitstring[10] << 8) | bitstring[11]; +#endif + if ((colors & 0xFFFF) <= ((colors & 0xFFFF0000) >> 16) && + (flags & DETEX_DECOMPRESS_FLAG_ENCODE)) + // GeForce 6 and 7 series produce wrong result in this case. + return false; + int color_r[4], color_g[4], color_b[4]; + // color_x[] has a value between 0 and 248 with the lower three bits zero. + color_b[0] = (colors & 0x0000001F) << 3; + color_g[0] = (colors & 0x000007E0) >> (5 - 2); + color_r[0] = (colors & 0x0000F800) >> (11 - 3); + color_b[1] = (colors & 0x001F0000) >> (16 - 3); + color_g[1] = (colors & 0x07E00000) >> (21 - 2); + color_r[1] = (colors & 0xF8000000) >> (27 - 3); + color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]); + color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]); + color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]); + color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]); + color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]); + color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]); + uint32_t pixels = *(uint32_t *)&bitstring[12]; + uint64_t alpha_bits = (uint32_t)bitstring[2] | + ((uint32_t)bitstring[3] << 8) | + ((uint64_t)*(uint32_t *)&bitstring[4] << 16); + for (int i = 0; i < 16; i++) { + int pixel = (pixels >> (i * 2)) & 0x3; + int code = (alpha_bits >> (i * 3)) & 0x7; + int alpha; + if (alpha0 > alpha1) + switch (code) { + case 0 : alpha = alpha0; break; + case 1 : alpha = alpha1; break; + case 2 : alpha = detexDivide0To1791By7(6 * alpha0 + 1 * alpha1); break; + case 3 : alpha = detexDivide0To1791By7(5 * alpha0 + 2 * alpha1); break; + case 4 : alpha = detexDivide0To1791By7(4 * alpha0 + 3 * alpha1); break; + case 5 : alpha = detexDivide0To1791By7(3 * alpha0 + 4 * alpha1); break; + case 6 : alpha = detexDivide0To1791By7(2 * alpha0 + 5 * alpha1); break; + case 7 : alpha = detexDivide0To1791By7(1 * alpha0 + 6 * alpha1); break; + } + else + switch (code) { + case 0 : alpha = alpha0; break; + case 1 : alpha = alpha1; break; + case 2 : alpha = detexDivide0To1279By5(4 * alpha0 + 1 * alpha1); break; + case 3 : alpha = detexDivide0To1279By5(3 * alpha0 + 2 * alpha1); break; + case 4 : alpha = detexDivide0To1279By5(2 * alpha0 + 3 * alpha1); break; + case 5 : alpha = detexDivide0To1279By5(1 * alpha0 + 4 * alpha1); break; + case 6 : alpha = 0; break; + case 7 : alpha = 0xFF; break; + } + *(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8( + color_r[pixel], color_g[pixel], color_b[pixel], alpha); + } + return true; +} + diff --git a/Source/ThirdParty/detex/detex.Build.cs b/Source/ThirdParty/detex/detex.Build.cs new file mode 100644 index 000000000..18e3414f8 --- /dev/null +++ b/Source/ThirdParty/detex/detex.Build.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +using Flax.Build; + +/// +/// https://github.com/hglm/detex +/// +public class detex : ThirdPartyModule +{ + /// + public override void Init() + { + base.Init(); + + LicenseType = LicenseTypes.MIT; + LicenseFilePath = "LICENSE"; + + // Merge third-party modules into engine binary + BinaryModuleName = "FlaxEngine"; + } +} diff --git a/Source/ThirdParty/detex/detex.h b/Source/ThirdParty/detex/detex.h new file mode 100644 index 000000000..adbeac512 --- /dev/null +++ b/Source/ThirdParty/detex/detex.h @@ -0,0 +1,1194 @@ +/* + +Copyright (c) 2015 Harm Hanemaaijer + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#ifndef __DETEX_H__ +#define __DETEX_H__ + +#undef __BEGIN_DECLS +#undef __END_DECLS +#ifdef __cplusplus +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#else +#define __BEGIN_DECLS /* empty */ +#define __END_DECLS /* empty */ +#endif + +/* Generic helper definitions for shared library support. */ +#if defined _WIN32 || defined __CYGWIN__ + #define DETEX_HELPER_SHARED_IMPORT __declspec(dllimport) + #define DETEX_HELPER_SHARED_EXPORT __declspec(dllexport) + #define DETEX_HELPER_SHARED_LOCAL +#else + #if __GNUC__ >= 4 + #define DETEX_HELPER_SHARED_IMPORT __attribute__ ((visibility ("default"))) + #define DETEX_HELPER_SHARED_EXPORT __attribute__ ((visibility ("default"))) + #define DETEX_HELPER_SHARED_LOCAL __attribute__ ((visibility ("hidden"))) + #else + #define DETEX_HELPER_SHARED_IMPORT + #define DETEX_HELPER_SHARED_EXPORT + #define DETEX_HELPER_SHARED_LOCAL + #endif +#endif + +/* Now we use the generic helper definitions above to define DETEX_API and DETEX_LOCAL. */ +/* DETEX_API is used for the public API symbols. It either imports or exports the symbol */ +/* for shared/DLL libraries (or does nothing for static build). DETEX_LOCAL is used for */ +/* non-API symbols. */ + +#ifdef DETEX_SHARED + /* Defined if DETEX is compiled as a shared library. */ + #ifdef DETEX_SHARED_EXPORTS + /* Defined if we are building the detex shared library (instead of using it). */ + #define DETEX_API DETEX_HELPER_SHARED_EXPORT + #else + #define DETEX_API DETEX_HELPER_SHARED_IMPORT + #endif /* DETEX_SHARED_EXPORTS */ + #define DETEX_LOCAL DETEX_HELPER_SHARED_LOCAL +#else + /* DETEX_SHARED is not defined: this means detex is a static lib. */ + #define DETEX_API + #define DETEX_LOCAL +#endif /* DETEX_SHARED */ + +__BEGIN_DECLS + +#include +#include +#include + +#define DETEX_INLINE_ONLY __attribute__((always_inline)) inline +#define DETEX_RESTRICT __restrict + +/* Maximum uncompressed block size in bytes. */ +#define DETEX_MAX_BLOCK_SIZE 256 + +/* Detex library pixel formats. */ + +enum { + /* The format has 16-bit components. */ + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT = 0x1, + /* The format has 32-bit components. */ + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT = 0x2, + /* The format has an alpha component. */ + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT = 0x4, + /* The sequential component order is RGB. */ + DETEX_PIXEL_FORMAT_RGB_COMPONENT_ORDER_BIT = 0x0, + /* The sequential component order is BGR. */ + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT = 0x8, + /* The format has one component. */ + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS = 0x0, + /* The format has two components. */ + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS = 0x10, + /* The format has three components. */ + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS = 0x20, + /* The format has four components. */ + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS = 0x30, + /* The format is stored as 8-bit pixels. */ + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS = 0x000, + /* The format is stored as 16-bit pixels. */ + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS = 0x100, + /* The format is stored as 24-bit pixels. */ + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS = 0x200, + /* The format is stored as 32-bit pixels. */ + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS = 0x300, + /* The format is stored as 48-bit pixels. */ + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS = 0x500, + /* The format is stored as 64-bit pixels. */ + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS = 0x700, + /* The format is stored as 96-bit pixels. */ + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS = 0xB00, + /* The format is stored as 128-bit pixels. */ + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS = 0xF00, + /* The format has signed integer components. */ + DETEX_PIXEL_FORMAT_SIGNED_BIT = 0x1000, + /* The format has (half-)float components. */ + DETEX_PIXEL_FORMAT_FLOAT_BIT = 0x2000, + /* The fomat is HDR (high dynamic range). */ + DETEX_PIXEL_FORMAT_HDR_BIT = 0x4000, + + DETEX_PIXEL_FORMAT_RGBA8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_BGRA8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_RGBX8 = ( + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_BGRX8 = ( + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_RGB8 = ( + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_BGR8 = ( + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_R8 = ( + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_SIGNED_R8 = ( + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + DETEX_PIXEL_FORMAT_RG8 = ( + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_SIGNED_RG8 = ( + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + DETEX_PIXEL_FORMAT_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_SIGNED_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + DETEX_PIXEL_FORMAT_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_SIGNED_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + DETEX_PIXEL_FORMAT_RGB16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_RGBA16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS + ), + DETEX_PIXEL_FORMAT_FLOAT_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_R16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RG16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBX16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBA16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBA16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGB16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGB16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_BGRX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_BGRX16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_SIGNED_FLOAT_BGRX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_R32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_R32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RG32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RG32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGB32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGB32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBX32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBX32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBA32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + DETEX_PIXEL_FORMAT_FLOAT_RGBA32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + DETEX_PIXEL_FORMAT_A8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS + ), +}; + +/* Mode mask flags. */ + +enum { + DETEX_MODE_MASK_ETC_INDIVIDUAL = 0x1, + DETEX_MODE_MASK_ETC_DIFFERENTIAL = 0x2, + DETEX_MODE_MASK_ETC_T = 0x4, + DETEX_MODE_MASK_ETC_H = 0x8, + DETEX_MODE_MASK_ETC_PLANAR = 0x10, + DETEX_MODE_MASK_ALL_MODES_ETC1 = 0x3, + DETEX_MODE_MASK_ALL_MODES_ETC2 = 0x1F, + DETEX_MODE_MASK_ALL_MODES_ETC2_PUNCHTHROUGH = 0X1E, + DETEX_MODE_MASK_ALL_MODES_BPTC = 0xFF, + DETEX_MODE_MASK_ALL_MODES_BPTC_FLOAT = 0x3FFF, + DETEX_MODE_MASK_ALL = 0XFFFFFFFF, +}; + +/* Decompression function flags. */ + +enum { + /* Function returns false (invalid block) when the compressed block */ + /* is in a format not allowed to be generated by an encoder. */ + DETEX_DECOMPRESS_FLAG_ENCODE = 0x1, + /* For compression formats that have opaque and non-opaque modes, */ + /* return false (invalid block) when the compressed block is encoded */ + /* using a non-opaque mode. */ + DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY = 0x2, + /* For compression formats that have opaque and non-opaque modes, */ + /* return false (invalid block) when the compressed block is encoded */ + /* using an opaque mode. */ + DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY = 0x4, +}; + +/* Set mode function flags. */ + +enum { + /* The block is opaque (alpha is always 0xFF). */ + DETEX_SET_MODE_FLAG_OPAQUE = 0x2, + /* The block is non-opaque (alpha is not always 0xFF). */ + DETEX_SET_MODE_FLAG_NON_OPAQUE = 0x4, + /* The block has punchthrough alpha (alpha is either 0x00 or 0xFF). */ + DETEX_SET_MODE_FLAG_PUNCHTHROUGH = 0x8, + /* The block only consists of one or two different pixel colors. */ + DETEX_SET_MODE_FLAG_MAX_TWO_COLORS = 0x10, +}; + +/* + * Decompression functions for 8-bit RGB8/RGBA8 formats. The output pixel format + * is DETEX_PIXEL_FORMAT_RGBA8 or DETEX_PIXEL_FORMAT_RGBX8 (32-bit pixels with + * optional alpha component, red component in lowest-order byte. When the + * texture format does not have alpha, alpha is set to 0xFF. + */ + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the ETC1 */ +/* format. */ +DETEX_API bool detexDecompressBlockETC1(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the ETC2 */ +/* format. */ +DETEX_API bool detexDecompressBlockETC2(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the */ +/* ETC2_PUNCHTROUGH format. */ +DETEX_API bool detexDecompressBlockETC2_PUNCHTHROUGH(const uint8_t *bitstring, + uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the ETC2_EAC */ +/* format. */ +DETEX_API bool detexDecompressBlockETC2_EAC(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); + + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC1 */ +/* format. */ +DETEX_API bool detexDecompressBlockBC1(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC1A */ +/* format. */ +DETEX_API bool detexDecompressBlockBC1A(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC2 */ +/* format. */ +DETEX_API bool detexDecompressBlockBC2(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the BC3 */ +/* format. */ +DETEX_API bool detexDecompressBlockBC3(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the BPTC */ +/* (BC7) format. */ +DETEX_API bool detexDecompressBlockBPTC(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); + +/* + * Decompression functions for 8-bit unsigned R and RG formats. The + * output format is DETEX_PIXEL_FORMAT_R8 or DETEX_PIXEL_FORMAT_RG8. + */ + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the */ +/* unsigned RGTC1 (BC4) format. */ +DETEX_API bool detexDecompressBlockRGTC1(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* unsigned RGTC2 (BC5) format. */ +DETEX_API bool detexDecompressBlockRGTC2(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); + +/* + * Decompression functions for 16-bit unsigned/signed R and RG formats. The + * output format is DETEX_PIXEL_FORMAT_R16, DETEX_PIXEL_FORMAT_SIGNED_R16, + * DETEX_PIXEL_FORMAT_RG16, or DETEX_PIXEL_FORMAT_SIGNED_RG16. + */ + +/* Decompress a 64-bit 4x4 pixel texture block compressed using the */ +/* signed RGTC1 (signed BC4) format. */ +DETEX_API bool detexDecompressBlockSIGNED_RGTC1(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* signed RGTC2 (signed BC5) format. */ +DETEX_API bool detexDecompressBlockSIGNED_RGTC2(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the */ +/* ETC2_R11_EAC format. */ +DETEX_API bool detexDecompressBlockEAC_R11(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 64-bit 4x4 pixel texture block compressed using the */ +/* ETC2_SIGNED_R11_EAC format. */ +DETEX_API bool detexDecompressBlockEAC_SIGNED_R11(const uint8_t *bitstring, + uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* ETC2_RG11_EAC format. */ +DETEX_API bool detexDecompressBlockEAC_RG11(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* ETC2_SIGNED_RG11_EAC format. */ +DETEX_API bool detexDecompressBlockEAC_SIGNED_RG11(const uint8_t *bitstring, + uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer); + +/* + * Decompression functions for 16-bit half-float formats. The output format is + * DETEX_PIXEL_FORMAT_FLOAT_RGBX16 or DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16. + */ + +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* BPTC_FLOAT (BC6H) format. The output format is */ +/* DETEX_PIXEL_FORMAT_FLOAT_RGBX16. */ +DETEX_API bool detexDecompressBlockBPTC_FLOAT(const uint8_t *bitstring, uint32_t mode_mask, + uint32_t flags, uint8_t *pixel_buffer); +/* Decompress a 128-bit 4x4 pixel texture block compressed using the */ +/* BPTC_FLOAT (BC6H_FLOAT) format. The output format is */ +/* DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16. */ +DETEX_API bool detexDecompressBlockBPTC_SIGNED_FLOAT(const uint8_t *bitstring, + uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer); + + +/* + * Get mode functions. They return the internal compression format mode used + * inside the compressed block. For compressed formats that do not use a mode, + * there is no GetMode function. + */ + +DETEX_API uint32_t detexGetModeBC1(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeETC1(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeETC2(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeETC2_PUNCHTHROUGH(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeETC2_EAC(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeBPTC(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeBPTC_FLOAT(const uint8_t *bitstring); +DETEX_API uint32_t detexGetModeBPTC_SIGNED_FLOAT(const uint8_t *bitstring); + +/* + * Set mode functions. The set mode function modifies a compressed texture block + * so that the specified mode is set, making use of information about the block + * (whether it is opaque, non-opaque or punchthrough for formats with alpha, + * whether at most two different colors are used). For compressed formats + * that do not use a mode, there is no SetMode function. + */ + +DETEX_API void detexSetModeBC1(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeETC1(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeETC2(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeETC2_PUNCHTHROUGH(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeETC2_EAC(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeBPTC(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); +DETEX_API void detexSetModeBPTC_FLOAT(uint8_t *bitstring, uint32_t mode, uint32_t flags, + uint32_t *colors); + +/* Compressed texture format definitions for general texture decompression */ +/* functions. */ + +#define DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(n) ((uint32_t)n << 24) + +enum { + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_UNCOMPRESSED = 0, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1 = 1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_S3TC = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1A = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT3 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT5 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_UF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_SF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC7 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4, +}; + +enum { + DETEX_TEXTURE_FORMAT_PIXEL_FORMAT_MASK = 0x0000FFFF, + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT = 0x00800000, + DETEX_TEXTURE_FORMAT_BC1 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1) | + DETEX_PIXEL_FORMAT_RGBX8 + ), + DETEX_TEXTURE_FORMAT_BC1A = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A) | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_BC2 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_BC3 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_RGTC1 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1) | + DETEX_PIXEL_FORMAT_R8 + ), + DETEX_TEXTURE_FORMAT_SIGNED_RGTC1 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1) | + DETEX_PIXEL_FORMAT_SIGNED_R16 + ), + DETEX_TEXTURE_FORMAT_RGTC2 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RG8 + ), + DETEX_TEXTURE_FORMAT_SIGNED_RGTC2 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_SIGNED_RG16 + ), + DETEX_TEXTURE_FORMAT_BPTC_FLOAT = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_FLOAT_RGBX16 + ), + DETEX_TEXTURE_FORMAT_BPTC_SIGNED_FLOAT = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16 + ), + DETEX_TEXTURE_FORMAT_BPTC = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_ETC1 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1) | + DETEX_PIXEL_FORMAT_RGBX8 + ), + DETEX_TEXTURE_FORMAT_ETC2 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2) | + DETEX_PIXEL_FORMAT_RGBX8 + ), + DETEX_TEXTURE_FORMAT_ETC2_PUNCHTHROUGH = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH) | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_ETC2_EAC = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RGBA8 + ), + DETEX_TEXTURE_FORMAT_EAC_R11 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11) | + DETEX_PIXEL_FORMAT_R16 + ), + DETEX_TEXTURE_FORMAT_EAC_SIGNED_R11 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11) | + DETEX_PIXEL_FORMAT_SIGNED_R16 + ), + DETEX_TEXTURE_FORMAT_EAC_RG11 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RG16 + ), + DETEX_TEXTURE_FORMAT_EAC_SIGNED_RG11 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_SIGNED_RG16 + ), + DETEX_TEXTURE_FORMAT_ASTC_4X4 = ( + DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS( + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4 ) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DETEX_PIXEL_FORMAT_RGBA8 + ), +}; + +typedef struct { + uint32_t format; + uint8_t *data; + int width; + int height; + int width_in_blocks; + int height_in_blocks; +} detexTexture; + +/* + * General texture decompression functions (tiled or linear) with specified + * compression format. + */ + +/* + * General block decompression function. Block is decompressed using the given + * compressed format, and stored in the given pixel format. + */ +DETEX_API bool detexDecompressBlock(const uint8_t *bitstring, uint32_t texture_format, + uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer, + uint32_t pixel_format); + +/* + * Decode texture function (tiled). Decode an entire compressed texture into an + * array of image buffer tiles (corresponding to compressed blocks), converting + * into the given pixel format. + */ +DETEX_API bool detexDecompressTextureTiled(const detexTexture *texture, uint8_t *pixel_buffer, + uint32_t pixel_format); + +/* + * Decode texture function (linear). Decode an entire texture into a single + * image buffer, with pixels stored row-by-row, converting into the given pixel + * format. + */ +DETEX_API bool detexDecompressTextureLinear(const detexTexture *texture, uint8_t *pixel_buffer, + uint32_t pixel_format); + + +/* + * Miscellaneous functions. + */ + +/* + * Convert pixels between different formats. The target pixel buffer must + * be allocated with sufficient size to the hold the result. Returns true if + * succesful. + */ +DETEX_API bool detexConvertPixels(uint8_t *source_pixel_buffer, uint32_t nu_pixels, + uint32_t source_pixel_format, uint8_t *target_pixel_buffer, + uint32_t target_pixel_format); + +/* Convert in-place, modifying the source pixel buffer only. If any conversion step changes the */ +/* pixel size, the function will not be succesful and return false. */ +DETEX_API bool detexConvertPixelsInPlace(uint8_t * DETEX_RESTRICT source_pixel_buffer, + uint32_t nu_pixels, uint32_t source_pixel_format, uint32_t target_pixel_format); + +/* Return the component bitfield masks for a pixel format (pixel size must be at most 64 bits). */ +/* Return true if succesful. */ +DETEX_API bool detexGetComponentMasks(uint32_t texture_format, uint64_t *red_mask, uint64_t *green_mask, + uint64_t *blue_mask, uint64_t *alpha_mask); + +/* Return a text description/identifier of the texture type. */ +DETEX_API const char *detexGetTextureFormatText(uint32_t texture_format); + +/* Return a alternative text description of the texture type. Returns empty string */ +/* when there is no alternative description. */ +DETEX_API const char *detexGetAlternativeTextureFormatText(uint32_t texture_format); + +/* Return OpenGL TexImage2D/KTX file parameters for a texture format. */ +DETEX_API bool detexGetOpenGLParameters(uint32_t texture_format, int *gl_internal_format, + uint32_t *gl_format, uint32_t *gl_type); + +/* Return DirectX 10 format for a texture format. */ +DETEX_API bool detexGetDX10Parameters(uint32_t texture_format, uint32_t *dx10_format); + +/* Return the error message for the last encountered error. */ +DETEX_API const char *detexGetErrorMessage(); + + +/* + * HDR-related functions. + */ + +/* Set HDR gamma curve parameters. */ +DETEX_API void detexSetHDRParameters(float gamma, float range_min, float range_max); + +/* Calculate the dynamic range of a pixel buffer. Valid for float and half-float formats. */ +/* Returns true if successful. */ +DETEX_API bool detexCalculateDynamicRange(uint8_t *pixel_buffer, int nu_pixels, uint32_t pixel_format, + float *range_min_out, float *range_max_out); + + +/* + * Texture file loading. + */ + +/* Load texture from KTX file with mip-maps. Returns true if successful. */ +/* nu_levels is a return parameter that returns the number of mipmap levels found. */ +/* textures_out is a return parameter for an array of detexTexture pointers that is allocated, */ +/* free with free(). textures_out[i] are allocated textures corresponding to each level, free */ +/* with free(). */ +DETEX_API bool detexLoadKTXFileWithMipmaps(const char *filename, int max_mipmaps, detexTexture ***textures_out, + int *nu_levels_out); + +/* Load texture from KTX file (first mip-map only). Returns true if successful. */ +/* The texture is allocated, free with free(). */ +DETEX_API bool detexLoadKTXFile(const char *filename, detexTexture **texture_out); + +/* Save textures to KTX file (multiple mip-maps levels). Return true if succesful. */ +DETEX_API bool detexSaveKTXFileWithMipmaps(detexTexture **textures, int nu_levels, const char *filename); + +/* Save texture to KTX file (single mip-map level). Returns true if succesful. */ +DETEX_API bool detexSaveKTXFile(detexTexture *texture, const char *filename); + +/* Load texture from DDS file with mip-maps. Returns true if successful. */ +/* nu_levels is a return parameter that returns the number of mipmap levels found. */ +/* textures_out is a return parameter for an array of detexTexture pointers that is allocated, */ +/* free with free(). textures_out[i] are allocated textures corresponding to each level, free */ +/* with free(). */ +DETEX_API bool detexLoadDDSFileWithMipmaps(const char *filename, int max_mipmaps, detexTexture ***textures_out, + int *nu_levels_out); + +/* Load texture from DDS file (first mip-map only). Returns true if successful. */ +/* The texture is allocated, free with free(). */ +DETEX_API bool detexLoadDDSFile(const char *filename, detexTexture **texture_out); + +/* Save textures to DDS file (multiple mip-maps levels). Return true if succesful. */ +DETEX_API bool detexSaveDDSFileWithMipmaps(detexTexture **textures, int nu_levels, const char *filename); + +/* Save texture to DDS file (single mip-map level). Returns true if succesful. */ +DETEX_API bool detexSaveDDSFile(detexTexture *texture, const char *filename); + +/* Load texture file (type autodetected from extension) with mipmaps. */ +DETEX_API bool detexLoadTextureFileWithMipmaps(const char *filename, int max_mipmaps, detexTexture ***textures_out, + int *nu_levels_out); + +/* Load texture file (type autodetected from extension). */ +DETEX_API bool detexLoadTextureFile(const char *filename, detexTexture **texture_out); + +/* Load texture from raw file (first mip-map only) given the format and dimensions */ +/* in texture. Returns true if successful. */ +/* The texture->data is allocated, free with free(). */ +DETEX_API bool detexLoadRawFile(const char *filename, detexTexture *texture); + +/* Save texture to raw file (first mip-map only) given the format and dimensions */ +/* in texture. Returns true if successful. */ +DETEX_API bool detexSaveRawFile(detexTexture *texture, const char *filename); + +/* Return pixel size in bytes for pixel format or texture format (decompressed). */ +static DETEX_INLINE_ONLY int detexGetPixelSize(uint32_t pixel_format) { + return 1 + ((pixel_format & 0xF00) >> 8); +} + +/* Return the number of components of a pixel format or texture format. */ +static DETEX_INLINE_ONLY int detexGetNumberOfComponents(uint32_t pixel_format) { + return 1 + ((pixel_format & 0x30) >> 4); +} + +/* Return the component size in bytes of a pixel format or texture format. */ +static DETEX_INLINE_ONLY int detexGetComponentSize(uint32_t pixel_format) { + return 1 << (pixel_format & 0x3); +} + +/* Return the approximate precision in bits of the components of a pixel format. */ +static DETEX_INLINE_ONLY uint32_t detexGetComponentPrecision(uint32_t pixel_format) { + return detexGetComponentSize(pixel_format) * 8 - + ((pixel_format & DETEX_PIXEL_FORMAT_FLOAT_BIT) != 0) * 5 * + (1 + (detexGetComponentSize(pixel_format) == 4)); +} + +/* Return the total size of a compressed texture. */ +static DETEX_INLINE_ONLY uint32_t detexTextureSize(uint32_t width_in_blocks, +uint32_t height_in_blocks, uint32_t pixel_format) { + return width_in_blocks * height_in_blocks * detexGetPixelSize(pixel_format) * 16; +} + +/* Return whether a pixel or texture format has an alpha component. */ +static DETEX_INLINE_ONLY uint32_t detexFormatHasAlpha(uint32_t pixel_format) { + return (pixel_format & DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT) != 0; +} + + +/* Return the compressed texture type index of a texture format. */ +static DETEX_INLINE_ONLY uint32_t detexGetCompressedFormat(uint32_t texture_format) { + return texture_format >> 24; +} + +/* Return the block size of a compressed texture format in bytes. */ +static DETEX_INLINE_ONLY uint32_t detexGetCompressedBlockSize(uint32_t texture_format) { + return 8 + ((texture_format & DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT) >> 20); +} + +/* Return whether a texture format is compressed. */ +static DETEX_INLINE_ONLY uint32_t detexFormatIsCompressed(uint32_t texture_format) { + return detexGetCompressedFormat(texture_format) != DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_UNCOMPRESSED; +} + +/* Return the pixel format of a texture format. */ +static DETEX_INLINE_ONLY uint32_t detexGetPixelFormat(uint32_t texture_format) { + return texture_format & DETEX_TEXTURE_FORMAT_PIXEL_FORMAT_MASK; +} + + +DETEX_API extern const uint8_t detex_clamp0to255_table[767]; + +/* Clamp an integer value in the range -255 to 511 to the the range 0 to 255. */ +static DETEX_INLINE_ONLY uint8_t detexClamp0To255(int x) { + return detex_clamp0to255_table[x + 255]; +} + +/* Clamp a float point value to the range 0.0 to 1.0f. */ +static DETEX_INLINE_ONLY float detexClamp0To1(float f) { + if (f < 0.0f) + return 0.0f; + else if (f > 1.0f) + return 1.0f; + else + return f; +} + + +/* Integer division using look-up tables, used by BC1/2/3 and RGTC (BC4/5) */ +/* decompression. */ + +DETEX_API extern const uint8_t detex_division_by_3_table[768]; + +static DETEX_INLINE_ONLY uint32_t detexDivide0To767By3(uint32_t value) { + return detex_division_by_3_table[value]; +} + +DETEX_API extern const uint8_t detex_division_by_7_table[1792]; + +static DETEX_INLINE_ONLY uint32_t detexDivide0To1791By7(uint32_t value) { + return detex_division_by_7_table[value]; +} + +static DETEX_INLINE_ONLY int8_t detexSignInt32(int v) { + return (int8_t)((v >> 31) | - (- v >> 31)); +} + +static DETEX_INLINE_ONLY int detexDivideMinus895To895By7(int value) { + return (int8_t)detex_division_by_7_table[abs(value)] * detexSignInt32(value); +} + +DETEX_API extern const uint8_t detex_division_by_5_table[1280]; + +static DETEX_INLINE_ONLY uint32_t detexDivide0To1279By5(uint32_t value) { + return detex_division_by_5_table[value]; +} + +static DETEX_INLINE_ONLY int detexDivideMinus639To639By5(int value) { + return (int8_t)detex_division_by_5_table[abs(value)] * detexSignInt32(value); +} + + +/* + * Define some short functions for pixel packing/unpacking. The compiler will + * take care of optimization by inlining and removing unused functions. + * + * The pixel format used corresponds to formats with an RGB component order, + * including: + * + * DETEX_PIXEL_FORMAT_RGB8, DETEX_PIXEL_FORMAT_RGBA8 + * detexPack32RGB8Alpha0xFF, detexPack32R8, detexPack32G8, detexPack32B8, + * detexPixel32GetR8, detexPixel32GetG8, detexPixel32GetB8 + * DETEX_PIXEL_FORMAT_RGBA8 + * detexPack32RGBA8, detexPack32A8, detexPixel32GetA8 + * DETEX_PIXEL_FORMAT_RG16, DETEX_PIXEL_FORMAT_SIGNED_RG16, + * DETEX_PIXEL_FORMAT_FLOAT_RG16 + * detexPack32RG16, detexPack32R16, detexPack32G16, detexPack32RG16, + * detexPixel32GetR16, detexPixel32GetG16 + * DETEX_PIXEL_FORMAT_FLOAT_RGBX16, DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16 + * detexPack64RGB16, detexPack64R16, detexPack64G16, detexPack64B16, + * detexPixel64GetR16, detexPixel64GetG16, detexPixel64GetB16 + */ + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__) + +static DETEX_INLINE_ONLY uint32_t detexPack32RGBA8(int r, int g, int b, int a) { + return (uint32_t)r | ((uint32_t)g << 8) | ((uint32_t)b << 16) | + ((uint32_t)a << 24); +} + +static DETEX_INLINE_ONLY uint32_t detexPack32RGB8Alpha0xFF(int r, int g, int b) { + return detexPack32RGBA8(r, g, b, 0xFF); +} + +static DETEX_INLINE_ONLY uint32_t detexPack32R8(int r) { + return (uint32_t)r; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32G8(int g) { + return (uint32_t)g << 8; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32B8(int b) { + return (uint32_t)b << 16; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32A8(int a) { + return (uint32_t)a << 24; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32RG8(uint32_t r8, uint32_t g8) { + return r8 | (g8 << 8); +} + +static DETEX_INLINE_ONLY uint32_t detexPack32R16(uint32_t r16) { + return r16; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32G16(uint32_t g16) { + return g16 << 16; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32RG16(uint32_t r16, uint32_t g16) { + return r16 | (g16 << 16); +} + +static DETEX_INLINE_ONLY uint64_t detexPack64R16(uint32_t r16) { + return r16; +} + +static DETEX_INLINE_ONLY uint64_t detexPack64G16(uint32_t g16) { + return g16 << 16; +} + +static DETEX_INLINE_ONLY uint64_t detexPack64B16(uint32_t b16) { + return (uint64_t)b16 << 32; +} + +static DETEX_INLINE_ONLY uint64_t detexPack64A16(uint32_t a16) { + return (uint64_t)a16 << 48; +} + +static DETEX_INLINE_ONLY uint64_t detexPack64RGB16(uint16_t r16, uint16_t g16, uint16_t b16) { + return (uint64_t)r16 | ((uint64_t)g16 << 16) | ((uint64_t)b16 << 32); +} + +static DETEX_INLINE_ONLY uint64_t detexPack64RGBA16(uint16_t r16, uint16_t g16, uint16_t b16, uint16_t a16) { + return (uint64_t)r16 | ((uint64_t)g16 << 16) | ((uint64_t)b16 << 32) | ((uint64_t)a16 << 48); +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetR8(uint32_t pixel) { + return pixel & 0xFF; +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetG8(uint32_t pixel) { + return (pixel & 0xFF00) >> 8; +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetB8(uint32_t pixel) { + return (pixel & 0xFF0000) >> 16; +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetA8(uint32_t pixel) { + return (pixel & 0xFF000000) >> 24; +} + +static DETEX_INLINE_ONLY int detexPixel32GetSignedR8(uint32_t pixel) { + return (int8_t)(pixel & 0xFF); +} + +static DETEX_INLINE_ONLY int detexPixel32GetSignedG8(uint32_t pixel) { + return (int8_t)((pixel & 0xFF00) >> 8); +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetR16(uint32_t pixel) { + return pixel & 0x0000FFFF; +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetG16(uint32_t pixel) { + return (pixel & 0xFFFF0000) >> 16; +} + +static DETEX_INLINE_ONLY int detexPixel32GetSignedR16(uint32_t pixel) { + return (int16_t)(pixel & 0x0000FFFF); +} + +static DETEX_INLINE_ONLY int detexPixel32GetSignedG16(uint32_t pixel) { + return (int16_t)((pixel & 0xFFFF0000) >> 16); +} + +static DETEX_INLINE_ONLY uint64_t detexPixel64GetR16(uint64_t pixel) { + return pixel & 0xFFFF; +} + +static DETEX_INLINE_ONLY uint64_t detexPixel64GetG16(uint64_t pixel) { + return (pixel & 0xFFFF0000) >> 16; +} + +static DETEX_INLINE_ONLY uint64_t detexPixel64GetB16(uint64_t pixel) { + return (pixel & 0xFFFF00000000) >> 32; +} + +static DETEX_INLINE_ONLY uint64_t detexPixel64GetA16(uint64_t pixel) { + return (pixel & 0xFFFF000000000000) >> 48; +} + +#define DETEX_PIXEL32_ALPHA_BYTE_OFFSET 3 + +#else + +#error Big-endian byte order not supported. + +static DETEX_INLINE_ONLY uint32_t detexPack32RGBA8(int r, int g, int b, int a) { + return a | ((uint32_t)b << 8) | ((uint32_t)g << 16) | ((uint32_t)r << 24); +} + +static DETEX_INLINE_ONLY uint32_t detexPack32RGB8Alpha0xFF(int r, int g, int b) { + return pack_rgba(r, g, b, 0xFF); +} + +static DETEX_INLINE_ONLY uint32_t detexPack32R8(int r) { + return (uint32_t)r << 24; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32G8(int g) { + return (uint32_t)g << 16; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32B8(int b) { + return (uint32_t)b << 8; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32A8(int a) { + return a; +} + +static DETEX_INLINE_ONLY uint32_t detexPack32RG16(uint32_t r16, uint32_t g16) { + return g16 | (r16 << 16); +} + +static DETEX_INLINE_ONLY int detexPixel32GetR8(uint32_t pixel) { + return (pixel & 0xFF000000) >> 24; +} + +static DETEX_INLINE_ONLY int detexPixel32GetG8(uint32_t pixel) { + return (pixel & 0xFF0000) >> 16; +} + +static DETEX_INLINE_ONLY int detexPixel32GetB8(uint32_t pixel) { + return (pixel & 0xFF00) >> 8; +} + +static DETEX_INLINE_ONLY int detexPixel32GetA8(uint32_t pixel) { + return pixel & 0xFF; +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetR16(uint32_t pixel) { + return ((pixel & 0xFF000000) >> 24) | ((pixel & 0x00FF0000) >> 8); +} + +static DETEX_INLINE_ONLY uint32_t detexPixel32GetG16(uint32_t pixel) { + return ((pixel & 0x0000FF00) >> 8) | ((pixel & 0x000000FF) << 8); +} + +#define DETEX_PIXEL32_ALPHA_BYTE_OFFSET 0 + +#endif + +__END_DECLS + +#endif + diff --git a/Source/ThirdParty/detex/division-tables.cpp b/Source/ThirdParty/detex/division-tables.cpp new file mode 100644 index 000000000..cb07c0c42 --- /dev/null +++ b/Source/ThirdParty/detex/division-tables.cpp @@ -0,0 +1,512 @@ +/* + +Copyright (c) 2015 Harm Hanemaaijer + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + +#include "detex.h" + +// Integer division using look-up tables, used by BC1/2/3 and RGTC (BC4/5) +// decompression. + +const uint8_t detex_division_by_3_table[768] = { + 0, 0, 0, 1, 1, 1, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, + 5, 5, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 9, 9, 9, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, + 13, 13, 14, 14, 14, 15, 15, 15, + 16, 16, 16, 17, 17, 17, 18, 18, + 18, 19, 19, 19, 20, 20, 20, 21, + 21, 21, 22, 22, 22, 23, 23, 23, + 24, 24, 24, 25, 25, 25, 26, 26, + 26, 27, 27, 27, 28, 28, 28, 29, + 29, 29, 30, 30, 30, 31, 31, 31, + 32, 32, 32, 33, 33, 33, 34, 34, + 34, 35, 35, 35, 36, 36, 36, 37, + 37, 37, 38, 38, 38, 39, 39, 39, + 40, 40, 40, 41, 41, 41, 42, 42, + 42, 43, 43, 43, 44, 44, 44, 45, + 45, 45, 46, 46, 46, 47, 47, 47, + 48, 48, 48, 49, 49, 49, 50, 50, + 50, 51, 51, 51, 52, 52, 52, 53, + 53, 53, 54, 54, 54, 55, 55, 55, + 56, 56, 56, 57, 57, 57, 58, 58, + 58, 59, 59, 59, 60, 60, 60, 61, + 61, 61, 62, 62, 62, 63, 63, 63, + 64, 64, 64, 65, 65, 65, 66, 66, + 66, 67, 67, 67, 68, 68, 68, 69, + 69, 69, 70, 70, 70, 71, 71, 71, + 72, 72, 72, 73, 73, 73, 74, 74, + 74, 75, 75, 75, 76, 76, 76, 77, + 77, 77, 78, 78, 78, 79, 79, 79, + 80, 80, 80, 81, 81, 81, 82, 82, + 82, 83, 83, 83, 84, 84, 84, 85, + 85, 85, 86, 86, 86, 87, 87, 87, + 88, 88, 88, 89, 89, 89, 90, 90, + 90, 91, 91, 91, 92, 92, 92, 93, + 93, 93, 94, 94, 94, 95, 95, 95, + 96, 96, 96, 97, 97, 97, 98, 98, + 98, 99, 99, 99, 100, 100, 100, 101, + 101, 101, 102, 102, 102, 103, 103, 103, + 104, 104, 104, 105, 105, 105, 106, 106, + 106, 107, 107, 107, 108, 108, 108, 109, + 109, 109, 110, 110, 110, 111, 111, 111, + 112, 112, 112, 113, 113, 113, 114, 114, + 114, 115, 115, 115, 116, 116, 116, 117, + 117, 117, 118, 118, 118, 119, 119, 119, + 120, 120, 120, 121, 121, 121, 122, 122, + 122, 123, 123, 123, 124, 124, 124, 125, + 125, 125, 126, 126, 126, 127, 127, 127, + 128, 128, 128, 129, 129, 129, 130, 130, + 130, 131, 131, 131, 132, 132, 132, 133, + 133, 133, 134, 134, 134, 135, 135, 135, + 136, 136, 136, 137, 137, 137, 138, 138, + 138, 139, 139, 139, 140, 140, 140, 141, + 141, 141, 142, 142, 142, 143, 143, 143, + 144, 144, 144, 145, 145, 145, 146, 146, + 146, 147, 147, 147, 148, 148, 148, 149, + 149, 149, 150, 150, 150, 151, 151, 151, + 152, 152, 152, 153, 153, 153, 154, 154, + 154, 155, 155, 155, 156, 156, 156, 157, + 157, 157, 158, 158, 158, 159, 159, 159, + 160, 160, 160, 161, 161, 161, 162, 162, + 162, 163, 163, 163, 164, 164, 164, 165, + 165, 165, 166, 166, 166, 167, 167, 167, + 168, 168, 168, 169, 169, 169, 170, 170, + 170, 171, 171, 171, 172, 172, 172, 173, + 173, 173, 174, 174, 174, 175, 175, 175, + 176, 176, 176, 177, 177, 177, 178, 178, + 178, 179, 179, 179, 180, 180, 180, 181, + 181, 181, 182, 182, 182, 183, 183, 183, + 184, 184, 184, 185, 185, 185, 186, 186, + 186, 187, 187, 187, 188, 188, 188, 189, + 189, 189, 190, 190, 190, 191, 191, 191, + 192, 192, 192, 193, 193, 193, 194, 194, + 194, 195, 195, 195, 196, 196, 196, 197, + 197, 197, 198, 198, 198, 199, 199, 199, + 200, 200, 200, 201, 201, 201, 202, 202, + 202, 203, 203, 203, 204, 204, 204, 205, + 205, 205, 206, 206, 206, 207, 207, 207, + 208, 208, 208, 209, 209, 209, 210, 210, + 210, 211, 211, 211, 212, 212, 212, 213, + 213, 213, 214, 214, 214, 215, 215, 215, + 216, 216, 216, 217, 217, 217, 218, 218, + 218, 219, 219, 219, 220, 220, 220, 221, + 221, 221, 222, 222, 222, 223, 223, 223, + 224, 224, 224, 225, 225, 225, 226, 226, + 226, 227, 227, 227, 228, 228, 228, 229, + 229, 229, 230, 230, 230, 231, 231, 231, + 232, 232, 232, 233, 233, 233, 234, 234, + 234, 235, 235, 235, 236, 236, 236, 237, + 237, 237, 238, 238, 238, 239, 239, 239, + 240, 240, 240, 241, 241, 241, 242, 242, + 242, 243, 243, 243, 244, 244, 244, 245, + 245, 245, 246, 246, 246, 247, 247, 247, + 248, 248, 248, 249, 249, 249, 250, 250, + 250, 251, 251, 251, 252, 252, 252, 253, + 253, 253, 254, 254, 254, 255, 255, 255, +}; + +const uint8_t detex_division_by_7_table[1792] = { + 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, + 6, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 13, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, + 14, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 18, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, + 21, 21, 22, 22, 22, 22, 22, 22, + 22, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 25, + 25, 25, 25, 25, 25, 25, 26, 26, + 26, 26, 26, 26, 26, 27, 27, 27, + 27, 27, 27, 27, 28, 28, 28, 28, + 28, 28, 28, 29, 29, 29, 29, 29, + 29, 29, 30, 30, 30, 30, 30, 30, + 30, 31, 31, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 32, 32, 32, 33, + 33, 33, 33, 33, 33, 33, 34, 34, + 34, 34, 34, 34, 34, 35, 35, 35, + 35, 35, 35, 35, 36, 36, 36, 36, + 36, 36, 36, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, + 38, 39, 39, 39, 39, 39, 39, 39, + 40, 40, 40, 40, 40, 40, 40, 41, + 41, 41, 41, 41, 41, 41, 42, 42, + 42, 42, 42, 42, 42, 43, 43, 43, + 43, 43, 43, 43, 44, 44, 44, 44, + 44, 44, 44, 45, 45, 45, 45, 45, + 45, 45, 46, 46, 46, 46, 46, 46, + 46, 47, 47, 47, 47, 47, 47, 47, + 48, 48, 48, 48, 48, 48, 48, 49, + 49, 49, 49, 49, 49, 49, 50, 50, + 50, 50, 50, 50, 50, 51, 51, 51, + 51, 51, 51, 51, 52, 52, 52, 52, + 52, 52, 52, 53, 53, 53, 53, 53, + 53, 53, 54, 54, 54, 54, 54, 54, + 54, 55, 55, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 56, 56, 57, + 57, 57, 57, 57, 57, 57, 58, 58, + 58, 58, 58, 58, 58, 59, 59, 59, + 59, 59, 59, 59, 60, 60, 60, 60, + 60, 60, 60, 61, 61, 61, 61, 61, + 61, 61, 62, 62, 62, 62, 62, 62, + 62, 63, 63, 63, 63, 63, 63, 63, + 64, 64, 64, 64, 64, 64, 64, 65, + 65, 65, 65, 65, 65, 65, 66, 66, + 66, 66, 66, 66, 66, 67, 67, 67, + 67, 67, 67, 67, 68, 68, 68, 68, + 68, 68, 68, 69, 69, 69, 69, 69, + 69, 69, 70, 70, 70, 70, 70, 70, + 70, 71, 71, 71, 71, 71, 71, 71, + 72, 72, 72, 72, 72, 72, 72, 73, + 73, 73, 73, 73, 73, 73, 74, 74, + 74, 74, 74, 74, 74, 75, 75, 75, + 75, 75, 75, 75, 76, 76, 76, 76, + 76, 76, 76, 77, 77, 77, 77, 77, + 77, 77, 78, 78, 78, 78, 78, 78, + 78, 79, 79, 79, 79, 79, 79, 79, + 80, 80, 80, 80, 80, 80, 80, 81, + 81, 81, 81, 81, 81, 81, 82, 82, + 82, 82, 82, 82, 82, 83, 83, 83, + 83, 83, 83, 83, 84, 84, 84, 84, + 84, 84, 84, 85, 85, 85, 85, 85, + 85, 85, 86, 86, 86, 86, 86, 86, + 86, 87, 87, 87, 87, 87, 87, 87, + 88, 88, 88, 88, 88, 88, 88, 89, + 89, 89, 89, 89, 89, 89, 90, 90, + 90, 90, 90, 90, 90, 91, 91, 91, + 91, 91, 91, 91, 92, 92, 92, 92, + 92, 92, 92, 93, 93, 93, 93, 93, + 93, 93, 94, 94, 94, 94, 94, 94, + 94, 95, 95, 95, 95, 95, 95, 95, + 96, 96, 96, 96, 96, 96, 96, 97, + 97, 97, 97, 97, 97, 97, 98, 98, + 98, 98, 98, 98, 98, 99, 99, 99, + 99, 99, 99, 99, 100, 100, 100, 100, + 100, 100, 100, 101, 101, 101, 101, 101, + 101, 101, 102, 102, 102, 102, 102, 102, + 102, 103, 103, 103, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 104, 104, 105, + 105, 105, 105, 105, 105, 105, 106, 106, + 106, 106, 106, 106, 106, 107, 107, 107, + 107, 107, 107, 107, 108, 108, 108, 108, + 108, 108, 108, 109, 109, 109, 109, 109, + 109, 109, 110, 110, 110, 110, 110, 110, + 110, 111, 111, 111, 111, 111, 111, 111, + 112, 112, 112, 112, 112, 112, 112, 113, + 113, 113, 113, 113, 113, 113, 114, 114, + 114, 114, 114, 114, 114, 115, 115, 115, + 115, 115, 115, 115, 116, 116, 116, 116, + 116, 116, 116, 117, 117, 117, 117, 117, + 117, 117, 118, 118, 118, 118, 118, 118, + 118, 119, 119, 119, 119, 119, 119, 119, + 120, 120, 120, 120, 120, 120, 120, 121, + 121, 121, 121, 121, 121, 121, 122, 122, + 122, 122, 122, 122, 122, 123, 123, 123, + 123, 123, 123, 123, 124, 124, 124, 124, + 124, 124, 124, 125, 125, 125, 125, 125, + 125, 125, 126, 126, 126, 126, 126, 126, + 126, 127, 127, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 128, 128, 129, + 129, 129, 129, 129, 129, 129, 130, 130, + 130, 130, 130, 130, 130, 131, 131, 131, + 131, 131, 131, 131, 132, 132, 132, 132, + 132, 132, 132, 133, 133, 133, 133, 133, + 133, 133, 134, 134, 134, 134, 134, 134, + 134, 135, 135, 135, 135, 135, 135, 135, + 136, 136, 136, 136, 136, 136, 136, 137, + 137, 137, 137, 137, 137, 137, 138, 138, + 138, 138, 138, 138, 138, 139, 139, 139, + 139, 139, 139, 139, 140, 140, 140, 140, + 140, 140, 140, 141, 141, 141, 141, 141, + 141, 141, 142, 142, 142, 142, 142, 142, + 142, 143, 143, 143, 143, 143, 143, 143, + 144, 144, 144, 144, 144, 144, 144, 145, + 145, 145, 145, 145, 145, 145, 146, 146, + 146, 146, 146, 146, 146, 147, 147, 147, + 147, 147, 147, 147, 148, 148, 148, 148, + 148, 148, 148, 149, 149, 149, 149, 149, + 149, 149, 150, 150, 150, 150, 150, 150, + 150, 151, 151, 151, 151, 151, 151, 151, + 152, 152, 152, 152, 152, 152, 152, 153, + 153, 153, 153, 153, 153, 153, 154, 154, + 154, 154, 154, 154, 154, 155, 155, 155, + 155, 155, 155, 155, 156, 156, 156, 156, + 156, 156, 156, 157, 157, 157, 157, 157, + 157, 157, 158, 158, 158, 158, 158, 158, + 158, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 160, 160, 161, + 161, 161, 161, 161, 161, 161, 162, 162, + 162, 162, 162, 162, 162, 163, 163, 163, + 163, 163, 163, 163, 164, 164, 164, 164, + 164, 164, 164, 165, 165, 165, 165, 165, + 165, 165, 166, 166, 166, 166, 166, 166, + 166, 167, 167, 167, 167, 167, 167, 167, + 168, 168, 168, 168, 168, 168, 168, 169, + 169, 169, 169, 169, 169, 169, 170, 170, + 170, 170, 170, 170, 170, 171, 171, 171, + 171, 171, 171, 171, 172, 172, 172, 172, + 172, 172, 172, 173, 173, 173, 173, 173, + 173, 173, 174, 174, 174, 174, 174, 174, + 174, 175, 175, 175, 175, 175, 175, 175, + 176, 176, 176, 176, 176, 176, 176, 177, + 177, 177, 177, 177, 177, 177, 178, 178, + 178, 178, 178, 178, 178, 179, 179, 179, + 179, 179, 179, 179, 180, 180, 180, 180, + 180, 180, 180, 181, 181, 181, 181, 181, + 181, 181, 182, 182, 182, 182, 182, 182, + 182, 183, 183, 183, 183, 183, 183, 183, + 184, 184, 184, 184, 184, 184, 184, 185, + 185, 185, 185, 185, 185, 185, 186, 186, + 186, 186, 186, 186, 186, 187, 187, 187, + 187, 187, 187, 187, 188, 188, 188, 188, + 188, 188, 188, 189, 189, 189, 189, 189, + 189, 189, 190, 190, 190, 190, 190, 190, + 190, 191, 191, 191, 191, 191, 191, 191, + 192, 192, 192, 192, 192, 192, 192, 193, + 193, 193, 193, 193, 193, 193, 194, 194, + 194, 194, 194, 194, 194, 195, 195, 195, + 195, 195, 195, 195, 196, 196, 196, 196, + 196, 196, 196, 197, 197, 197, 197, 197, + 197, 197, 198, 198, 198, 198, 198, 198, + 198, 199, 199, 199, 199, 199, 199, 199, + 200, 200, 200, 200, 200, 200, 200, 201, + 201, 201, 201, 201, 201, 201, 202, 202, + 202, 202, 202, 202, 202, 203, 203, 203, + 203, 203, 203, 203, 204, 204, 204, 204, + 204, 204, 204, 205, 205, 205, 205, 205, + 205, 205, 206, 206, 206, 206, 206, 206, + 206, 207, 207, 207, 207, 207, 207, 207, + 208, 208, 208, 208, 208, 208, 208, 209, + 209, 209, 209, 209, 209, 209, 210, 210, + 210, 210, 210, 210, 210, 211, 211, 211, + 211, 211, 211, 211, 212, 212, 212, 212, + 212, 212, 212, 213, 213, 213, 213, 213, + 213, 213, 214, 214, 214, 214, 214, 214, + 214, 215, 215, 215, 215, 215, 215, 215, + 216, 216, 216, 216, 216, 216, 216, 217, + 217, 217, 217, 217, 217, 217, 218, 218, + 218, 218, 218, 218, 218, 219, 219, 219, + 219, 219, 219, 219, 220, 220, 220, 220, + 220, 220, 220, 221, 221, 221, 221, 221, + 221, 221, 222, 222, 222, 222, 222, 222, + 222, 223, 223, 223, 223, 223, 223, 223, + 224, 224, 224, 224, 224, 224, 224, 225, + 225, 225, 225, 225, 225, 225, 226, 226, + 226, 226, 226, 226, 226, 227, 227, 227, + 227, 227, 227, 227, 228, 228, 228, 228, + 228, 228, 228, 229, 229, 229, 229, 229, + 229, 229, 230, 230, 230, 230, 230, 230, + 230, 231, 231, 231, 231, 231, 231, 231, + 232, 232, 232, 232, 232, 232, 232, 233, + 233, 233, 233, 233, 233, 233, 234, 234, + 234, 234, 234, 234, 234, 235, 235, 235, + 235, 235, 235, 235, 236, 236, 236, 236, + 236, 236, 236, 237, 237, 237, 237, 237, + 237, 237, 238, 238, 238, 238, 238, 238, + 238, 239, 239, 239, 239, 239, 239, 239, + 240, 240, 240, 240, 240, 240, 240, 241, + 241, 241, 241, 241, 241, 241, 242, 242, + 242, 242, 242, 242, 242, 243, 243, 243, + 243, 243, 243, 243, 244, 244, 244, 244, + 244, 244, 244, 245, 245, 245, 245, 245, + 245, 245, 246, 246, 246, 246, 246, 246, + 246, 247, 247, 247, 247, 247, 247, 247, + 248, 248, 248, 248, 248, 248, 248, 249, + 249, 249, 249, 249, 249, 249, 250, 250, + 250, 250, 250, 250, 250, 251, 251, 251, + 251, 251, 251, 251, 252, 252, 252, 252, + 252, 252, 252, 253, 253, 253, 253, 253, + 253, 253, 254, 254, 254, 254, 254, 254, + 254, 255, 255, 255, 255, 255, 255, 255, +}; + +const uint8_t detex_division_by_5_table[1280] = { + 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 4, 4, 4, 4, + 4, 5, 5, 5, 5, 5, 6, 6, + 6, 6, 6, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 9, 9, 9, + 9, 9, 10, 10, 10, 10, 10, 11, + 11, 11, 11, 11, 12, 12, 12, 12, + 12, 13, 13, 13, 13, 13, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 17, 17, 17, + 17, 17, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 20, 20, 20, 20, + 20, 21, 21, 21, 21, 21, 22, 22, + 22, 22, 22, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 27, + 27, 27, 27, 27, 28, 28, 28, 28, + 28, 29, 29, 29, 29, 29, 30, 30, + 30, 30, 30, 31, 31, 31, 31, 31, + 32, 32, 32, 32, 32, 33, 33, 33, + 33, 33, 34, 34, 34, 34, 34, 35, + 35, 35, 35, 35, 36, 36, 36, 36, + 36, 37, 37, 37, 37, 37, 38, 38, + 38, 38, 38, 39, 39, 39, 39, 39, + 40, 40, 40, 40, 40, 41, 41, 41, + 41, 41, 42, 42, 42, 42, 42, 43, + 43, 43, 43, 43, 44, 44, 44, 44, + 44, 45, 45, 45, 45, 45, 46, 46, + 46, 46, 46, 47, 47, 47, 47, 47, + 48, 48, 48, 48, 48, 49, 49, 49, + 49, 49, 50, 50, 50, 50, 50, 51, + 51, 51, 51, 51, 52, 52, 52, 52, + 52, 53, 53, 53, 53, 53, 54, 54, + 54, 54, 54, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, + 57, 57, 58, 58, 58, 58, 58, 59, + 59, 59, 59, 59, 60, 60, 60, 60, + 60, 61, 61, 61, 61, 61, 62, 62, + 62, 62, 62, 63, 63, 63, 63, 63, + 64, 64, 64, 64, 64, 65, 65, 65, + 65, 65, 66, 66, 66, 66, 66, 67, + 67, 67, 67, 67, 68, 68, 68, 68, + 68, 69, 69, 69, 69, 69, 70, 70, + 70, 70, 70, 71, 71, 71, 71, 71, + 72, 72, 72, 72, 72, 73, 73, 73, + 73, 73, 74, 74, 74, 74, 74, 75, + 75, 75, 75, 75, 76, 76, 76, 76, + 76, 77, 77, 77, 77, 77, 78, 78, + 78, 78, 78, 79, 79, 79, 79, 79, + 80, 80, 80, 80, 80, 81, 81, 81, + 81, 81, 82, 82, 82, 82, 82, 83, + 83, 83, 83, 83, 84, 84, 84, 84, + 84, 85, 85, 85, 85, 85, 86, 86, + 86, 86, 86, 87, 87, 87, 87, 87, + 88, 88, 88, 88, 88, 89, 89, 89, + 89, 89, 90, 90, 90, 90, 90, 91, + 91, 91, 91, 91, 92, 92, 92, 92, + 92, 93, 93, 93, 93, 93, 94, 94, + 94, 94, 94, 95, 95, 95, 95, 95, + 96, 96, 96, 96, 96, 97, 97, 97, + 97, 97, 98, 98, 98, 98, 98, 99, + 99, 99, 99, 99, 100, 100, 100, 100, + 100, 101, 101, 101, 101, 101, 102, 102, + 102, 102, 102, 103, 103, 103, 103, 103, + 104, 104, 104, 104, 104, 105, 105, 105, + 105, 105, 106, 106, 106, 106, 106, 107, + 107, 107, 107, 107, 108, 108, 108, 108, + 108, 109, 109, 109, 109, 109, 110, 110, + 110, 110, 110, 111, 111, 111, 111, 111, + 112, 112, 112, 112, 112, 113, 113, 113, + 113, 113, 114, 114, 114, 114, 114, 115, + 115, 115, 115, 115, 116, 116, 116, 116, + 116, 117, 117, 117, 117, 117, 118, 118, + 118, 118, 118, 119, 119, 119, 119, 119, + 120, 120, 120, 120, 120, 121, 121, 121, + 121, 121, 122, 122, 122, 122, 122, 123, + 123, 123, 123, 123, 124, 124, 124, 124, + 124, 125, 125, 125, 125, 125, 126, 126, + 126, 126, 126, 127, 127, 127, 127, 127, + 128, 128, 128, 128, 128, 129, 129, 129, + 129, 129, 130, 130, 130, 130, 130, 131, + 131, 131, 131, 131, 132, 132, 132, 132, + 132, 133, 133, 133, 133, 133, 134, 134, + 134, 134, 134, 135, 135, 135, 135, 135, + 136, 136, 136, 136, 136, 137, 137, 137, + 137, 137, 138, 138, 138, 138, 138, 139, + 139, 139, 139, 139, 140, 140, 140, 140, + 140, 141, 141, 141, 141, 141, 142, 142, + 142, 142, 142, 143, 143, 143, 143, 143, + 144, 144, 144, 144, 144, 145, 145, 145, + 145, 145, 146, 146, 146, 146, 146, 147, + 147, 147, 147, 147, 148, 148, 148, 148, + 148, 149, 149, 149, 149, 149, 150, 150, + 150, 150, 150, 151, 151, 151, 151, 151, + 152, 152, 152, 152, 152, 153, 153, 153, + 153, 153, 154, 154, 154, 154, 154, 155, + 155, 155, 155, 155, 156, 156, 156, 156, + 156, 157, 157, 157, 157, 157, 158, 158, + 158, 158, 158, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 161, 161, 161, + 161, 161, 162, 162, 162, 162, 162, 163, + 163, 163, 163, 163, 164, 164, 164, 164, + 164, 165, 165, 165, 165, 165, 166, 166, + 166, 166, 166, 167, 167, 167, 167, 167, + 168, 168, 168, 168, 168, 169, 169, 169, + 169, 169, 170, 170, 170, 170, 170, 171, + 171, 171, 171, 171, 172, 172, 172, 172, + 172, 173, 173, 173, 173, 173, 174, 174, + 174, 174, 174, 175, 175, 175, 175, 175, + 176, 176, 176, 176, 176, 177, 177, 177, + 177, 177, 178, 178, 178, 178, 178, 179, + 179, 179, 179, 179, 180, 180, 180, 180, + 180, 181, 181, 181, 181, 181, 182, 182, + 182, 182, 182, 183, 183, 183, 183, 183, + 184, 184, 184, 184, 184, 185, 185, 185, + 185, 185, 186, 186, 186, 186, 186, 187, + 187, 187, 187, 187, 188, 188, 188, 188, + 188, 189, 189, 189, 189, 189, 190, 190, + 190, 190, 190, 191, 191, 191, 191, 191, + 192, 192, 192, 192, 192, 193, 193, 193, + 193, 193, 194, 194, 194, 194, 194, 195, + 195, 195, 195, 195, 196, 196, 196, 196, + 196, 197, 197, 197, 197, 197, 198, 198, + 198, 198, 198, 199, 199, 199, 199, 199, + 200, 200, 200, 200, 200, 201, 201, 201, + 201, 201, 202, 202, 202, 202, 202, 203, + 203, 203, 203, 203, 204, 204, 204, 204, + 204, 205, 205, 205, 205, 205, 206, 206, + 206, 206, 206, 207, 207, 207, 207, 207, + 208, 208, 208, 208, 208, 209, 209, 209, + 209, 209, 210, 210, 210, 210, 210, 211, + 211, 211, 211, 211, 212, 212, 212, 212, + 212, 213, 213, 213, 213, 213, 214, 214, + 214, 214, 214, 215, 215, 215, 215, 215, + 216, 216, 216, 216, 216, 217, 217, 217, + 217, 217, 218, 218, 218, 218, 218, 219, + 219, 219, 219, 219, 220, 220, 220, 220, + 220, 221, 221, 221, 221, 221, 222, 222, + 222, 222, 222, 223, 223, 223, 223, 223, + 224, 224, 224, 224, 224, 225, 225, 225, + 225, 225, 226, 226, 226, 226, 226, 227, + 227, 227, 227, 227, 228, 228, 228, 228, + 228, 229, 229, 229, 229, 229, 230, 230, + 230, 230, 230, 231, 231, 231, 231, 231, + 232, 232, 232, 232, 232, 233, 233, 233, + 233, 233, 234, 234, 234, 234, 234, 235, + 235, 235, 235, 235, 236, 236, 236, 236, + 236, 237, 237, 237, 237, 237, 238, 238, + 238, 238, 238, 239, 239, 239, 239, 239, + 240, 240, 240, 240, 240, 241, 241, 241, + 241, 241, 242, 242, 242, 242, 242, 243, + 243, 243, 243, 243, 244, 244, 244, 244, + 244, 245, 245, 245, 245, 245, 246, 246, + 246, 246, 246, 247, 247, 247, 247, 247, + 248, 248, 248, 248, 248, 249, 249, 249, + 249, 249, 250, 250, 250, 250, 250, 251, + 251, 251, 251, 251, 252, 252, 252, 252, + 252, 253, 253, 253, 253, 253, 254, 254, + 254, 254, 254, 255, 255, 255, 255, 255, +}; +