Initial support of KTX texture load using TinyKTX.
diff --git a/README.md b/README.md
index f2f9e1e..2fe5f32 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
   * [x] Image save
 * Extensions
   * [x] Draco mesh decoding(`TINYGLTF_ENABLE_DRACO` required)
-  * [x] KTX image support(`TINYGLTF_ENABLE_KTX` required)
+  * [x] KTX image support(no mipmap. `TINYGLTF_ENABLE_KTX` required)
 
 ## Examples
 
@@ -83,6 +83,7 @@
   * [ ] OpenEXR extension through TinyEXR.
 * [ ] 16bit PNG support in Serialization
 * [ ] Write example and tests for `animation` and `skin`
+* [ ] mipmap support for KTX image.
 
 ## Licenses
 
@@ -94,12 +95,15 @@
 * base64 : Copyright (C) 2004-2008 René Nyffenegger
 * stb_image.h : v2.08 - public domain image loader - [Github link](https://github.com/nothings/stb/blob/master/stb_image.h)
 * stb_image_write.h : v1.09 - public domain image writer - [Github link](https://github.com/nothings/stb/blob/master/stb_image_write.h)
+* tinyktx.h : Copyright (c) 2019, DeanoC. Licensed under 2 clause BSD license.
 
 
 ## Build and example
 
 Copy `stb_image.h`, `stb_image_write.h`, `json.hpp` and `tiny_gltf.h` to your project.
 
+If you enable KTX support(`TINYGLTF_ENABLE_KTX`), Copy `tinyktx.h` to your project.
+
 ### Loading glTF 2.0 model
 
 ```c++
@@ -146,6 +150,7 @@
 * `TINYGLTF_NO_INCLUDE_STB_IMAGE `: Disable including `stb_image.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
 * `TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE `: Disable including `stb_image_write.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
 * `TINYGLTF_ENABLE_KTX` : Enable loading KTX images( https://www.khronos.org/opengles/sdk/tools/KTX/ ) using `tiny_ktx.h`. Supported MIME is `image/ktx` ( https://github.com/KhronosGroup/glTF/issues/835 ). See `models/Cube-KTX` for details. Application also defined `TINYKTX_IMPLEMENTATION` in **one** .cc file.
+  * `TINYGLTF_NO_INCLUDE_TINYKTX` : Disable including `tinyktx.h` from within `tiny_gltf.h` because it has been already included before or you want to include it using custom path before including `tiny_gltf.h`.
 
 
 ### Saving gltTF 2.0 model
@@ -184,9 +189,6 @@
 $ ./tester_noexcept
 ```
 
-## Third party licenses
+## Third party licenses used in unit tests
 
-* json.hpp : Licensed under the MIT License <http://opensource.org/licenses/MIT>. Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.
-* stb_image : Public domain.
 * catch : Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. Distributed under the Boost Software License, Version 1.0.
-* tiny_ktx : Copyright (c) 2019, DeanoC. Licensed under 2 clause BSD license.
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 83ededc..888053e 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -492,14 +492,19 @@
   std::string name;
   int width;
   int height;
-  int component;
+
+  //
+  // For KTX image, component, bits and pixel_type will be set to `0`, and KTX attributes are stored in `extras`.
+  // FIXME(syoyo): Find more proper way to handle KTX and non-KTX image by keeping backward-compatibility as much as possible.
+  //
+  int component;   // The number of channel components in the image.
   int bits;        // bit depth per channel. 8(byte), 16 or 32.
   int pixel_type;  // pixel type(TINYGLTF_COMPONENT_TYPE_***). usually
                    // UBYTE(bits = 8) or USHORT(bits = 16)
   std::vector<unsigned char> image;
   int bufferView;        // (required if no uri)
   std::string mimeType;  // (required if no uri) ["image/jpeg", "image/png",
-                         // "image/bmp", "image/gif"]
+                         // "image/bmp", "image/gif", etc]
   std::string uri;       // (required if no mimeType)
   Value extras;
   ExtensionMap extensions;
@@ -1124,6 +1129,12 @@
 #include "draco/core/decoder_buffer.h"
 #endif
 
+#ifdef TINYGLTF_ENABLE_KTX
+#ifndef TINYGLTF_NO_INCLUDE_TINY_KTX
+#include "tiny_ktx.h"
+#endif
+#endif
+
 #ifndef TINYGLTF_NO_STB_IMAGE
 #ifndef TINYGLTF_NO_INCLUDE_STB_IMAGE
 #include "stb_image.h"
@@ -1679,8 +1690,8 @@
   load_image_user_data_ = user_data;
 }
 
-#ifndef TINYGLTF_NO_STB_IMAGE
-bool LoadImageData(Image *image, const int image_idx, std::string *err,
+#if !defined(TINYGLTF_NO_STB_IMAGE)
+bool LoadImageDataSTB(Image *image, const int image_idx, std::string *err,
                    std::string *warn, int req_width, int req_height,
                    const unsigned char *bytes, int size, void *user_data) {
   (void)user_data;
@@ -1777,6 +1788,207 @@
 }
 #endif
 
+#if defined(TINYGLTF_ENABLE_KTX)
+
+struct SimpleVFile {
+  std::string *err = nullptr;
+  const uint8_t *data = nullptr;
+  size_t pos = 0;
+  size_t len = 0;
+};
+
+static void tinyktxCallbackError(void *user, char const *msg) {
+  SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user);
+
+  if (ss->err) {
+    (*ss->err) += "Tiny_Ktx ERROR: " + std::string(msg) + "\n";
+  }
+}
+
+
+static void *tinyktxCallbackAlloc(void *user, size_t size) {
+  (void)user;
+  return malloc(size);
+};
+
+static void tinyktxCallbackFree(void *user, void *data) {
+  (void)user;
+  free(data);
+};
+
+static size_t tinyktxCallbackRead(void *user, void* data, size_t size) {
+  SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user);
+
+  if ((ss->pos + size) >= ss->len) {
+    if (ss->err) {
+      std::stringstream msg;
+      msg << "KTX read: Invalid data length. pos = " << ss->pos << ", len = " << ss->len << ", requested size to read = " << size << "\n";
+      (*ss->err) += msg.str();
+    }
+    return size_t(0);
+  }
+
+  memcpy(data, ss->data + ss->pos, size);
+
+  return size;
+};
+
+static bool tinyktxCallbackSeek(void *user, int64_t offset) {
+
+  SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user);
+
+  if ((offset < 0) || (size_t(offset) >= ss->len)) {
+    if (ss->err) {
+      std::stringstream msg;
+      msg << "KTX read: Invalid data offset. len = " << ss->len << ", requested offset = " << offset << "\n";
+      (*ss->err) += msg.str();
+    }
+
+    return false;
+  }
+
+  ss->pos = offset;
+  return true;
+
+}
+
+static int64_t tinyktxCallbackTell(void *user) {
+  SimpleVFile *ss = reinterpret_cast<SimpleVFile *>(user);
+
+  return int64_t(ss->pos);
+};
+
+
+bool LoadImageDataKTX(Image *image, const int image_idx, std::string *err,
+                   std::string *warn, int req_width, int req_height,
+                   const unsigned char *bytes, int size, void *user_data) {
+  (void)user_data;
+  (void)warn;
+  (void)req_width;
+  (void)req_height;
+
+  TinyKtx_Callbacks callbacks {
+                  &tinyktxCallbackError,
+                  &tinyktxCallbackAlloc,
+                  &tinyktxCallbackFree,
+                  tinyktxCallbackRead,
+                  &tinyktxCallbackSeek,
+                  &tinyktxCallbackTell
+  };
+
+  SimpleVFile vfile;
+  vfile.err = err;
+  vfile.pos = 0;
+  vfile.data = bytes;
+  vfile.len = size;
+
+  auto ctx =  TinyKtx_CreateContext( &callbacks, reinterpret_cast<void *>(&vfile) );
+  TinyKtx_ReadHeader(ctx);
+  uint32_t w = TinyKtx_Width(ctx);
+  uint32_t h = TinyKtx_Height(ctx);
+  uint32_t d = TinyKtx_Depth(ctx);
+
+  TinyKtx_Format fmt = TinyKtx_GetFormat(ctx);
+
+  if(fmt == TKTX_UNDEFINED) {
+      TinyKtx_DestroyContext(ctx);
+      return false;
+  }
+
+  int num_mipmaps = TinyKtx_NumberOfMipmaps(ctx);
+  if (num_mipmaps < 1) {
+    // ???
+    if (err) {
+      (*err) += "Number of mipmaps are zero for KTX image[" + std::to_string(image_idx) + ".\n";
+    }
+    TinyKtx_DestroyContext(ctx);
+    return false;
+  }
+
+  {
+    // TODO(syoyo): Support mipmap.
+    int miplevel = 0;
+
+    size_t byte_count = TinyKtx_ImageSize(ctx, miplevel);
+    if (byte_count == 0) {
+      // ???
+      if (err) {
+        (*err) += "KTX image [" + std::to_string(image_idx) + "] has zero bytes.\n";
+      }
+
+      TinyKtx_DestroyContext(ctx);
+      return false;
+    }
+
+    image->image.resize(byte_count);
+    memcpy(image->image.data(), TinyKtx_ImageRawData(ctx, miplevel), byte_count);
+
+    TinyKtx_DestroyContext(ctx);
+
+    // Set to 0 for KTX image.
+    image->pixel_type = 0;
+    image->bits = 0;
+    image->component = 0;
+
+    // extras for KTX
+    Value::Object extras;
+    extras["ktx_format"] = Value(int(fmt)); // TODO(syoyo): Store OpenGL format
+    extras["depth"] = Value(int(d));
+    extras["byteCount"] = Value(int(byte_count)); // Assume image size is < 2GB
+    image->extras = Value(extras);
+    // TODO(syoyo): Store more KTX attributes.
+  }
+
+  image->width = w;
+  image->height = h;
+
+  return true;
+}
+#endif
+
+bool LoadImageData(Image *image, const int image_idx, std::string *err,
+                   std::string *warn, int req_width, int req_height,
+                   const unsigned char *bytes, int size, void *user_data) {
+
+  bool ret = false;
+
+#if defined(TINYGLTF_ENABLE_KTX)
+  // Try KTX image
+
+  ret = tinygltf::LoadImageDataKTX(image, image_idx, err, warn, req_width, req_height,
+                   bytes, size, user_data);
+
+  if (ret) {
+    return true;
+  }
+
+#endif
+
+#if defined(TINYGLTF_NO_STB_IMAGE)
+  // Try to load images using stb_image(png, gif, bmp, tga, ...)
+
+  ret = tinygltf::LoadImageDataSTB(image, image_idx, err, warn, req_width, req_height,
+                   bytes, size, user_data);
+
+  if (ret) {
+    return true;
+  }
+
+#endif
+
+  (void)image;
+  (void)image_idx;
+  (void)err;
+  (void)warn;
+  (void)req_width;
+  (void)req_height;
+  (void)bytes;
+  (void)size;
+  (void)user_data;
+
+  return false;
+}
+
 void TinyGLTF::SetImageWriter(WriteImageDataFunction func, void *user_data) {
   WriteImageData = func;
   write_image_user_data_ = user_data;
@@ -1800,6 +2012,8 @@
   std::string header;
   std::vector<unsigned char> data;
 
+  // TODO(LTE): Support ktx
+
   if (ext == "png") {
     if ((image->bits != 8) ||
         (image->pixel_type != TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE)) {
@@ -2047,6 +2261,10 @@
     return "bmp";
   } else if (mimeType == "image/gif") {
     return "gif";
+#if defined(TINYGLTF_ENABLE_KTX)
+  } else if (mimeType == "image/ktx") {
+    return "ktx";
+#endif
   }
 
   return "";
@@ -2107,6 +2325,13 @@
     return true;
   }
 
+#if defined(TINYGLTF_ENABLE_KTX)
+  header = "data:image/ktx;base64,";
+  if (in.find(header) == 0) {
+    return true;
+  }
+#endif
+
   header = "data:text/plain;base64,";
   if (in.find(header) == 0) {
     return true;
@@ -2160,6 +2385,16 @@
     }
   }
 
