Support KTX texture of R8G8B8 format in `basic` example.
diff --git a/examples/basic/main.cpp b/examples/basic/main.cpp
index 03fb67c..d3b7b4a 100644
--- a/examples/basic/main.cpp
+++ b/examples/basic/main.cpp
@@ -14,6 +14,7 @@
 #endif
 
 // Inlude tinyktx.h before tiny_gltf.h
+// to get TKTX_*** definitions
 #define TINYKTX_IMPLEMENTATION
 #include "../../tinyktx.h"
 
@@ -27,6 +28,8 @@
 #define TINYGLTF_NOEXCEPTION
 #define JSON_NOEXCEPTION
 #define TINYGLTF_ENABLE_KTX
+// tinyktx.h is already included above,
+// so let tiny_gltf.h know do not include tinyktx.h anymore
 #define TINYGLTF_NO_INCLUDE_TINY_KTX
 #include "../../tiny_gltf.h"
 
@@ -56,6 +59,30 @@
   return res;
 }
 
+static bool GetOpenGLFormatFromKTX(int ktx_fmt, GLint *internal_format, GLenum *format, GLenum *type) {
+#if defined(TINYGLTF_ENABLE_KTX)
+    bool ret = true;
+
+    std::cout << "fmt = " << ktx_fmt << ", rgb8 fmt = " << TKTX_R8G8B8_UNORM << "\n";
+
+    if (ktx_fmt == TKTX_R8G8B8_UNORM) {
+      (*internal_format) = GL_RGB;
+      (*format) = GL_RGB;
+      (*type) = GL_UNSIGNED_BYTE;
+    } else {
+      // TODO(syoyo): Support more KTX formats.
+      ret = false;
+    }
+
+    return ret;
+#else
+    (void)fmt;
+    (void)internal_format;
+    (void)internal_format;
+    return false;
+#endif
+}
+
 std::map<int, GLuint> bindMesh(std::map<int, GLuint> vbos,
                                tinygltf::Model &model, tinygltf::Mesh &mesh) {
   for (size_t i = 0; i < model.bufferViews.size(); ++i) {
@@ -114,7 +141,7 @@
                               accessor.normalized ? GL_TRUE : GL_FALSE,
                               byteStride, BUFFER_OFFSET(accessor.byteOffset));
       } else
-        std::cout << "vaa missing: " << attrib.first << std::endl;
+        std::cout << "Unsupported vertex attribute: " << attrib.first << std::endl;
     }
 
     GLuint texid;
@@ -130,29 +157,52 @@
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
+    GLint internal_format = GL_RGBA;
     GLenum format = GL_RGBA;
-
-    if (image.component == 1) {
-      format = GL_RED;
-    } else if (image.component == 2) {
-      format = GL_RG;
-    } else if (image.component == 3) {
-      format = GL_RGB;
-    } else {
-      // ???
-    }
-
     GLenum type = GL_UNSIGNED_BYTE;
-    if (image.bits == 8) {
-      // ok
-    } else if (image.bits == 16) {
-      type = GL_UNSIGNED_SHORT;
+
+    bool valid = false;
+
+    // KTX extension
+    if (image.extras.Has("ktx_format")) {
+
+      valid = GetOpenGLFormatFromKTX(image.extras.Get("ktx_format").Get<int>(), &internal_format, &format, &type);
+
+      if (valid) {
+
+        std::cout << "ktx_format: " << image.extras.Get("ktx_format").Get<int>() << std::endl;
+        std::cout << "ktx image size: " << image.width << ", " << image.height << std::endl;
+      }
+
     } else {
-      // ???
+
+      if (image.component == 1) {
+        format = GL_RED;
+      } else if (image.component == 2) {
+        format = GL_RG;
+      } else if (image.component == 3) {
+        format = GL_RGB;
+      } else if (image.component == 4) {
+        format = GL_RGBA;
+      } else {
+        valid = false;
+      }
+
+      if (image.bits == 8) {
+        // ok
+      } else if (image.bits == 16) {
+        type = GL_UNSIGNED_SHORT;
+      } else {
+        valid = false;
+      }
+
     }
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0,
-                 format, type, &image.image.at(0));
+    if (valid) {
+
+      glTexImage2D(GL_TEXTURE_2D, 0, internal_format, image.width, image.height, 0,
+                   format, type, &image.image.at(0));
+    }
   }
 
   return vbos;