+#if defined(TINYGLTF_ENABLE_KTX)
+  if (data.empty()) {
+    header = "data:image/ktx;base64,";
+    if (in.find(header) == 0) {
+      mime_type = "image/ktx";
+      data = base64_decode(in.substr(header.size()));  // cut mime string.
+    }
+  }
+#endif
+
   if (data.empty()) {
     header = "data:text/plain;base64,";
     if (in.find(header) == 0) {
diff --git a/tinyktx.h b/tinyktx.h
new file mode 100644
index 0000000..027de9a
--- /dev/null
+++ b/tinyktx.h
@@ -0,0 +1,1600 @@
+// BSD clause 2 license see full LICENSE text at end of file
+#pragma once
+#ifndef TINY_KTX_TINYKTX_H
+#define TINY_KTX_TINYKTX_H
+
+#ifndef TINYKTX_HAVE_UINTXX_T
+#include <stdint.h> 	// for uint32_t and int64_t
+#endif
+#ifndef TINYKTX_HAVE_BOOL
+#include <stdbool.h>	// for bool
+#endif
+#ifndef TINYKTX_HAVE_SIZE_T
+#include <stddef.h>		// for size_t
+#endif
+#ifndef TINYKTX_HAVE_MEMCPY
+#include <string.h> 	// for memcpy
+#endif
+
+// if you don't want the helper format function or already have GL defines
+// comment these two lines out
+//#define TINYKTX_WANT_TINYKTX_FORMAT 0
+//#define TINYKTX_WANT_FAKE_GL_DEFINES 0
+
+
+#ifndef TINYKTX_WANT_TINYKTX_FORMAT
+#define TINYKTX_WANT_TINYKTX_FORMAT 1
+#define TINYKTX_WANT_FAKE_GL_DEFINES 1
+#endif
+
+#ifndef TINYKTX_WANT_FAKE_GL_DEFINES
+#define TINYKTX_WANT_FAKE_GL_DEFINES 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TINYKTX_MAX_MIPMAPLEVELS 16
+
+typedef struct TinyKtx_Context *TinyKtx_ContextHandle;
+
+typedef void *(*TinyKtx_AllocFunc)(void *user, size_t size);
+typedef void (*TinyKtx_FreeFunc)(void *user, void *memory);
+typedef size_t (*TinyKtx_ReadFunc)(void *user, void *buffer, size_t byteCount);
+typedef bool (*TinyKtx_SeekFunc)(void *user, int64_t offset);
+typedef int64_t (*TinyKtx_TellFunc)(void *user);
+typedef void (*TinyKtx_ErrorFunc)(void *user, char const *msg);
+
+typedef struct TinyKtx_Callbacks {
+	TinyKtx_ErrorFunc error;
+	TinyKtx_AllocFunc alloc;
+	TinyKtx_FreeFunc free;
+	TinyKtx_ReadFunc read;
+	TinyKtx_SeekFunc seek;
+	TinyKtx_TellFunc tell;
+} TinyKtx_Callbacks;
+
+TinyKtx_ContextHandle TinyKtx_CreateContext(TinyKtx_Callbacks const *callbacks, void *user);
+void TinyKtx_DestroyContext(TinyKtx_ContextHandle handle);
+
+// reset like you reuse the context for another file (saves an alloc/free cycle)
+void TinyKtx_Reset(TinyKtx_ContextHandle handle);
+
+// call this to read the header file should already be at the start of the KTX data
+bool TinyKtx_ReadHeader(TinyKtx_ContextHandle handle);
+
+// this is slow linear search. TODO add iterator style reading of key value pairs
+bool TinyKtx_GetValue(TinyKtx_ContextHandle handle, char const *key, void const **value);
+
+bool TinyKtx_Is1D(TinyKtx_ContextHandle handle);
+bool TinyKtx_Is2D(TinyKtx_ContextHandle handle);
+bool TinyKtx_Is3D(TinyKtx_ContextHandle handle);
+bool TinyKtx_IsCubemap(TinyKtx_ContextHandle handle);
+bool TinyKtx_IsArray(TinyKtx_ContextHandle handle);
+
+bool TinyKtx_Dimensions(TinyKtx_ContextHandle handle, uint32_t* width, uint32_t* height, uint32_t* depth, uint32_t* slices);
+uint32_t TinyKtx_Width(TinyKtx_ContextHandle handle);
+uint32_t TinyKtx_Height(TinyKtx_ContextHandle handle);
+uint32_t TinyKtx_Depth(TinyKtx_ContextHandle handle);
+uint32_t TinyKtx_ArraySlices(TinyKtx_ContextHandle handle);
+
+bool TinyKtx_GetFormatGL(TinyKtx_ContextHandle handle, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize, uint32_t* glbaseinternalformat);
+
+bool TinyKtx_NeedsGenerationOfMipmaps(TinyKtx_ContextHandle handle);
+bool TinyKtx_NeedsEndianCorrecting(TinyKtx_ContextHandle handle);
+
+uint32_t TinyKtx_NumberOfMipmaps(TinyKtx_ContextHandle handle);
+uint32_t TinyKtx_ImageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel);
+
+// data return by ImageRawData is owned by the context. Don't free it!
+void const *TinyKtx_ImageRawData(TinyKtx_ContextHandle handle, uint32_t mipmaplevel);
+
+typedef void (*TinyKtx_WriteFunc)(void *user, void const *buffer, size_t byteCount);
+
+typedef struct TinyKtx_WriteCallbacks {
+	TinyKtx_ErrorFunc error;
+	TinyKtx_AllocFunc alloc;
+	TinyKtx_FreeFunc free;
+	TinyKtx_WriteFunc write;
+} TinyKtx_WriteCallbacks;
+
+
+bool TinyKtx_WriteImageGL(TinyKtx_WriteCallbacks const *callbacks,
+													void *user,
+													uint32_t width,
+													uint32_t height,
+													uint32_t depth,
+													uint32_t slices,
+													uint32_t mipmaplevels,
+													uint32_t format,
+													uint32_t internalFormat,
+													uint32_t baseFormat,
+													uint32_t type,
+													uint32_t typeSize,
+													bool cubemap,
+													uint32_t const *mipmapsizes,
+													void const **mipmaps);
+
+#if TINYKTX_WANT_TINYKTX_FORMAT != 0
+// ktx is based on GL (slightly confusing imho) texture format system
+// there is format, internal format, type etc.
+
+// we try and expose a more dx12/vulkan/metal style of format
+// but obviously still need to GL data so bare with me.
+// a TinyKTX_Format is the equivilent to GL/KTX Format and Type
+// the API doesn't expose the actual values (which come from GL itself)
+// but provide an API call to crack them back into the actual GL values).
+
+// this may look very similar to Vulkan/Dx12 format (its not but related)
+// these are even more closely related to my gfx_imageformat library...
+
+typedef enum TinyKtx_Format {
+	TKTX_UNDEFINED = 0,
+	TKTX_R4G4_UNORM_PACK8,
+	TKTX_R4G4B4A4_UNORM_PACK16,
+	TKTX_B4G4R4A4_UNORM_PACK16,
+	TKTX_R5G6B5_UNORM_PACK16,
+	TKTX_B5G6R5_UNORM_PACK16,
+	TKTX_R5G5B5A1_UNORM_PACK16,
+	TKTX_B5G5R5A1_UNORM_PACK16,
+	TKTX_A1R5G5B5_UNORM_PACK16,
+
+	TKTX_R8_UNORM,
+	TKTX_R8_SNORM,
+	TKTX_R8_UINT,
+	TKTX_R8_SINT,
+	TKTX_R8_SRGB,
+
+	TKTX_R8G8_UNORM,
+	TKTX_R8G8_SNORM,
+	TKTX_R8G8_UINT,
+	TKTX_R8G8_SINT,
+	TKTX_R8G8_SRGB,
+
+	TKTX_R8G8B8_UNORM,
+	TKTX_R8G8B8_SNORM,
+	TKTX_R8G8B8_UINT,
+	TKTX_R8G8B8_SINT,
+	TKTX_R8G8B8_SRGB,
+	TKTX_B8G8R8_UNORM,
+	TKTX_B8G8R8_SNORM,
+	TKTX_B8G8R8_UINT,
+	TKTX_B8G8R8_SINT,
+	TKTX_B8G8R8_SRGB,
+
+	TKTX_R8G8B8A8_UNORM,
+	TKTX_R8G8B8A8_SNORM,
+	TKTX_R8G8B8A8_UINT,
+	TKTX_R8G8B8A8_SINT,
+	TKTX_R8G8B8A8_SRGB,
+	TKTX_B8G8R8A8_UNORM,
+	TKTX_B8G8R8A8_SNORM,
+	TKTX_B8G8R8A8_UINT,
+	TKTX_B8G8R8A8_SINT,
+	TKTX_B8G8R8A8_SRGB,
+
+	TKTX_A8B8G8R8_UNORM_PACK32,
+	TKTX_A8B8G8R8_SNORM_PACK32,
+	TKTX_A8B8G8R8_UINT_PACK32,
+	TKTX_A8B8G8R8_SINT_PACK32,
+	TKTX_A8B8G8R8_SRGB_PACK32,
+
+	TKTX_E5B9G9R9_UFLOAT_PACK32,
+	TKTX_A2R10G10B10_UNORM_PACK32,
+	TKTX_A2R10G10B10_UINT_PACK32,
+	TKTX_A2B10G10R10_UNORM_PACK32,
+	TKTX_A2B10G10R10_UINT_PACK32,
+	TKTX_B10G11R11_UFLOAT_PACK32,
+
+	TKTX_R16_UNORM,
+	TKTX_R16_SNORM,
+	TKTX_R16_UINT,
+	TKTX_R16_SINT,
+	TKTX_R16_SFLOAT,
+	TKTX_R16G16_UNORM,
+	TKTX_R16G16_SNORM,
+	TKTX_R16G16_UINT,
+	TKTX_R16G16_SINT,
+	TKTX_R16G16_SFLOAT,
+	TKTX_R16G16B16_UNORM,
+	TKTX_R16G16B16_SNORM,
+	TKTX_R16G16B16_UINT,
+	TKTX_R16G16B16_SINT,
+	TKTX_R16G16B16_SFLOAT,
+	TKTX_R16G16B16A16_UNORM,
+	TKTX_R16G16B16A16_SNORM,
+	TKTX_R16G16B16A16_UINT,
+	TKTX_R16G16B16A16_SINT,
+	TKTX_R16G16B16A16_SFLOAT,
+	TKTX_R32_UINT,
+	TKTX_R32_SINT,
+	TKTX_R32_SFLOAT,
+	TKTX_R32G32_UINT,
+	TKTX_R32G32_SINT,
+	TKTX_R32G32_SFLOAT,
+	TKTX_R32G32B32_UINT,
+	TKTX_R32G32B32_SINT,
+	TKTX_R32G32B32_SFLOAT,
+	TKTX_R32G32B32A32_UINT,
+	TKTX_R32G32B32A32_SINT,
+	TKTX_R32G32B32A32_SFLOAT,
+
+	TKTX_BC1_RGB_UNORM_BLOCK,
+	TKTX_BC1_RGB_SRGB_BLOCK,
+	TKTX_BC1_RGBA_UNORM_BLOCK,
+	TKTX_BC1_RGBA_SRGB_BLOCK,
+	TKTX_BC2_UNORM_BLOCK,
+	TKTX_BC2_SRGB_BLOCK,
+	TKTX_BC3_UNORM_BLOCK,
+	TKTX_BC3_SRGB_BLOCK,
+	TKTX_BC4_UNORM_BLOCK,
+	TKTX_BC4_SNORM_BLOCK,
+	TKTX_BC5_UNORM_BLOCK,
+	TKTX_BC5_SNORM_BLOCK,
+	TKTX_BC6H_UFLOAT_BLOCK,
+	TKTX_BC6H_SFLOAT_BLOCK,
+	TKTX_BC7_UNORM_BLOCK,
+	TKTX_BC7_SRGB_BLOCK,
+
+	TKTX_ETC2_R8G8B8_UNORM_BLOCK,
+	TKTX_ETC2_R8G8B8A1_UNORM_BLOCK,
+	TKTX_ETC2_R8G8B8A8_UNORM_BLOCK,
+	TKTX_ETC2_R8G8B8_SRGB_BLOCK,
+	TKTX_ETC2_R8G8B8A1_SRGB_BLOCK,
+	TKTX_ETC2_R8G8B8A8_SRGB_BLOCK,
+	TKTX_EAC_R11_UNORM_BLOCK,
+	TKTX_EAC_R11G11_UNORM_BLOCK,
+	TKTX_EAC_R11_SNORM_BLOCK,
+	TKTX_EAC_R11G11_SNORM_BLOCK,
+
+	TKTX_PVR_2BPP_BLOCK,
+	TKTX_PVR_2BPPA_BLOCK,
+	TKTX_PVR_4BPP_BLOCK,
+	TKTX_PVR_4BPPA_BLOCK,
+	TKTX_PVR_2BPP_SRGB_BLOCK,
+	TKTX_PVR_2BPPA_SRGB_BLOCK,
+	TKTX_PVR_4BPP_SRGB_BLOCK,
+	TKTX_PVR_4BPPA_SRGB_BLOCK,
+
+	TKTX_ASTC_4x4_UNORM_BLOCK,
+	TKTX_ASTC_4x4_SRGB_BLOCK,
+	TKTX_ASTC_5x4_UNORM_BLOCK,
+	TKTX_ASTC_5x4_SRGB_BLOCK,
+	TKTX_ASTC_5x5_UNORM_BLOCK,
+	TKTX_ASTC_5x5_SRGB_BLOCK,
+	TKTX_ASTC_6x5_UNORM_BLOCK,
+	TKTX_ASTC_6x5_SRGB_BLOCK,
+	TKTX_ASTC_6x6_UNORM_BLOCK,
+	TKTX_ASTC_6x6_SRGB_BLOCK,
+	TKTX_ASTC_8x5_UNORM_BLOCK,
+	TKTX_ASTC_8x5_SRGB_BLOCK,
+	TKTX_ASTC_8x6_UNORM_BLOCK,
+	TKTX_ASTC_8x6_SRGB_BLOCK,
+	TKTX_ASTC_8x8_UNORM_BLOCK,
+	TKTX_ASTC_8x8_SRGB_BLOCK,
+	TKTX_ASTC_10x5_UNORM_BLOCK,
+	TKTX_ASTC_10x5_SRGB_BLOCK,
+	TKTX_ASTC_10x6_UNORM_BLOCK,
+	TKTX_ASTC_10x6_SRGB_BLOCK,
+	TKTX_ASTC_10x8_UNORM_BLOCK,
+	TKTX_ASTC_10x8_SRGB_BLOCK,
+	TKTX_ASTC_10x10_UNORM_BLOCK,
+	TKTX_ASTC_10x10_SRGB_BLOCK,
+	TKTX_ASTC_12x10_UNORM_BLOCK,
+	TKTX_ASTC_12x10_SRGB_BLOCK,
+	TKTX_ASTC_12x12_UNORM_BLOCK,
+	TKTX_ASTC_12x12_SRGB_BLOCK,
+
+} TinyKtx_Format;
+
+TinyKtx_Format TinyKtx_GetFormat(TinyKtx_ContextHandle handle);
+bool TinyKtx_CrackFormatToGL(TinyKtx_Format format, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize);
+bool TinyKtx_WriteImage(TinyKtx_WriteCallbacks const *callbacks,
+												void *user,
+												uint32_t width,
+												uint32_t height,
+												uint32_t depth,
+												uint32_t slices,
+												uint32_t mipmaplevels,
+												TinyKtx_Format format,
+												bool cubemap,
+												uint32_t const *mipmapsizes,
+												void const **mipmaps);
+#endif
+
+#if TINYKTX_WANT_FAKE_GL_DEFINES != 0
+// GL types
+#define TINYKTX_GL_TYPE_COMPRESSED                      0x0
+#define TINYKTX_GL_TYPE_BYTE                            0x1400
+#define TINYKTX_GL_TYPE_UNSIGNED_BYTE                    0x1401
+#define TINYKTX_GL_TYPE_SHORT                            0x1402
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT                  0x1403
+#define TINYKTX_GL_TYPE_INT                              0x1404
+#define TINYKTX_GL_TYPE_UNSIGNED_INT                    0x1405
+#define TINYKTX_GL_TYPE_FLOAT                            0x1406
+#define TINYKTX_GL_TYPE_DOUBLE                          0x140A
+#define TINYKTX_GL_TYPE_HALF_FLOAT                      0x140B
+#define TINYKTX_GL_TYPE_UNSIGNED_BYTE_3_3_2              0x8032
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4          0x8033
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_5_5_1          0x8034
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8            0x8035
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_10_10_10_2          0x8036
+#define TINYKTX_GL_TYPE_UNSIGNED_BYTE_2_3_3_REV          0x8362
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5            0x8363
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_6_5_REV        0x8364
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_4_4_4_4_REV      0x8365
+#define TINYKTX_GL_TYPE_UNSIGNED_SHORT_1_5_5_5_REV      0x8366
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_8_8_8_8_REV        0x8367
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_2_10_10_10_REV      0x8368
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_24_8                0x84FA
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_5_9_9_9_REV        0x8C3E
+#define TINYKTX_GL_TYPE_UNSIGNED_INT_10F_11F_11F_REV    0x8C3B
+#define TINYKTX_GL_TYPE_FLOAT_32_UNSIGNED_INT_24_8_REV  0x8DAD
+
+// formats
+#define TINYKTX_GL_FORMAT_RED                              0x1903
+#define TINYKTX_GL_FORMAT_GREEN                            0x1904
+#define TINYKTX_GL_FORMAT_BLUE                            0x1905
+#define TINYKTX_GL_FORMAT_ALPHA                            0x1906
+#define TINYKTX_GL_FORMAT_RGB                              0x1907
+#define TINYKTX_GL_FORMAT_RGBA                            0x1908
+#define TINYKTX_GL_FORMAT_LUMINANCE                        0x1909
+#define TINYKTX_GL_FORMAT_LUMINANCE_ALPHA                  0x190A
+#define TINYKTX_GL_FORMAT_ABGR                            0x8000
+#define TINYKTX_GL_FORMAT_INTENSITY                        0x8049
+#define TINYKTX_GL_FORMAT_BGR                              0x80E0
+#define TINYKTX_GL_FORMAT_BGRA                            0x80E1
+#define TINYKTX_GL_FORMAT_RG                              0x8227
+#define TINYKTX_GL_FORMAT_RG_INTEGER                      0x8228
+#define TINYKTX_GL_FORMAT_SRGB                            0x8C40
+#define TINYKTX_GL_FORMAT_SRGB_ALPHA                      0x8C42
+#define TINYKTX_GL_FORMAT_SLUMINANCE_ALPHA                0x8C44
+#define TINYKTX_GL_FORMAT_SLUMINANCE                      0x8C46
+#define TINYKTX_GL_FORMAT_RED_INTEGER                      0x8D94
+#define TINYKTX_GL_FORMAT_GREEN_INTEGER                    0x8D95
+#define TINYKTX_GL_FORMAT_BLUE_INTEGER                    0x8D96
+#define TINYKTX_GL_FORMAT_ALPHA_INTEGER                    0x8D97
+#define TINYKTX_GL_FORMAT_RGB_INTEGER                      0x8D98
+#define TINYKTX_GL_FORMAT_RGBA_INTEGER                    0x8D99
+#define TINYKTX_GL_FORMAT_BGR_INTEGER                      0x8D9A
+#define TINYKTX_GL_FORMAT_BGRA_INTEGER                    0x8D9B
+#define TINYKTX_GL_FORMAT_RED_SNORM                        0x8F90
+#define TINYKTX_GL_FORMAT_RG_SNORM                        0x8F91
+#define TINYKTX_GL_FORMAT_RGB_SNORM                        0x8F92
+#define TINYKTX_GL_FORMAT_RGBA_SNORM                      0x8F93
+
+#define TINYKTX_GL_INTFORMAT_ALPHA4                          0x803B
+#define TINYKTX_GL_INTFORMAT_ALPHA8                          0x803C
+#define TINYKTX_GL_INTFORMAT_ALPHA12                          0x803D
+#define TINYKTX_GL_INTFORMAT_ALPHA16                          0x803E
+#define TINYKTX_GL_INTFORMAT_LUMINANCE4                      0x803F
+#define TINYKTX_GL_INTFORMAT_LUMINANCE8                      0x8040
+#define TINYKTX_GL_INTFORMAT_LUMINANCE12                      0x8041
+#define TINYKTX_GL_INTFORMAT_LUMINANCE16                      0x8042
+#define TINYKTX_GL_INTFORMAT_LUMINANCE4_ALPHA4                0x8043
+#define TINYKTX_GL_INTFORMAT_LUMINANCE6_ALPHA2                0x8044
+#define TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8                0x8045
+#define TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA4              0x8046
+#define TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA12              0x8047
+#define TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16              0x8048
+#define TINYKTX_GL_INTFORMAT_INTENSITY4                      0x804A
+#define TINYKTX_GL_INTFORMAT_INTENSITY8                      0x804B
+#define TINYKTX_GL_INTFORMAT_INTENSITY12                      0x804C
+#define TINYKTX_GL_INTFORMAT_INTENSITY16                      0x804D
+#define TINYKTX_GL_INTFORMAT_RGB2                            0x804E
+#define TINYKTX_GL_INTFORMAT_RGB4                            0x804F
+#define TINYKTX_GL_INTFORMAT_RGB5                            0x8050
+#define TINYKTX_GL_INTFORMAT_RGB8                              0x8051
+#define TINYKTX_GL_INTFORMAT_RGB10                            0x8052
+#define TINYKTX_GL_INTFORMAT_RGB12                            0x8053
+#define TINYKTX_GL_INTFORMAT_RGB16                            0x8054
+#define TINYKTX_GL_INTFORMAT_RGBA2                            0x8055
+#define TINYKTX_GL_INTFORMAT_RGBA4                            0x8056
+#define TINYKTX_GL_INTFORMAT_RGB5_A1                          0x8057
+#define TINYKTX_GL_INTFORMAT_RGBA8                            0x8058
+#define TINYKTX_GL_INTFORMAT_RGB10_A2                        0x8059
+#define TINYKTX_GL_INTFORMAT_RGBA12                          0x805A
+#define TINYKTX_GL_INTFORMAT_RGBA16                          0x805B
+#define TINYKTX_GL_INTFORMAT_R8                              0x8229
+#define TINYKTX_GL_INTFORMAT_R16                              0x822A
+#define TINYKTX_GL_INTFORMAT_RG8                              0x822B
+#define TINYKTX_GL_INTFORMAT_RG16                            0x822C
+#define TINYKTX_GL_INTFORMAT_R16F                            0x822D
+#define TINYKTX_GL_INTFORMAT_R32F                            0x822E
+#define TINYKTX_GL_INTFORMAT_RG16F                            0x822F
+#define TINYKTX_GL_INTFORMAT_RG32F                            0x8230
+#define TINYKTX_GL_INTFORMAT_R8I                              0x8231
+#define TINYKTX_GL_INTFORMAT_R8UI                            0x8232
+#define TINYKTX_GL_INTFORMAT_R16I                            0x8233
+#define TINYKTX_GL_INTFORMAT_R16UI                            0x8234
+#define TINYKTX_GL_INTFORMAT_R32I                            0x8235
+#define TINYKTX_GL_INTFORMAT_R32UI                            0x8236
+#define TINYKTX_GL_INTFORMAT_RG8I                            0x8237
+#define TINYKTX_GL_INTFORMAT_RG8UI                            0x8238
+#define TINYKTX_GL_INTFORMAT_RG16I                            0x8239
+#define TINYKTX_GL_INTFORMAT_RG16UI                          0x823A
+#define TINYKTX_GL_INTFORMAT_RG32I                            0x823B
+#define TINYKTX_GL_INTFORMAT_RG32UI                          0x823C
+#define TINYKTX_GL_INTFORMAT_RGBA32F                          0x8814
+#define TINYKTX_GL_INTFORMAT_RGB32F                          0x8815
+#define TINYKTX_GL_INTFORMAT_RGBA16F                          0x881A
+#define TINYKTX_GL_INTFORMAT_RGB16F                          0x881B
+#define TINYKTX_GL_INTFORMAT_R11F_G11F_B10F                  0x8C3A
+#define TINYKTX_GL_INTFORMAT_UNSIGNED_INT_10F_11F_11F_REV      0x8C3B
+#define TINYKTX_GL_INTFORMAT_RGB9_E5                          0x8C3D
+#define TINYKTX_GL_INTFORMAT_SRGB8                            0x8C41
+#define TINYKTX_GL_INTFORMAT_SRGB8_ALPHA8                      0x8C43
+#define TINYKTX_GL_INTFORMAT_SLUMINANCE8_ALPHA8              0x8C45
+#define TINYKTX_GL_INTFORMAT_SLUMINANCE8                      0x8C47
+#define TINYKTX_GL_INTFORMAT_RGB565                          0x8D62
+#define TINYKTX_GL_INTFORMAT_RGBA32UI                        0x8D70
+#define TINYKTX_GL_INTFORMAT_RGB32UI                          0x8D71
+#define TINYKTX_GL_INTFORMAT_RGBA16UI                        0x8D76
+#define TINYKTX_GL_INTFORMAT_RGB16UI                          0x8D77
+#define TINYKTX_GL_INTFORMAT_RGBA8UI                          0x8D7C
+#define TINYKTX_GL_INTFORMAT_RGB8UI                          0x8D7D
+#define TINYKTX_GL_INTFORMAT_RGBA32I                          0x8D82
+#define TINYKTX_GL_INTFORMAT_RGB32I                          0x8D83
+#define TINYKTX_GL_INTFORMAT_RGBA16I                          0x8D88
+#define TINYKTX_GL_INTFORMAT_RGB16I                          0x8D89
+#define TINYKTX_GL_INTFORMAT_RGBA8I                          0x8D8E
+#define TINYKTX_GL_INTFORMAT_RGB8I                            0x8D8F
+#define TINYKTX_GL_INTFORMAT_FLOAT_32_UNSIGNED_INT_24_8_REV  0x8DAD
+#define TINYKTX_GL_INTFORMAT_R8_SNORM                        0x8F94
+#define TINYKTX_GL_INTFORMAT_RG8_SNORM                        0x8F95
+#define TINYKTX_GL_INTFORMAT_RGB8_SNORM                      0x8F96
+#define TINYKTX_GL_INTFORMAT_RGBA8_SNORM                      0x8F97
+#define TINYKTX_GL_INTFORMAT_R16_SNORM                        0x8F98
+#define TINYKTX_GL_INTFORMAT_RG16_SNORM                      0x8F99
+#define TINYKTX_GL_INTFORMAT_RGB16_SNORM                      0x8F9A
+#define TINYKTX_GL_INTFORMAT_RGBA16_SNORM                    0x8F9B
+#define TINYKTX_GL_INTFORMAT_ALPHA8_SNORM                    0x9014
+#define TINYKTX_GL_INTFORMAT_LUMINANCE8_SNORM                0x9015
+#define TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8_SNORM          0x9016
+#define TINYKTX_GL_INTFORMAT_INTENSITY8_SNORM                0x9017
+#define TINYKTX_GL_INTFORMAT_ALPHA16_SNORM                    0x9018
+#define TINYKTX_GL_INTFORMAT_LUMINANCE16_SNORM                0x9019
+#define TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16_SNORM        0x901A
+#define TINYKTX_GL_INTFORMAT_INTENSITY16_SNORM                0x901B
+
+#define TINYKTX_GL_PALETTE4_RGB8_OES              0x8B90
+#define TINYKTX_GL_PALETTE4_RGBA8_OES             0x8B91
+#define TINYKTX_GL_PALETTE4_R5_G6_B5_OES          0x8B92
+#define TINYKTX_GL_PALETTE4_RGBA4_OES             0x8B93
+#define TINYKTX_GL_PALETTE4_RGB5_A1_OES           0x8B94
+#define TINYKTX_GL_PALETTE8_RGB8_OES              0x8B95
+#define TINYKTX_GL_PALETTE8_RGBA8_OES             0x8B96
+#define TINYKTX_GL_PALETTE8_R5_G6_B5_OES          0x8B97
+#define TINYKTX_GL_PALETTE8_RGBA4_OES             0x8B98
+#define TINYKTX_GL_PALETTE8_RGB5_A1_OES           0x8B99
+
+// compressed formats
+
+#define TINYKTX_GL_COMPRESSED_RGB_S3TC_DXT1                  	0x83F0
+#define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT1                  0x83F1
+#define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT3                  0x83F2
+#define TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT5                  0x83F3
+#define TINYKTX_GL_COMPRESSED_3DC_X_AMD                       0x87F9
+#define TINYKTX_GL_COMPRESSED_3DC_XY_AMD                      0x87FA
+#define TINYKTX_GL_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA    	0x87EE
+#define TINYKTX_GL_COMPRESSED_SRGB_PVRTC_2BPPV1               0x8A54
+#define TINYKTX_GL_COMPRESSED_SRGB_PVRTC_4BPPV1               0x8A55
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1         0x8A56
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1         0x8A57
+#define TINYKTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1                0x8C00
+#define TINYKTX_GL_COMPRESSED_RGB_PVRTC_2BPPV1                0x8C01
+#define TINYKTX_GL_COMPRESSED_RGBA_PVRTC_4BPPV1               0x8C02
+#define TINYKTX_GL_COMPRESSED_RGBA_PVRTC_2BPPV1               0x8C03
+#define TINYKTX_GL_COMPRESSED_SRGB_S3TC_DXT1                  0x8C4C
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1            0x8C4D
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3            0x8C4E
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5            0x8C4F
+#define TINYKTX_GL_COMPRESSED_LUMINANCE_LATC1                	0x8C70
+#define TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1          0x8C71
+#define TINYKTX_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2           0x8C72
+#define TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2    0x8C73
+#define TINYKTX_GL_COMPRESSED_ATC_RGB                         0x8C92
+#define TINYKTX_GL_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA         0x8C93
+#define TINYKTX_GL_COMPRESSED_RED_RGTC1                       0x8DBB
+#define TINYKTX_GL_COMPRESSED_SIGNED_RED_RGTC1                0x8DBC
+#define TINYKTX_GL_COMPRESSED_RED_GREEN_RGTC2                	0x8DBD
+#define TINYKTX_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2          0x8DBE
+#define TINYKTX_GL_COMPRESSED_ETC1_RGB8_OES                   0x8D64
+#define TINYKTX_GL_COMPRESSED_RGBA_BPTC_UNORM                	0x8E8C
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM          	0x8E8D
+#define TINYKTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT          	0x8E8E
+#define TINYKTX_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT        	0x8E8F
+#define TINYKTX_GL_COMPRESSED_R11_EAC                        	0x9270
+#define TINYKTX_GL_COMPRESSED_SIGNED_R11_EAC                  0x9271
+#define TINYKTX_GL_COMPRESSED_RG11_EAC                        0x9272
+#define TINYKTX_GL_COMPRESSED_SIGNED_RG11_EAC                	0x9273
+#define TINYKTX_GL_COMPRESSED_RGB8_ETC2                      	0x9274
+#define TINYKTX_GL_COMPRESSED_SRGB8_ETC2                      0x9275
+#define TINYKTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2   0x9276
+#define TINYKTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2  0x9277
+#define TINYKTX_GL_COMPRESSED_RGBA8_ETC2_EAC                  0x9278
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC           0x9279
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2         0x93F0
+#define TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2         0x93F1
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_4x4		   							0x93B0
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x4		              	0x93B1
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x5		              	0x93B2
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x5		              	0x93B3
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x6		              	0x93B4
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x5		              	0x93B5
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x6		              	0x93B6
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x8		              	0x93B7
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x5		              0x93B8
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x6		              0x93B9
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x8		              0x93BA
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x10	            		0x93BB
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x10	            		0x93BC
+#define TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x12	            		0x93BD
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4			      0x93D0
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4			      0x93D1
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5			      0x93D2
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5						0x93D3
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6						0x93D4
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5						0x93D5
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6						0x93D6
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8						0x93D7
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5					0x93D8
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6					0x93D9
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8					0x93DA
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10					0x93DB
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10     		0x93DC
+#define TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12     		0x93DD
+
+#endif
+
+#ifdef TINYKTX_IMPLEMENTATION
+
+typedef struct TinyKtx_Header {
+	uint8_t identifier[12];
+	uint32_t endianness;
+	uint32_t glType;
+	uint32_t glTypeSize;
+	uint32_t glFormat;
+	uint32_t glInternalFormat;
+	uint32_t glBaseInternalFormat;
+	uint32_t pixelWidth;
+	uint32_t pixelHeight;
+	uint32_t pixelDepth;
+	uint32_t numberOfArrayElements;
+	uint32_t numberOfFaces;
+	uint32_t numberOfMipmapLevels;
+	uint32_t bytesOfKeyValueData;
+
+} TinyKtx_Header;
+
+typedef struct TinyKtx_KeyValuePair {
+	uint32_t size;
+} TinyKtx_KeyValuePair; // followed by at least size bytes (aligned to 4)
+
+
+typedef struct TinyKtx_Context {
+	TinyKtx_Callbacks callbacks;
+	void *user;
+	uint64_t headerPos;
+	uint64_t firstImagePos;
+
+	TinyKtx_Header header;
+	TinyKtx_KeyValuePair const *keyData;
+	bool headerValid;
+	bool sameEndian;
+
+	uint32_t mipMapSizes[TINYKTX_MAX_MIPMAPLEVELS];
+	uint8_t const *mipmaps[TINYKTX_MAX_MIPMAPLEVELS];
+
+} TinyKtx_Context;
+
+static uint8_t TinyKtx_fileIdentifier[12] = {
+		0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
+};
+static void TinyKtx_NullErrorFunc(void *user, char const *msg) {}
+
+TinyKtx_ContextHandle TinyKtx_CreateContext(TinyKtx_Callbacks const *callbacks, void *user) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) callbacks->alloc(user, sizeof(TinyKtx_Context));
+	if (ctx == NULL)
+		return NULL;
+
+	memset(ctx, 0, sizeof(TinyKtx_Context));
+	memcpy(&ctx->callbacks, callbacks, sizeof(TinyKtx_Callbacks));
+	ctx->user = user;
+	if (ctx->callbacks.error == NULL) {
+		ctx->callbacks.error = &TinyKtx_NullErrorFunc;
+	}
+
+	if (ctx->callbacks.read == NULL) {
+		ctx->callbacks.error(user, "TinyKtx must have read callback");
+		return NULL;
+	}
+	if (ctx->callbacks.alloc == NULL) {
+		ctx->callbacks.error(user, "TinyKtx must have alloc callback");
+		return NULL;
+	}
+	if (ctx->callbacks.free == NULL) {
+		ctx->callbacks.error(user, "TinyKtx must have free callback");
+		return NULL;
+	}
+	if (ctx->callbacks.seek == NULL) {
+		ctx->callbacks.error(user, "TinyKtx must have seek callback");
+		return NULL;
+	}
+	if (ctx->callbacks.tell == NULL) {
+		ctx->callbacks.error(user, "TinyKtx must have tell callback");
+		return NULL;
+	}
+
+	TinyKtx_Reset(ctx);
+
+	return ctx;
+}
+
+void TinyKtx_DestroyContext(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return;
+	TinyKtx_Reset(handle);
+	ctx->callbacks.free(ctx->user, ctx);
+}
+
+void TinyKtx_Reset(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return;
+
+	// backup user provided callbacks and data
+	TinyKtx_Callbacks callbacks;
+	memcpy(&callbacks, &ctx->callbacks, sizeof(TinyKtx_Callbacks));
+	void *user = ctx->user;
+
+	// free memory of sub data
+	if (ctx->keyData != NULL) {
+		ctx->callbacks.free(ctx->user, (void *) ctx->keyData);
+	}
+	for (int i = 0; i < TINYKTX_MAX_MIPMAPLEVELS; ++i) {
+		if (ctx->mipmaps[i] != NULL) {
+			ctx->callbacks.free(ctx->user, (void *) ctx->mipmaps[i]);
+		}
+	}
+
+	// reset to default state
+	memset(ctx, 0, sizeof(TinyKtx_Context));
+	memcpy(&ctx->callbacks, &callbacks, sizeof(TinyKtx_Callbacks));
+	ctx->user = user;
+
+}
+
+bool TinyKtx_ReadHeader(TinyKtx_ContextHandle handle) {
+
+	static uint32_t const sameEndianDecider = 0x04030201;
+	static uint32_t const differentEndianDecider = 0x01020304;
+
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+
+	ctx->headerPos = ctx->callbacks.tell(ctx->user);
+	ctx->callbacks.read(ctx->user, &ctx->header, sizeof(TinyKtx_Header));
+
+	if (memcmp(&ctx->header.identifier, TinyKtx_fileIdentifier, 12) != 0) {
+		ctx->callbacks.error(ctx->user, "Not a KTX file or corrupted as identified isn't valid");
+		return false;
+	}
+
+	if (ctx->header.endianness == sameEndianDecider) {
+		ctx->sameEndian = true;
+	} else if (ctx->header.endianness == differentEndianDecider) {
+		ctx->sameEndian = false;
+	} else {
+		// corrupt or mid endian?
+		ctx->callbacks.error(ctx->user, "Endian Error");
+		return false;
+	}
+
+	if (ctx->header.numberOfFaces != 1 && ctx->header.numberOfFaces != 6) {
+		ctx->callbacks.error(ctx->user, "no. of Faces must be 1 or 6");
+		return false;
+	}
+
+	ctx->keyData = (TinyKtx_KeyValuePair const *) ctx->callbacks.alloc(ctx->user, ctx->header.bytesOfKeyValueData);
+	ctx->callbacks.read(ctx->user, (void *) ctx->keyData, ctx->header.bytesOfKeyValueData);
+
+	ctx->firstImagePos = ctx->callbacks.tell(ctx->user);
+
+	ctx->headerValid = true;
+	return true;
+}
+bool TinyKtx_GetValue(TinyKtx_ContextHandle handle, char const *key, void const **value) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	if (ctx->keyData == NULL) {
+		ctx->callbacks.error(ctx->user, "No key value data in this KTX");
+		return false;
+	}
+
+	TinyKtx_KeyValuePair const *curKey = ctx->keyData;
+	while (((uint8_t *) curKey - (uint8_t *) ctx->keyData) < ctx->header.bytesOfKeyValueData) {
+		char const *kvp = (char const *) curKey;
+
+		if (strcmp(kvp, key) == 0) {
+			size_t sl = strlen(kvp);
+			*value = (void const *) (kvp + sl);
+			return true;
+		}
+		curKey = curKey + ((curKey->size + 3u) & ~3u);
+	}
+	return false;
+}
+
+bool TinyKtx_Is1D(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return (ctx->header.pixelHeight == 1 && ctx->header.pixelDepth == 1);
+}
+bool TinyKtx_Is2D(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return (ctx->header.pixelHeight != 1 && ctx->header.pixelDepth == 1);
+}
+bool TinyKtx_Is3D(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return (ctx->header.pixelHeight != 1 && ctx->header.pixelDepth != 1);
+}
+
+bool TinyKtx_IsCubemap(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return (ctx->header.numberOfFaces == 6);
+}
+bool TinyKtx_IsArray(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return (ctx->header.numberOfArrayElements > 1);
+}
+bool TinyKtx_Dimensions(TinyKtx_ContextHandle handle,
+												uint32_t *width,
+												uint32_t *height,
+												uint32_t *depth,
+												uint32_t *slices) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+	if (width)
+		*width = ctx->header.pixelWidth;
+	if (height)
+		*height = ctx->header.pixelWidth;
+	if (depth)
+		*depth = ctx->header.pixelDepth;
+	if (slices)
+		*slices = ctx->header.numberOfArrayElements;
+
+	return true;
+}
+
+uint32_t TinyKtx_Width(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+
+	return ctx->header.pixelWidth;
+}
+
+uint32_t TinyKtx_Height(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+
+	return ctx->header.pixelHeight;
+}
+
+uint32_t TinyKtx_Depth(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+
+	return ctx->header.pixelDepth;
+}
+
+uint32_t TinyKtx_ArraySlices(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+
+	return ctx->header.numberOfArrayElements;
+}
+
+uint32_t TinyKtx_NumberOfMipmaps(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+
+	return ctx->header.numberOfMipmapLevels ? ctx->header.numberOfMipmapLevels : 1;
+}
+
+bool TinyKtx_NeedsGenerationOfMipmaps(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return ctx->header.numberOfMipmapLevels == 0;
+}
+
+bool TinyKtx_NeedsEndianCorrecting(TinyKtx_ContextHandle handle) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	return ctx->sameEndian == false;
+}
+
+bool TinyKtx_GetFormatGL(TinyKtx_ContextHandle handle, uint32_t *glformat, uint32_t *gltype, uint32_t *glinternalformat, uint32_t* typesize, uint32_t* glbaseinternalformat) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return false;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return false;
+	}
+
+	*glformat = ctx->header.glFormat;
+	*gltype = ctx->header.glType;
+	*glinternalformat = ctx->header.glInternalFormat;
+	*glbaseinternalformat = ctx->header.glBaseInternalFormat;
+	*typesize = ctx->header.glBaseInternalFormat;
+
+	return true;
+}
+
+bool TinyKtx_WriteImageGL(TinyKtx_WriteCallbacks const *callbacks,
+													void *user,
+													uint32_t width,
+													uint32_t height,
+													uint32_t depth,
+													uint32_t slices,
+													uint32_t mipmaplevels,
+													uint32_t format,
+													uint32_t internalFormat,
+													uint32_t baseFormat,
+													uint32_t type,
+													uint32_t typeSize,
+													bool cubemap,
+													uint32_t const *mipmapsizes,
+													void const **mipmaps) {
+
+	TinyKtx_Header header;
+	memcpy(header.identifier, TinyKtx_fileIdentifier, 12);
+	header.endianness = 0x04030201;
+	header.glFormat = format;
+	header.glInternalFormat = internalFormat;
+	header.glBaseInternalFormat = baseFormat;
+	header.glType = type;
+	header.glTypeSize = typeSize;
+	header.pixelWidth = width;
+	header.pixelHeight = height;
+	header.pixelDepth = depth;
+	header.numberOfArrayElements = slices;
+	header.numberOfFaces = cubemap ? 6 : 1;
+	header.numberOfMipmapLevels = mipmaplevels;
+	// TODO keyvalue pair data
+	header.bytesOfKeyValueData = 0;
+	callbacks->write(user, &header, sizeof(TinyKtx_Header));
+
+	static uint8_t const padding[4] = {0, 0, 0, 0};
+
+	// TODO this might be wrong for non array cubemaps with < 4 bytes per pixel...
+	// cubemap padding needs factoring in.
+	for (uint32_t i = 0u; i < mipmaplevels; ++i) {
+		callbacks->write(user, mipmapsizes + i, sizeof(uint32_t));
+		callbacks->write(user, mipmaps[i], mipmapsizes[i]);
+		callbacks->write(user, padding, ((mipmapsizes[i] + 3u) & ~3u) - mipmapsizes[i]);
+	}
+
+	return true;
+}
+
+static uint32_t imageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel, bool seekLast) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return 0;
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return 0;
+	}
+	if (mipmaplevel >= ctx->header.numberOfMipmapLevels) {
+		ctx->callbacks.error(ctx->user, "Invalid mipmap level");
+		return 0;
+	}
+	if (mipmaplevel >= TINYKTX_MAX_MIPMAPLEVELS) {
+		ctx->callbacks.error(ctx->user, "Invalid mipmap level");
+		return 0;
+	}
+	if (!seekLast && ctx->mipMapSizes[mipmaplevel] != 0)
+		return ctx->mipMapSizes[mipmaplevel];
+
+	uint64_t currentOffset = ctx->firstImagePos;
+	for (uint32_t i = 0; i <= mipmaplevel; ++i) {
+		uint32_t size;
+		// if we have already read this mipmaps size use it
+		if (ctx->mipMapSizes[i] != 0) {
+			size = ctx->mipMapSizes[i];
+			if (seekLast && i == mipmaplevel) {
+				ctx->callbacks.seek(ctx->user, currentOffset + sizeof(uint32_t));
+			}
+		} else {
+			// otherwise seek and read it
+			ctx->callbacks.seek(ctx->user, currentOffset);
+			size_t readchk = ctx->callbacks.read(ctx->user, &size, sizeof(uint32_t));
+			if(readchk != 4) {
+				ctx->callbacks.error(ctx->user, "Reading image size error");
+				return 0;
+			}
+
+			if (ctx->header.numberOfFaces == 6 && ctx->header.numberOfArrayElements == 0) {
+				size = ((size + 3u) & ~3u) * 6; // face padding and 6 faces
+			}
+
+			ctx->mipMapSizes[i] = size;
+		}
+		currentOffset += (size + sizeof(uint32_t) + 3u) & ~3u; // size + mip padding
+	}
+
+	return ctx->mipMapSizes[mipmaplevel];
+}
+
+uint32_t TinyKtx_ImageSize(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) {
+	return imageSize(handle, mipmaplevel, false);
+}
+
+void const *TinyKtx_ImageRawData(TinyKtx_ContextHandle handle, uint32_t mipmaplevel) {
+	TinyKtx_Context *ctx = (TinyKtx_Context *) handle;
+	if (ctx == NULL)
+		return NULL;
+
+	if (ctx->headerValid == false) {
+		ctx->callbacks.error(ctx->user, "Header data hasn't been read yet or its invalid");
+		return NULL;
+	}
+
+	if (mipmaplevel >= ctx->header.numberOfMipmapLevels) {
+		ctx->callbacks.error(ctx->user, "Invalid mipmap level");
+		return NULL;
+	}
+
+	if (mipmaplevel >= TINYKTX_MAX_MIPMAPLEVELS) {
+		ctx->callbacks.error(ctx->user, "Invalid mipmap level");
+		return NULL;
+	}
+
+	if (ctx->mipmaps[mipmaplevel] != NULL)
+		return ctx->mipmaps[mipmaplevel];
+
+	uint32_t size = imageSize(handle, mipmaplevel, true);
+	if (size == 0)
+		return NULL;
+
+	ctx->mipmaps[mipmaplevel] = (uint8_t const*) ctx->callbacks.alloc(ctx->user, size);
+	if (ctx->mipmaps[mipmaplevel]) {
+		ctx->callbacks.read(ctx->user, (void *) ctx->mipmaps[mipmaplevel], size);
+	}
+
+	return ctx->mipmaps[mipmaplevel];
+}
+
+#if TINYKTX_WANT_TINYKTX_FORMAT != 0
+
+#define FT(fmt, type, intfmt, size) *glformat = TINYKTX_GL_FORMAT_##fmt; \
+                                    *gltype = TINYKTX_GL_TYPE_##type; \
+                                    *glinternalformat = TINYKTX_GL_INTFORMAT_##intfmt; \
+                                    *typesize = size; \
+                                    return true;
+#define FTC(fmt, intfmt) *glformat = TINYKTX_GL_FORMAT_##fmt; \
+                                    *gltype = TINYKTX_GL_TYPE_COMPRESSED; \
+                                    *glinternalformat = TINYKTX_GL_COMPRESSED_##intfmt; \
+                                    *typesize = 1; \
+                                    return true;
+
+bool TinyKtx_CrackFormatToGL(TinyKtx_Format format,
+														 uint32_t *glformat,
+														 uint32_t *gltype,
+														 uint32_t *glinternalformat,
+														 uint32_t *typesize) {
+	switch (format) {
+	case TKTX_R4G4_UNORM_PACK8: break;
+	case TKTX_R4G4B4A4_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_4_4_4_4, RGBA4, 1)
+	case TKTX_B4G4R4A4_UNORM_PACK16: FT(BGRA, UNSIGNED_SHORT_4_4_4_4_REV, RGBA4, 1)
+	case TKTX_R5G6B5_UNORM_PACK16: FT(RGB, UNSIGNED_SHORT_5_6_5, RGB565, 1)
+	case TKTX_B5G6R5_UNORM_PACK16: FT(BGR, UNSIGNED_SHORT_5_6_5_REV, RGB565, 1)
+	case TKTX_R5G5B5A1_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_5_5_5_1, RGB5_A1, 1)
+	case TKTX_A1R5G5B5_UNORM_PACK16: FT(RGBA, UNSIGNED_SHORT_1_5_5_5_REV, RGB5_A1, 1)
+	case TKTX_B5G5R5A1_UNORM_PACK16: FT(BGRA, UNSIGNED_SHORT_5_5_5_1, RGB5_A1, 1)
+
+	case TKTX_A2R10G10B10_UNORM_PACK32: FT(BGRA, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 1)
+	case TKTX_A2R10G10B10_UINT_PACK32: FT(BGRA_INTEGER, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 1)
+	case TKTX_A2B10G10R10_UNORM_PACK32: FT(RGBA, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 1)
+	case TKTX_A2B10G10R10_UINT_PACK32: FT(RGBA_INTEGER, UNSIGNED_INT_2_10_10_10_REV, RGB10_A2, 1)
+
+	case TKTX_R8_UNORM: FT(RED, UNSIGNED_BYTE, R8, 1)
+	case TKTX_R8_SNORM: FT(RED, BYTE, R8_SNORM, 1)
+	case TKTX_R8_UINT: FT(RED_INTEGER, UNSIGNED_BYTE, R8UI, 1)
+	case TKTX_R8_SINT: FT(RED_INTEGER, BYTE, R8I, 1)
+	case TKTX_R8_SRGB: FT(SLUMINANCE, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_R8G8_UNORM: FT(RG, UNSIGNED_BYTE, RG8, 1)
+	case TKTX_R8G8_SNORM: FT(RG, BYTE, RG8_SNORM, 1)
+	case TKTX_R8G8_UINT: FT(RG_INTEGER, UNSIGNED_BYTE, RG8UI, 1)
+	case TKTX_R8G8_SINT: FT(RG_INTEGER, BYTE, RG8I, 1)
+	case TKTX_R8G8_SRGB: FT(SLUMINANCE_ALPHA, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_R8G8B8_UNORM: FT(RGB, UNSIGNED_BYTE, RGB8, 1)
+	case TKTX_R8G8B8_SNORM: FT(RGB, BYTE, RGB8_SNORM, 1)
+	case TKTX_R8G8B8_UINT: FT(RGB_INTEGER, UNSIGNED_BYTE, RGB8UI, 1)
+	case TKTX_R8G8B8_SINT: FT(RGB_INTEGER, BYTE, RGB8I, 1)
+	case TKTX_R8G8B8_SRGB: FT(SRGB, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_B8G8R8_UNORM: FT(BGR, UNSIGNED_BYTE, RGB8, 1)
+	case TKTX_B8G8R8_SNORM: FT(BGR, BYTE, RGB8_SNORM, 1)
+	case TKTX_B8G8R8_UINT: FT(BGR_INTEGER, UNSIGNED_BYTE, RGB8UI, 1)
+	case TKTX_B8G8R8_SINT: FT(BGR_INTEGER, BYTE, RGB8I, 1)
+	case TKTX_B8G8R8_SRGB: FT(BGR, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_R8G8B8A8_UNORM:FT(RGBA, UNSIGNED_BYTE, RGBA8, 1)
+	case TKTX_R8G8B8A8_SNORM:FT(RGBA, BYTE, RGBA8_SNORM, 1)
+	case TKTX_R8G8B8A8_UINT: FT(RGBA_INTEGER, UNSIGNED_BYTE, RGBA8UI, 1)
+	case TKTX_R8G8B8A8_SINT: FT(RGBA_INTEGER, BYTE, RGBA8I, 1)
+	case TKTX_R8G8B8A8_SRGB: FT(SRGB_ALPHA, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_B8G8R8A8_UNORM: FT(BGRA, UNSIGNED_BYTE, RGBA8, 1)
+	case TKTX_B8G8R8A8_SNORM: FT(BGRA, BYTE, RGBA8_SNORM, 1)
+	case TKTX_B8G8R8A8_UINT: FT(BGRA_INTEGER, UNSIGNED_BYTE, RGBA8UI, 1)
+	case TKTX_B8G8R8A8_SINT: FT(BGRA_INTEGER, BYTE, RGBA8I, 1)
+	case TKTX_B8G8R8A8_SRGB: FT(BGRA, UNSIGNED_BYTE, SRGB8, 1)
+
+	case TKTX_E5B9G9R9_UFLOAT_PACK32: FT(BGR, UNSIGNED_INT_5_9_9_9_REV, RGB9_E5, 1);
+	case TKTX_A8B8G8R8_UNORM_PACK32: FT(ABGR, UNSIGNED_BYTE, RGBA8, 1)
+	case TKTX_A8B8G8R8_SNORM_PACK32: FT(ABGR, BYTE, RGBA8, 1)
+	case TKTX_A8B8G8R8_UINT_PACK32: FT(ABGR, UNSIGNED_BYTE, RGBA8UI, 1)
+	case TKTX_A8B8G8R8_SINT_PACK32: FT(ABGR, BYTE, RGBA8I, 1)
+	case TKTX_A8B8G8R8_SRGB_PACK32: FT(ABGR, UNSIGNED_BYTE, SRGB8, 1)
+	case TKTX_B10G11R11_UFLOAT_PACK32: FT(BGR, UNSIGNED_INT_10F_11F_11F_REV, R11F_G11F_B10F, 1)
+
+	case TKTX_R16_UNORM: FT(RED, UNSIGNED_SHORT, R16, 2)
+	case TKTX_R16_SNORM: FT(RED, SHORT, R16_SNORM, 2)
+	case TKTX_R16_UINT: FT(RED_INTEGER, UNSIGNED_SHORT, R16UI, 2)
+	case TKTX_R16_SINT: FT(RED_INTEGER, SHORT, R16I, 2)
+	case TKTX_R16_SFLOAT:FT(RED, HALF_FLOAT, R16F, 2)
+
+	case TKTX_R16G16_UNORM: FT(RG, UNSIGNED_SHORT, RG16, 2)
+	case TKTX_R16G16_SNORM: FT(RG, SHORT, RG16_SNORM, 2)
+	case TKTX_R16G16_UINT: FT(RG_INTEGER, UNSIGNED_SHORT, RG16UI, 2)
+	case TKTX_R16G16_SINT: FT(RG_INTEGER, SHORT, RG16I, 2)
+	case TKTX_R16G16_SFLOAT:FT(RG, HALF_FLOAT, RG16F, 2)
+
+	case TKTX_R16G16B16_UNORM: FT(RGB, UNSIGNED_SHORT, RGB16, 2)
+	case TKTX_R16G16B16_SNORM: FT(RGB, SHORT, RGB16_SNORM, 2)
+	case TKTX_R16G16B16_UINT: FT(RGB_INTEGER, UNSIGNED_SHORT, RGB16UI, 2)
+	case TKTX_R16G16B16_SINT: FT(RGB_INTEGER, SHORT, RGB16I, 2)
+	case TKTX_R16G16B16_SFLOAT: FT(RGB, HALF_FLOAT, RGB16F, 2)
+
+	case TKTX_R16G16B16A16_UNORM: FT(RGBA, UNSIGNED_SHORT, RGBA16, 2)
+	case TKTX_R16G16B16A16_SNORM: FT(RGBA, SHORT, RGBA16_SNORM, 2)
+	case TKTX_R16G16B16A16_UINT: FT(RGBA_INTEGER, UNSIGNED_SHORT, RGBA16UI, 2)
+	case TKTX_R16G16B16A16_SINT: FT(RGBA_INTEGER, SHORT, RGBA16I, 2)
+	case TKTX_R16G16B16A16_SFLOAT:FT(RGBA, HALF_FLOAT, RGBA16F, 2)
+
+	case TKTX_R32_UINT: FT(RED_INTEGER, UNSIGNED_INT, R32UI, 4)
+	case TKTX_R32_SINT: FT(RED_INTEGER, INT, R32I, 4)
+	case TKTX_R32_SFLOAT: FT(RED, FLOAT, R32F, 4)
+
+	case TKTX_R32G32_UINT: FT(RG_INTEGER, UNSIGNED_INT, RG32UI, 4)
+	case TKTX_R32G32_SINT: FT(RG_INTEGER, INT, RG32I, 4)
+	case TKTX_R32G32_SFLOAT: FT(RG, FLOAT, RG32F, 4)
+
+	case TKTX_R32G32B32_UINT: FT(RGB_INTEGER, UNSIGNED_INT, RGB32UI, 4)
+	case TKTX_R32G32B32_SINT: FT(RGB_INTEGER, INT, RGB32I, 4)
+	case TKTX_R32G32B32_SFLOAT: FT(RGB_INTEGER, FLOAT, RGB32F, 4)
+
+	case TKTX_R32G32B32A32_UINT: FT(RGBA_INTEGER, UNSIGNED_INT, RGBA32UI, 4)
+	case TKTX_R32G32B32A32_SINT: FT(RGBA_INTEGER, INT, RGBA32I, 4)
+	case TKTX_R32G32B32A32_SFLOAT:FT(RGBA, FLOAT, RGBA32F, 4)
+
+	case TKTX_BC1_RGB_UNORM_BLOCK: FTC(RGB, RGB_S3TC_DXT1)
+	case TKTX_BC1_RGB_SRGB_BLOCK: FTC(RGB, SRGB_S3TC_DXT1)
+	case TKTX_BC1_RGBA_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT1)
+	case TKTX_BC1_RGBA_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT1)
+	case TKTX_BC2_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT3)
+	case TKTX_BC2_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT3)
+	case TKTX_BC3_UNORM_BLOCK: FTC(RGBA, RGBA_S3TC_DXT5)
+	case TKTX_BC3_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_S3TC_DXT5)
+	case TKTX_BC4_UNORM_BLOCK: FTC(RED, RED_RGTC1)
+	case TKTX_BC4_SNORM_BLOCK: FTC(RED, SIGNED_RED_RGTC1)
+	case TKTX_BC5_UNORM_BLOCK: FTC(RG, RED_GREEN_RGTC2)
+	case TKTX_BC5_SNORM_BLOCK: FTC(RG, SIGNED_RED_GREEN_RGTC2)
+	case TKTX_BC6H_UFLOAT_BLOCK: FTC(RGB, RGB_BPTC_UNSIGNED_FLOAT)
+	case TKTX_BC6H_SFLOAT_BLOCK: FTC(RGB, RGB_BPTC_SIGNED_FLOAT)
+	case TKTX_BC7_UNORM_BLOCK: FTC(RGBA, RGBA_BPTC_UNORM)
+	case TKTX_BC7_SRGB_BLOCK: FTC(RGBA, SRGB_ALPHA_BPTC_UNORM)
+
+	case TKTX_ETC2_R8G8B8_UNORM_BLOCK: FTC(RGB, RGB8_ETC2)
+	case TKTX_ETC2_R8G8B8A1_UNORM_BLOCK: FTC(RGBA, RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+	case TKTX_ETC2_R8G8B8A8_UNORM_BLOCK: FTC(RGBA, RGBA8_ETC2_EAC)
+	case TKTX_ETC2_R8G8B8_SRGB_BLOCK: FTC(SRGB, SRGB8_ETC2)
+	case TKTX_ETC2_R8G8B8A1_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+	case TKTX_ETC2_R8G8B8A8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ETC2_EAC)
+	case TKTX_EAC_R11_UNORM_BLOCK: FTC(RED, R11_EAC)
+	case TKTX_EAC_R11G11_UNORM_BLOCK: FTC(RG, RG11_EAC)
+	case TKTX_EAC_R11_SNORM_BLOCK: FTC(RED, SIGNED_R11_EAC)
+	case TKTX_EAC_R11G11_SNORM_BLOCK: FTC(RG, SIGNED_RG11_EAC)
+
+	case TKTX_PVR_2BPP_BLOCK: FTC(RGB, RGB_PVRTC_2BPPV1)
+	case TKTX_PVR_2BPPA_BLOCK: FTC(RGBA, RGBA_PVRTC_2BPPV1);
+	case TKTX_PVR_4BPP_BLOCK: FTC(RGB, RGB_PVRTC_4BPPV1)
+	case TKTX_PVR_4BPPA_BLOCK: FTC(RGB, RGB_PVRTC_4BPPV1)
+	case TKTX_PVR_2BPP_SRGB_BLOCK: FTC(SRGB, SRGB_PVRTC_2BPPV1)
+	case TKTX_PVR_2BPPA_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB_ALPHA_PVRTC_2BPPV1);
+	case TKTX_PVR_4BPP_SRGB_BLOCK: FTC(SRGB, SRGB_PVRTC_2BPPV1)
+	case TKTX_PVR_4BPPA_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB_ALPHA_PVRTC_2BPPV1);
+
+	case TKTX_ASTC_4x4_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_4x4)
+	case TKTX_ASTC_4x4_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_4x4)
+	case TKTX_ASTC_5x4_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_5x4)
+	case TKTX_ASTC_5x4_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_5x4)
+	case TKTX_ASTC_5x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_5x5)
+	case TKTX_ASTC_5x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_5x5)
+	case TKTX_ASTC_6x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_6x5)
+	case TKTX_ASTC_6x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_6x5)
+	case TKTX_ASTC_6x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_6x6)
+	case TKTX_ASTC_6x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_6x6)
+	case TKTX_ASTC_8x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x5)
+	case TKTX_ASTC_8x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x5)
+	case TKTX_ASTC_8x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x6)
+	case TKTX_ASTC_8x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x6)
+	case TKTX_ASTC_8x8_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_8x8)
+	case TKTX_ASTC_8x8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_8x8)
+	case TKTX_ASTC_10x5_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x5)
+	case TKTX_ASTC_10x5_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x5)
+	case TKTX_ASTC_10x6_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x6)
+	case TKTX_ASTC_10x6_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x6)
+	case TKTX_ASTC_10x8_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x8);
+	case TKTX_ASTC_10x8_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x8)
+	case TKTX_ASTC_10x10_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_10x10)
+	case TKTX_ASTC_10x10_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_10x10)
+	case TKTX_ASTC_12x10_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_12x10)
+	case TKTX_ASTC_12x10_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_12x10)
+	case TKTX_ASTC_12x12_UNORM_BLOCK: FTC(RGBA, RGBA_ASTC_12x12)
+	case TKTX_ASTC_12x12_SRGB_BLOCK: FTC(SRGB_ALPHA, SRGB8_ALPHA8_ASTC_12x12)
+
+	default:break;
+	}
+	return false;
+}
+#undef FT
+#undef FTC
+
+TinyKtx_Format TinyKtx_CrackFormatFromGL(uint32_t const glformat,
+																				 uint32_t const gltype,
+																				 uint32_t const glinternalformat,
+																				 uint32_t const typesize) {
+	switch (glinternalformat) {
+	case TINYKTX_GL_COMPRESSED_RGB_S3TC_DXT1: return TKTX_BC1_RGB_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT1: return TKTX_BC1_RGBA_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT3: return TKTX_BC2_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_S3TC_DXT5: return TKTX_BC3_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_3DC_X_AMD: return TKTX_BC4_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_3DC_XY_AMD: return TKTX_BC5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_PVRTC_2BPPV1: return TKTX_PVR_2BPP_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_PVRTC_4BPPV1: return TKTX_PVR_2BPPA_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1: return TKTX_PVR_2BPPA_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1: return TKTX_PVR_4BPPA_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1: return TKTX_PVR_4BPP_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB_PVRTC_2BPPV1: return TKTX_PVR_2BPP_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_PVRTC_4BPPV1: return TKTX_PVR_4BPPA_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_PVRTC_2BPPV1: return TKTX_PVR_2BPPA_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_S3TC_DXT1: return TKTX_BC1_RGB_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1: return TKTX_BC1_RGBA_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3: return TKTX_BC2_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5: return TKTX_BC3_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_LUMINANCE_LATC1: return TKTX_BC4_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1: return TKTX_BC4_SNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2: return TKTX_BC5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2: return TKTX_BC5_SNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RED_RGTC1: return TKTX_BC4_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_RED_RGTC1: return TKTX_BC4_SNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RED_GREEN_RGTC2: return TKTX_BC5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2: return TKTX_BC5_SNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_ETC1_RGB8_OES: return TKTX_ETC2_R8G8B8_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_BPTC_UNORM: return TKTX_BC7_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: return TKTX_BC7_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: return TKTX_BC6H_SFLOAT_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: return TKTX_BC6H_UFLOAT_BLOCK;
+	case TINYKTX_GL_COMPRESSED_R11_EAC: return TKTX_EAC_R11_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_R11_EAC: return TKTX_EAC_R11_SNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RG11_EAC: return TKTX_EAC_R11G11_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SIGNED_RG11_EAC: return TKTX_EAC_R11G11_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB8_ETC2: return TKTX_ETC2_R8G8B8_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ETC2: return TKTX_ETC2_R8G8B8_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: return TKTX_ETC2_R8G8B8A1_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return TKTX_ETC2_R8G8B8A1_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA8_ETC2_EAC: return TKTX_ETC2_R8G8B8A8_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: return TKTX_ETC2_R8G8B8A8_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_4x4: return TKTX_ASTC_4x4_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x4: return TKTX_ASTC_5x4_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_5x5: return TKTX_ASTC_5x5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x5: return TKTX_ASTC_6x5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_6x6: return TKTX_ASTC_6x6_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x5: return TKTX_ASTC_8x5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x6: return TKTX_ASTC_8x6_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_8x8: return TKTX_ASTC_8x8_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x5: return TKTX_ASTC_10x5_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x6: return TKTX_ASTC_10x6_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x8: return TKTX_ASTC_10x8_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_10x10: return TKTX_ASTC_10x10_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x10: return TKTX_ASTC_12x10_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_RGBA_ASTC_12x12: return TKTX_ASTC_12x12_UNORM_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4: return TKTX_ASTC_4x4_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4: return TKTX_ASTC_5x4_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5: return TKTX_ASTC_5x5_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5: return TKTX_ASTC_6x5_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6: return TKTX_ASTC_6x6_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5: return TKTX_ASTC_8x5_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6: return TKTX_ASTC_8x6_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8: return TKTX_ASTC_8x8_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5: return TKTX_ASTC_10x5_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6: return TKTX_ASTC_10x6_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8: return TKTX_ASTC_10x8_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10: return TKTX_ASTC_10x10_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10: return TKTX_ASTC_12x10_SRGB_BLOCK;
+	case TINYKTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12: return TKTX_ASTC_12x12_SRGB_BLOCK;
+
+	// non compressed
+	case TINYKTX_GL_INTFORMAT_R8: return TKTX_R8_UNORM;
+	case TINYKTX_GL_INTFORMAT_RG8: return TKTX_R8G8_UNORM;
+	case TINYKTX_GL_INTFORMAT_RGB8: return TKTX_R8G8B8_UNORM;
+	case TINYKTX_GL_INTFORMAT_RGBA8:
+		if(glformat == TINYKTX_GL_FORMAT_RGBA) {
+			if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) {
+				return TKTX_R8G8B8A8_UNORM;
+			} else if(gltype == TINYKTX_GL_TYPE_BYTE) {
+				return TKTX_R8G8B8A8_SNORM;
+			}
+		} else if(glformat == TINYKTX_GL_FORMAT_BGRA) {
+			if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) {
+				return TKTX_B8G8R8A8_UNORM;
+			} else if(gltype == TINYKTX_GL_TYPE_BYTE) {
+				return TKTX_B8G8R8A8_SNORM;
+			}
+		} else if(glformat == TINYKTX_GL_FORMAT_ABGR) {
+			if(gltype == TINYKTX_GL_TYPE_UNSIGNED_BYTE) {
+				return TKTX_A8B8G8R8_UNORM_PACK32;
+			} else if(gltype == TINYKTX_GL_TYPE_BYTE) {
+				return TKTX_A8B8G8R8_SNORM_PACK32;
+			}
+		}
+		break;
+	case TINYKTX_GL_INTFORMAT_R8_SNORM: return TKTX_R8_SNORM;
+	case TINYKTX_GL_INTFORMAT_RG8_SNORM: return TKTX_R8G8_SNORM;
+	case TINYKTX_GL_INTFORMAT_RGB8_SNORM: return TKTX_R8G8B8_SNORM;
+	case TINYKTX_GL_INTFORMAT_RGBA8_SNORM: return TKTX_R8G8B8A8_SNORM;
+
+	case TINYKTX_GL_INTFORMAT_R16: return TKTX_R16_UNORM;
+	case TINYKTX_GL_INTFORMAT_RG16: return TKTX_R16G16_UNORM;
+	case TINYKTX_GL_INTFORMAT_RGB16: return TKTX_R16G16B16_UNORM;
+	case TINYKTX_GL_INTFORMAT_RGBA16: return TKTX_R16G16B16A16_UNORM;
+
+	case TINYKTX_GL_INTFORMAT_R16_SNORM:return TKTX_R16_SNORM;
+	case TINYKTX_GL_INTFORMAT_RG16_SNORM: return TKTX_R16G16_SNORM;
+	case TINYKTX_GL_INTFORMAT_RGB16_SNORM: return TKTX_R16G16B16_SNORM;
+	case TINYKTX_GL_INTFORMAT_RGBA16_SNORM: return TKTX_R16G16B16A16_SNORM;
+
+	case TINYKTX_GL_INTFORMAT_R8I: return TKTX_R8_SINT;
+	case TINYKTX_GL_INTFORMAT_RG8I: return TKTX_R8G8_SINT;
+	case TINYKTX_GL_INTFORMAT_RGB8I:return TKTX_R8G8B8_SINT;
+	case TINYKTX_GL_INTFORMAT_RGBA8I:
+		if(glformat == TINYKTX_GL_FORMAT_RGBA || glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) {
+			return TKTX_R8G8B8A8_SINT;
+		} else if(glformat == TINYKTX_GL_FORMAT_BGRA || glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) {
+			return TKTX_B8G8R8A8_SINT;
+		} else if(glformat == TINYKTX_GL_FORMAT_ABGR) {
+			return TKTX_A8B8G8R8_SINT_PACK32;
+		}
+		break;
+
+	case TINYKTX_GL_INTFORMAT_R16I: return TKTX_R16_SINT;
+	case TINYKTX_GL_INTFORMAT_RG16I: return TKTX_R16G16_SINT;
+	case TINYKTX_GL_INTFORMAT_RGB16I:return TKTX_R16G16B16_SINT;
+	case TINYKTX_GL_INTFORMAT_RGBA16I:return TKTX_R16G16B16A16_SINT;
+
+	case TINYKTX_GL_INTFORMAT_R32I: return TKTX_R32_SINT;
+	case TINYKTX_GL_INTFORMAT_RG32I: return TKTX_R32G32_SINT;
+	case TINYKTX_GL_INTFORMAT_RGB32I: return TKTX_R32G32B32_SINT;
+	case TINYKTX_GL_INTFORMAT_RGBA32I:return TKTX_R32G32B32A32_SINT;
+
+	case TINYKTX_GL_INTFORMAT_R8UI: return TKTX_R8_UINT;
+	case TINYKTX_GL_INTFORMAT_RG8UI: return TKTX_R8G8_UINT;
+	case TINYKTX_GL_INTFORMAT_RGB8UI: return TKTX_R8G8B8_UINT;
+	case TINYKTX_GL_INTFORMAT_RGBA8UI:
+		if(glformat == TINYKTX_GL_FORMAT_RGBA || glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) {
+			return TKTX_R8G8B8A8_UINT;
+		} else if(glformat == TINYKTX_GL_FORMAT_BGRA || glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) {
+			return TKTX_B8G8R8A8_UINT;
+		} else if(glformat == TINYKTX_GL_FORMAT_ABGR) {
+			return TKTX_A8B8G8R8_UINT_PACK32;
+		}
+		break;
+
+	case TINYKTX_GL_INTFORMAT_R16UI: return TKTX_R16_UINT;
+	case TINYKTX_GL_INTFORMAT_RG16UI: return TKTX_R16G16_UINT;
+	case TINYKTX_GL_INTFORMAT_RGB16UI:return TKTX_R16G16B16_UINT;
+	case TINYKTX_GL_INTFORMAT_RGBA16UI: return TKTX_R16G16B16A16_UINT;
+
+	case TINYKTX_GL_INTFORMAT_R32UI: return TKTX_R32_UINT;
+	case TINYKTX_GL_INTFORMAT_RG32UI: return TKTX_R32G32_UINT;
+	case TINYKTX_GL_INTFORMAT_RGB32UI: return TKTX_R32G32B32_UINT;
+	case TINYKTX_GL_INTFORMAT_RGBA32UI: return TKTX_R32G32B32A32_UINT;
+
+	case TINYKTX_GL_INTFORMAT_R16F: return TKTX_R16_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RG16F: return TKTX_R16G16_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RGB16F: return TKTX_R16G16B16_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RGBA16F: return TKTX_R16G16B16A16_SFLOAT;
+
+	case TINYKTX_GL_INTFORMAT_R32F: return TKTX_R32_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RG32F: return TKTX_R32G32_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RGB32F: return TKTX_R32G32B32_SFLOAT;
+	case TINYKTX_GL_INTFORMAT_RGBA32F: return TKTX_R32G32B32A32_SFLOAT;
+
+	case TINYKTX_GL_INTFORMAT_R11F_G11F_B10F: return TKTX_B10G11R11_UFLOAT_PACK32; //??
+	case TINYKTX_GL_INTFORMAT_UNSIGNED_INT_10F_11F_11F_REV: return TKTX_B10G11R11_UFLOAT_PACK32; //?
+	case TINYKTX_GL_INTFORMAT_RGB9_E5: return TKTX_E5B9G9R9_UFLOAT_PACK32;
+	case TINYKTX_GL_INTFORMAT_SLUMINANCE8_ALPHA8: return TKTX_R8G8_SRGB;
+	case TINYKTX_GL_INTFORMAT_SLUMINANCE8: return TKTX_R8_SRGB;
+	case TINYKTX_GL_INTFORMAT_RGB565: return TKTX_R5G6B5_UNORM_PACK16;
+
+	case TINYKTX_GL_INTFORMAT_ALPHA8: return TKTX_R8_UNORM;
+	case TINYKTX_GL_INTFORMAT_ALPHA16: return TKTX_R16_UNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE8: return TKTX_R8_UNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE16: return TKTX_R16_UNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8: return TKTX_R8G8_UNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16: return TKTX_R16G16_UNORM;
+	case TINYKTX_GL_INTFORMAT_INTENSITY8: return TKTX_R8_UNORM;
+	case TINYKTX_GL_INTFORMAT_INTENSITY16: return TKTX_R16_UNORM;
+
+	case TINYKTX_GL_INTFORMAT_ALPHA8_SNORM: return TKTX_R8_SNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE8_SNORM: return TKTX_R8_SNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE8_ALPHA8_SNORM: return TKTX_R8G8_SNORM;
+	case TINYKTX_GL_INTFORMAT_INTENSITY8_SNORM: return TKTX_R8_SNORM;
+	case TINYKTX_GL_INTFORMAT_ALPHA16_SNORM: return TKTX_R16_SNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE16_SNORM: return TKTX_R16_SNORM;
+	case TINYKTX_GL_INTFORMAT_LUMINANCE16_ALPHA16_SNORM: return TKTX_R16G16_SNORM;
+	case TINYKTX_GL_INTFORMAT_INTENSITY16_SNORM: return TKTX_R16_SNORM;
+
+	case TINYKTX_GL_INTFORMAT_RGB5_A1:
+		if (gltype == TINYKTX_GL_TYPE_UNSIGNED_SHORT_1_5_5_5_REV) {
+			return TKTX_A1R5G5B5_UNORM_PACK16;
+		} else if (gltype == TINYKTX_GL_TYPE_UNSIGNED_SHORT_5_5_5_1) {
+			return TKTX_R5G5B5A1_UNORM_PACK16;
+		}
+		break;
+
+	case TINYKTX_GL_INTFORMAT_SRGB8:
+	case TINYKTX_GL_INTFORMAT_SRGB8_ALPHA8:
+		if (glformat == TINYKTX_GL_FORMAT_SLUMINANCE) {
+			return TKTX_R8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_SLUMINANCE_ALPHA) {
+			return TKTX_R8G8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_SRGB) {
+			return TKTX_R8G8B8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_SRGB_ALPHA) {
+			return TKTX_R8G8B8A8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_BGR) {
+			return TKTX_B8G8R8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_BGRA) {
+			return TKTX_B8G8R8A8_SRGB;
+		} else if (glformat == TINYKTX_GL_FORMAT_ABGR) {
+			return TKTX_A8B8G8R8_SRGB_PACK32;
+		}
+		break;
+	case TINYKTX_GL_INTFORMAT_RGBA4:
+		if(glformat == TINYKTX_GL_FORMAT_RGBA) {
+			return TKTX_R4G4B4A4_UNORM_PACK16;
+		} else if(glformat == TINYKTX_GL_FORMAT_BGRA) {
+			return TKTX_B4G4R4A4_UNORM_PACK16;
+		}
+		break;
+
+	case TINYKTX_GL_INTFORMAT_RGB10_A2:
+		if(glformat == TINYKTX_GL_FORMAT_BGRA) {
+			return TKTX_A2R10G10B10_UNORM_PACK32;
+		} else if(glformat == TINYKTX_GL_FORMAT_RGBA) {
+			return TKTX_A2B10G10R10_UNORM_PACK32;
+		} else		if(glformat == TINYKTX_GL_FORMAT_BGRA_INTEGER) {
+			return TKTX_A2R10G10B10_UINT_PACK32;
+		} else if(glformat == TINYKTX_GL_FORMAT_RGBA_INTEGER) {
+			return TKTX_A2B10G10R10_UINT_PACK32;
+		}
+		break;
+
+			// can't handle yet
+	case TINYKTX_GL_INTFORMAT_ALPHA4:
+	case TINYKTX_GL_INTFORMAT_ALPHA12:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE4:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE12:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE4_ALPHA4:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE6_ALPHA2:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA4:
+	case TINYKTX_GL_INTFORMAT_LUMINANCE12_ALPHA12:
+	case TINYKTX_GL_INTFORMAT_INTENSITY4:
+	case TINYKTX_GL_INTFORMAT_INTENSITY12:
+	case TINYKTX_GL_INTFORMAT_RGB2:
+	case TINYKTX_GL_INTFORMAT_RGB4:
+	case TINYKTX_GL_INTFORMAT_RGB5:
+	case TINYKTX_GL_INTFORMAT_RGB10:
+	case TINYKTX_GL_INTFORMAT_RGB12:
+	case TINYKTX_GL_INTFORMAT_RGBA2:
+	case TINYKTX_GL_INTFORMAT_RGBA12:
+	case TINYKTX_GL_INTFORMAT_FLOAT_32_UNSIGNED_INT_24_8_REV:
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2:
+	case TINYKTX_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2:
+	case TINYKTX_GL_COMPRESSED_ATC_RGB:
+	case TINYKTX_GL_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA:
+	case TINYKTX_GL_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA:
+	default: break;
+	}
+	return TKTX_UNDEFINED;
+}
+
+TinyKtx_Format TinyKtx_GetFormat(TinyKtx_ContextHandle handle) {
+	uint32_t glformat;
+	uint32_t gltype;
+	uint32_t glinternalformat;
+	uint32_t typesize;
+	uint32_t glbaseinternalformat;
+
+	if(TinyKtx_GetFormatGL(handle, &glformat, &gltype, &glinternalformat, &typesize, &glbaseinternalformat) == false)
+		return TKTX_UNDEFINED;
+
+	return TinyKtx_CrackFormatFromGL(glformat, gltype, glinternalformat, typesize);
+}
+
+bool TinyKtx_WriteImage(TinyKtx_WriteCallbacks const *callbacks,
+												void *user,
+												uint32_t width,
+												uint32_t height,
+												uint32_t depth,
+												uint32_t slices,
+												uint32_t mipmaplevels,
+												TinyKtx_Format format,
+												bool cubemap,
+												uint32_t const *mipmapsizes,
+												void const **mipmaps) {
+	uint32_t glformat;
+	uint32_t glinternalFormat;
+	uint32_t gltype;
+	uint32_t gltypeSize;
+	if (TinyKtx_CrackFormatToGL(format, &glformat, &gltype, &glinternalFormat, &gltypeSize) == false)
+		return false;
+
+	return TinyKtx_WriteImageGL(callbacks,
+															user,
+															width,
+															height,
+															depth,
+															slices,
+															mipmaplevels,
+															glformat,
+															glinternalFormat,
+															glinternalFormat, //??
+															gltype,
+															gltypeSize,
+															cubemap,
+															mipmapsizes,
+															mipmaps
+	);
+
+}
+#endif // end #if TINYKTX_WANT_TINYKTX_FORMAT != 0
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // end header
+/*
+BSD 2-Clause License
+
+Copyright (c) 2019, DeanoC
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/