diff --git a/models/Cube-KTX/Cube.bin b/models/Cube-KTX/Cube.bin
new file mode 100644
index 0000000..7dae4b0
--- /dev/null
+++ b/models/Cube-KTX/Cube.bin
Binary files differ
diff --git a/models/Cube-KTX/Cube.gltf b/models/Cube-KTX/Cube.gltf
new file mode 100644
index 0000000..fc8aca0
--- /dev/null
+++ b/models/Cube-KTX/Cube.gltf
@@ -0,0 +1,193 @@
+{
+   "accessors" : [
+      {
+         "bufferView" : 0,
+         "byteOffset" : 0,
+         "componentType" : 5123,
+         "count" : 36,
+         "max" : [
+            35
+         ],
+         "min" : [
+            0
+         ],
+         "type" : "SCALAR"
+      },
+      {
+         "bufferView" : 1,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000,
+            1.000001
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC3"
+      },
+      {
+         "bufferView" : 2,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000,
+            1.000000
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC3"
+      },
+      {
+         "bufferView" : 3,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            -0.000000,
+            -0.000000,
+            1.000000
+         ],
+         "min" : [
+            0.000000,
+            -0.000000,
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC4"
+      },
+      {
+         "bufferView" : 4,
+         "byteOffset" : 0,
+         "componentType" : 5126,
+         "count" : 36,
+         "max" : [
+            1.000000,
+            1.000000
+         ],
+         "min" : [
+            -1.000000,
+            -1.000000
+         ],
+         "type" : "VEC2"
+      }
+   ],
+   "asset" : {
+      "generator" : "VKTS glTF 2.0 exporter",
+      "version" : "2.0"
+   },
+   "bufferViews" : [
+      {
+         "buffer" : 0,
+         "byteLength" : 72,
+         "byteOffset" : 0,
+         "target" : 34963
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 432,
+         "byteOffset" : 72,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 432,
+         "byteOffset" : 504,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 576,
+         "byteOffset" : 936,
+         "target" : 34962
+      },
+      {
+         "buffer" : 0,
+         "byteLength" : 288,
+         "byteOffset" : 1512,
+         "target" : 34962
+      }
+   ],
+   "buffers" : [
+      {
+         "byteLength" : 1800,
+         "uri" : "Cube.bin"
+      }
+   ],
+   "images" : [
+      {
+         "uri" : "Cube_BaseColor.ktx"
+      },
+      {
+         "uri" : "Cube_MetallicRoughness.ktx"
+      }
+   ],
+   "materials" : [
+      {
+         "name" : "Cube",
+         "pbrMetallicRoughness" : {
+            "baseColorTexture" : {
+               "index" : 0
+            },
+            "metallicRoughnessTexture" : {
+               "index" : 1
+            }
+         }
+      }
+   ],
+   "meshes" : [
+      {
+         "name" : "Cube",
+         "primitives" : [
+            {
+               "attributes" : {
+                  "NORMAL" : 2,
+                  "POSITION" : 1,
+                  "TANGENT" : 3,
+                  "TEXCOORD_0" : 4
+               },
+               "indices" : 0,
+               "material" : 0,
+               "mode" : 4
+            }
+         ]
+      }
+   ],
+   "nodes" : [
+      {
+         "mesh" : 0,
+         "name" : "Cube"
+      }
+   ],
+   "samplers" : [
+      {}
+   ],
+   "scene" : 0,
+   "scenes" : [
+      {
+         "nodes" : [
+            0
+         ]
+      }
+   ],
+   "textures" : [
+      {
+         "sampler" : 0,
+         "source" : 0
+      },
+      {
+         "sampler" : 0,
+         "source" : 1
+      }
+   ]
+}
diff --git a/models/Cube-KTX/Cube_BaseColor.ktx b/models/Cube-KTX/Cube_BaseColor.ktx
new file mode 100644
index 0000000..888c9e7
--- /dev/null
+++ b/models/Cube-KTX/Cube_BaseColor.ktx
Binary files differ
diff --git a/models/Cube-KTX/Cube_MetallicRoughness.ktx b/models/Cube-KTX/Cube_MetallicRoughness.ktx
new file mode 100644
index 0000000..4df13a7
--- /dev/null
+++ b/models/Cube-KTX/Cube_MetallicRoughness.ktx
Binary files differ
diff --git a/models/Cube-KTX/README.md b/models/Cube-KTX/README.md
new file mode 100644
index 0000000..f9f032c
--- /dev/null
+++ b/models/Cube-KTX/README.md
@@ -0,0 +1,12 @@
+License: Donated by Norbert Nopper for glTF testing.
+
+https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Cube
+
+
+----
+
+Converted .png to .ktx image by Syoyo Fujita.
+
+.png -> .ppm using image magic(resize with 25% to reduce file size)
+.ppm -> .ktx using `toktx` in KTX-Software https://github.com/KhronosGroup/KTX-Software
+
diff --git a/tiny_gltf.h b/tiny_gltf.h
index 888053e..883fd52 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -1808,6 +1808,7 @@
 
 static void *tinyktxCallbackAlloc(void *user, size_t size) {
   (void)user;
+  //std::cerr << "Alloc : " << std::to_string(size) << "\n";
   return malloc(size);
 };
 
@@ -1819,7 +1820,7 @@
 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->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";
@@ -1830,6 +1831,9 @@
 
   memcpy(data, ss->data + ss->pos, size);
 
+  // Advance pos
+  ss->pos += size;
+
   return size;
 };
 
@@ -1871,7 +1875,7 @@
                   &tinyktxCallbackError,
                   &tinyktxCallbackAlloc,
                   &tinyktxCallbackFree,
-                  tinyktxCallbackRead,
+                  &tinyktxCallbackRead,
                   &tinyktxCallbackSeek,
                   &tinyktxCallbackTell
   };
@@ -1920,6 +1924,12 @@
       return false;
     }
 
+    const void *src_ptr = TinyKtx_ImageRawData(ctx, miplevel);
+    if (src_ptr == nullptr) {
+      TinyKtx_DestroyContext(ctx);
+      return false;
+    }
+
     image->image.resize(byte_count);
     memcpy(image->image.data(), TinyKtx_ImageRawData(ctx, miplevel), byte_count);
 
@@ -1952,34 +1962,49 @@
 
   bool ret = false;
 
+  std::string stb_err;
+  std::string stb_warn;
+
+#if !defined(TINYGLTF_NO_STB_IMAGE)
+  // Try to load images using stb_image(png, gif, bmp, tga, ...)
+
+  ret = tinygltf::LoadImageDataSTB(image, image_idx, &stb_err, &stb_warn, req_width, req_height,
+                   bytes, size, user_data);
+
+  if (ret) {
+    return true;
+  }
+
+#endif
+
+  std::string ktx_err;
+  std::string ktx_warn;
+
 #if defined(TINYGLTF_ENABLE_KTX)
   // Try KTX image
 
-  ret = tinygltf::LoadImageDataKTX(image, image_idx, err, warn, req_width, req_height,
+  ret = tinygltf::LoadImageDataKTX(image, image_idx, &ktx_err, &ktx_warn, req_width, req_height,
                    bytes, size, user_data);
 
   if (ret) {
+    if (warn) {
+      (*warn) = ktx_warn;
+    }
     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;
+  if (err) {
+    (*err) = stb_err + ktx_err;
   }
 
-#endif
+  if (warn) {
+    (*warn) = stb_warn + ktx_warn;
+  }
 
   (void)image;
   (void)image_idx;
-  (void)err;
-  (void)warn;
   (void)req_width;
   (void)req_height;
   (void)bytes;