Browse Source

Separated png module from opengl, added unit test for png (#1693) [ci skip]

* ENH: separate png from opengl, by splitting it into stb and opengl_image modules
     Added a unit test for PNG,BMP,TGA,JPG reading and writing
     Renamed module png to stb
     Renamed functions readPNG to read_image and writePNG to write_image

* name folder by dependency; consistent arg order

---------

Co-authored-by: Alec Jacobson <[email protected]>
Vladimir S. FONOV 2 years ago
parent
commit
02e0a1ba83

+ 2 - 1
CMakeLists.txt

@@ -91,7 +91,7 @@ option(LIBIGL_EMBREE           "Build target igl::embree"           ${LIBIGL_TOP
 option(LIBIGL_GLFW             "Build target igl::glfw"             ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_GLFW             "Build target igl::glfw"             ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_IMGUI            "Build target igl::imgui"            ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_IMGUI            "Build target igl::imgui"            ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_OPENGL           "Build target igl::opengl"           ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_OPENGL           "Build target igl::opengl"           ${LIBIGL_TOPLEVEL_PROJECT})
-option(LIBIGL_PNG              "Build target igl::png"              ${LIBIGL_TOPLEVEL_PROJECT})
+option(LIBIGL_STB              "Build target igl::stb"              ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_PREDICATES       "Build target igl::predicates"       ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_PREDICATES       "Build target igl::predicates"       ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_SPECTRA          "Build target igl::spectra"          ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_SPECTRA          "Build target igl::spectra"          ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_XML              "Build target igl::xml"              ${LIBIGL_TOPLEVEL_PROJECT})
 option(LIBIGL_XML              "Build target igl::xml"              ${LIBIGL_TOPLEVEL_PROJECT})
@@ -168,3 +168,4 @@ if(LIBIGL_INSTALL)
     write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
     write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
     install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}")
     install(FILES "${project_config_out}" "${version_config_file}" DESTINATION "${export_dest_dir}")
 endif()
 endif()
+

+ 1 - 1
LibiglOptions.cmake.sample

@@ -56,7 +56,7 @@
 # option(LIBIGL_GLFW                "Build target igl::glfw"                ON)
 # option(LIBIGL_GLFW                "Build target igl::glfw"                ON)
 # option(LIBIGL_IMGUI               "Build target igl::imgui"               ON)
 # option(LIBIGL_IMGUI               "Build target igl::imgui"               ON)
 # option(LIBIGL_OPENGL              "Build target igl::opengl"              ON)
 # option(LIBIGL_OPENGL              "Build target igl::opengl"              ON)
-# option(LIBIGL_PNG                 "Build target igl::png"                 ON)
+# option(LIBIGL_STB                 "Build target igl::stb"                 ON)
 # option(LIBIGL_PREDICATES          "Build target igl::predicates"          ON)
 # option(LIBIGL_PREDICATES          "Build target igl::predicates"          ON)
 # option(LIBIGL_XML                 "Build target igl::xml"                 ON)
 # option(LIBIGL_XML                 "Build target igl::xml"                 ON)
 # option(LIBIGL_COPYLEFT_CGAL       "Build target igl_copyleft::cgal"       ON)
 # option(LIBIGL_COPYLEFT_CGAL       "Build target igl_copyleft::cgal"       ON)

+ 0 - 23
cmake/igl/modules/png.cmake

@@ -1,23 +0,0 @@
-# 1. Define module
-igl_add_library(igl_png)
-
-# 2. Include headers
-include(GNUInstallDirs)
-target_include_directories(igl_png ${IGL_SCOPE}
-    $<BUILD_INTERFACE:${libigl_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-)
-
-# 3. Target sources
-file(GLOB INC_FILES "${libigl_SOURCE_DIR}/include/igl/png/*.h")
-file(GLOB SRC_FILES "${libigl_SOURCE_DIR}/include/igl/png/*.cpp")
-igl_target_sources(igl_png ${INC_FILES} ${SRC_FILES})
-
-# 4. Dependencies
-include(stb)
-igl_include(opengl)
-target_link_libraries(igl_png ${IGL_SCOPE}
-    igl::core
-    igl::opengl
-    stb::stb
-)

+ 35 - 0
cmake/igl/modules/stb.cmake

@@ -0,0 +1,35 @@
+# 1. Define module
+igl_add_library(igl_stb)
+
+# 2. Include headers
+include(GNUInstallDirs)
+target_include_directories(igl_stb ${IGL_SCOPE}
+    $<BUILD_INTERFACE:${libigl_SOURCE_DIR}/include>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+# 3. Target sources
+file(GLOB INC_FILES "${libigl_SOURCE_DIR}/include/igl/stb/*.h")
+file(GLOB SRC_FILES "${libigl_SOURCE_DIR}/include/igl/stb/*.cpp")
+if(LIBIGL_OPENGL)
+  message(STATUS "Including igl/opengl/stb support")
+  file(GLOB OPENGL_INC_FILES "${libigl_SOURCE_DIR}/include/igl/opengl/stb/*.h")
+  file(GLOB OPENGL_SRC_FILES "${libigl_SOURCE_DIR}/include/igl/opengl/stb/*.cpp")
+  list(APPEND INC_FILES ${OPENGL_INC_FILES})
+  list(APPEND SRC_FILES ${OPENGL_SRC_FILES})
+endif()
+igl_target_sources(igl_stb ${INC_FILES} ${SRC_FILES})
+
+# 4. Dependencies
+include(stb)
+target_link_libraries(igl_stb ${IGL_SCOPE}
+    igl::core
+    stb::stb
+)
+
+if(LIBIGL_OPENGL)
+  igl_include(opengl)
+  target_link_libraries(igl_stb ${IGL_SCOPE}
+      igl::opengl
+  )
+endif()

+ 1 - 1
cmake/libigl.cmake

@@ -18,7 +18,7 @@ igl_include_optional(opengl)
 igl_include_optional(glfw)
 igl_include_optional(glfw)
 igl_include_optional(imgui)
 igl_include_optional(imgui)
 igl_include_optional(predicates)
 igl_include_optional(predicates)
-igl_include_optional(png)
+igl_include_optional(stb)
 igl_include_optional(spectra)
 igl_include_optional(spectra)
 igl_include_optional(xml)
 igl_include_optional(xml)
 
 

+ 6 - 5
include/igl/png/render_to_png.cpp → include/igl/opengl/stb/render_to_file.cpp

@@ -5,13 +5,14 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
-#include "render_to_png.h"
+#include "render_to_file.h"
+#include "../../stb/write_image.h"
 #include <stb_image_write.h>
 #include <stb_image_write.h>
 
 
-#include "../opengl/gl.h"
+#include "../gl.h"
 
 
-IGL_INLINE bool igl::png::render_to_png(
-  const std::string png_file,
+IGL_INLINE bool igl::opengl::stb::render_to_file(
+  const std::string filename,
   const int width,
   const int width,
   const int height,
   const int height,
   const bool alpha,
   const bool alpha,
@@ -35,7 +36,7 @@ IGL_INLINE bool igl::png::render_to_png(
       data[4*(i+j*width)+3] = 255;
       data[4*(i+j*width)+3] = 255;
     }
     }
   }
   }
-  bool ret = stbi_write_png(png_file.c_str(), width, height, 4, data, 4*width*sizeof(unsigned char));
+  const bool ret = igl::stb::write_image(filename,width,height,data);
   delete [] data;
   delete [] data;
   return ret;
   return ret;
 }
 }

+ 43 - 0
include/igl/opengl/stb/render_to_file.h

@@ -0,0 +1,43 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <[email protected]>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_OPENGL_STB_RENDER_TO_PNG_H
+#define IGL_OPENGL_STB_RENDER_TO_PNG_H
+#include "../../igl_inline.h"
+
+#include <string>
+namespace igl
+{
+  namespace opengl
+  {
+    namespace stb
+    {
+      /// Render current open GL image to an image file
+      ///
+      /// @param[in] filename  path to output file
+      /// @param[in] width  width of scene and resulting image
+      /// @param[in] height height of scene and resulting image
+      /// @param[in] alpha  whether to include alpha channel
+      /// @param[in] fast  sacrifice compression ratio for speed
+      /// @return true only if no errors occurred
+      ///
+      /// \see igl::stb::write_image, render_to_file_async
+      IGL_INLINE bool render_to_file(
+        const std::string filename,
+        const int width,
+        const int height,
+        const bool alpha = true,
+        const bool fast = false);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "render_to_file.cpp"
+#endif
+
+#endif

+ 9 - 8
include/igl/png/render_to_png_async.cpp → include/igl/opengl/stb/render_to_file_async.cpp

@@ -5,13 +5,14 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
-#include "render_to_png_async.h"
-#include "../opengl/gl.h"
+#include "render_to_file_async.h"
+#include "../../stb/write_image.h"
+#include "../gl.h"
 #include <stb_image_write.h>
 #include <stb_image_write.h>
 
 
-static IGL_INLINE bool render_to_png_async_helper(
+static IGL_INLINE bool render_to_file_async_helper(
   unsigned char * img, int width, int height,
   unsigned char * img, int width, int height,
-  const std::string png_file,
+  const std::string filename,
   const bool alpha,
   const bool alpha,
   const bool fast)
   const bool fast)
 {
 {
@@ -25,13 +26,13 @@ static IGL_INLINE bool render_to_png_async_helper(
     }
     }
   }
   }
 
 
-  bool ret = stbi_write_png(png_file.c_str(), width, height, 4, img, width*sizeof(unsigned char));
+  const bool ret = igl::stb::write_image(filename,width,height,img);
   delete [] img;
   delete [] img;
   return ret;
   return ret;
 }
 }
 
 
-IGL_INLINE std::thread igl::png::render_to_png_async(
-  const std::string png_file,
+IGL_INLINE std::thread igl::opengl::stb::render_to_file_async(
+  const std::string filename,
   const int width,
   const int width,
   const int height,
   const int height,
   const bool alpha,
   const bool alpha,
@@ -48,7 +49,7 @@ IGL_INLINE std::thread igl::png::render_to_png_async(
     GL_UNSIGNED_BYTE,
     GL_UNSIGNED_BYTE,
     data);
     data);
   // Part that should be asynchronous
   // Part that should be asynchronous
-  std::thread t(render_to_png_async_helper,data,width,height,png_file,alpha,fast);
+  std::thread t(render_to_file_async_helper,data,width,height,filename,alpha,fast);
   t.detach();
   t.detach();
   return t;
   return t;
 }
 }

+ 48 - 0
include/igl/opengl/stb/render_to_file_async.h

@@ -0,0 +1,48 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <[email protected]>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_OPENGL_STB_RENDER_TO_PNG_ASYNC_H
+#define IGL_OPENGL_STB_RENDER_TO_PNG_ASYNC_H
+#include "../../igl_inline.h"
+#include <thread>
+//#include <boost/thread/thread.hpp>
+
+#include <string>
+namespace igl
+{
+  namespace opengl
+  {
+    namespace stb
+    {
+      // History:
+      //  added multithreaded parameter and support, Alec Sept 3, 2012
+      //
+      /// Render current open GL image to file using a separate thread
+      ///
+      /// @param[in] filename  path to output image file
+      /// @param[in] width  width of scene and resulting image
+      /// @param[in] height height of scene and resulting image
+      /// @param[in] alpha  whether to include alpha channel
+      /// @param[in] fast  sacrifice compression ratio for speed
+      /// @return true only if no errors occurred
+      ///
+      /// \see render_to_file
+      IGL_INLINE std::thread render_to_file_async(
+        const std::string filename,
+        const int width,
+        const int height,
+        const bool alpha = true,
+        const bool fast = false);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "render_to_file_async.cpp"
+#endif
+
+#endif

+ 0 - 40
include/igl/png/readPNG.h

@@ -1,40 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2016 Daniele Panozzo <[email protected]>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_READ_PNG_H
-#define IGL_PNG_READ_PNG_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <string>
-
-namespace igl
-{
-  namespace png
-  {
-    /// Read an image from a .png file into 4 memory buffers
-    ///
-    /// @param[in] png_file  path to .png file
-    /// @param[out] R  red channel
-    /// @param[out] G  green channel
-    /// @param[out] B  blue channel
-    /// @param[out] A  alpha channel
-    /// @return true on success, false on failure
-    ///
-    IGL_INLINE bool readPNG(const std::string png_file,
-    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
-    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
-    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
-    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
-    );
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "readPNG.cpp"
-#endif
-
-#endif

+ 0 - 40
include/igl/png/render_to_png.h

@@ -1,40 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2013 Alec Jacobson <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_RENDER_TO_PNG_H
-#define IGL_PNG_RENDER_TO_PNG_H
-#include "../igl_inline.h"
-
-#include <string>
-namespace igl
-{
-  namespace png
-  {
-    /// Render current open GL image to .png file
-    ///
-    /// @param[in] png_file  path to output .png file
-    /// @param[in] width  width of scene and resulting image
-    /// @param[in] height height of scene and resulting image
-    /// @param[in] alpha  whether to include alpha channel
-    /// @param[in] fast  sacrifice compression ratio for speed
-    /// @return true only if no errors occurred
-    ///
-    /// \see render_to_tga which is faster but writes .tga files
-    IGL_INLINE bool render_to_png(
-      const std::string png_file,
-      const int width,
-      const int height,
-      const bool alpha = true,
-      const bool fast = false);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "render_to_png.cpp"
-#endif
-
-#endif

+ 0 - 45
include/igl/png/render_to_png_async.h

@@ -1,45 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2013 Alec Jacobson <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_RENDER_TO_PNG_ASYNC_H
-#define IGL_PNG_RENDER_TO_PNG_ASYNC_H
-#include "../igl_inline.h"
-#include <thread>
-//#include <boost/thread/thread.hpp>
-
-#include <string>
-namespace igl
-{
-  namespace png
-  {
-    // History:
-    //  added multithreaded parameter and support, Alec Sept 3, 2012
-    //
-    /// Render current open GL image to .png file using a separate thread
-    ///
-    /// @param[in] png_file  path to output .png file
-    /// @param[in] width  width of scene and resulting image
-    /// @param[in] height height of scene and resulting image
-    /// @param[in] alpha  whether to include alpha channel
-    /// @param[in] fast  sacrifice compression ratio for speed
-    /// @return true only if no errors occurred
-    ///
-    /// \see render_to_png
-    IGL_INLINE std::thread render_to_png_async(
-      const std::string png_file,
-      const int width,
-      const int height,
-      const bool alpha = true,
-      const bool fast = false);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "render_to_png_async.cpp"
-#endif
-
-#endif

+ 0 - 61
include/igl/png/texture_from_file.cpp

@@ -1,61 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Alec Jacobson <[email protected]>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "texture_from_file.h"
-
-#include "texture_from_png.h"
-#include "../STR.h"
-#include "../pathinfo.h"
-#include "../opengl/report_gl_error.h"
-//#include "../opengl2/texture_from_tga.h"
-#include <string>
-#include <algorithm>
-#include <iostream>
-
-IGL_INLINE bool igl::png::texture_from_file(const std::string filename, GLuint & id)
-{
-  using namespace igl::opengl;
-  using namespace std;
-  // dirname, basename, extension and filename
-  string d,b,ext,f;
-  pathinfo(filename,d,b,ext,f);
-  // Convert extension to lower case
-  transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
-  //if(ext == "tga")
-  //{
-  //  return texture_from_tga(filename,id);
-  //}else 
-  if(ext == "png")
-  {
-    return texture_from_png(filename,id);
-  }else
-  {
-#ifdef __APPLE__
-    // Convert to a temporary png file
-    string tmp = "/var/tmp/.texture_from_file.png";
-#define PATH_TO_CONVERT "/opt/local/bin/convert"
-    string command = STR(PATH_TO_CONVERT<<" \""<<filename<<"\" \""<<tmp<<"\"");
-    try
-    {
-      if(system(command.c_str())==0)
-      {
-        return texture_from_file(tmp.c_str(),id);
-      }else
-      {
-        cerr<<"texture_from_file: calling to convert ('"<<command<<"') failed..."<<endl;
-        return false;
-      }
-    }catch(int e)
-    {
-      cerr<<"^"<<__FUNCTION__<<": Calling to convert crashed..."<<endl;
-      return false;
-    }
-#else
-    return false;
-#endif
-  }
-}

+ 0 - 37
include/igl/png/texture_from_file.h

@@ -1,37 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_TEXTURE_FROM_FILE_H
-#define IGL_PNG_TEXTURE_FROM_FILE_H
-#include "../igl_inline.h"
-#include "../opengl/gl.h"
-
-#include <string>
-
-namespace igl
-{
-  namespace png
-  {
-    /// Read an image from an image file and use it as a texture. Officially,
-    /// only <del>.tga and</del> .png are supported. Any filetype read by
-    /// ImageMagick's `convert` will work via an unsafe system call.
-    ///
-    /// @param[in] filename  path to image file
-    /// @param[out] id  of generated openGL texture
-    /// @return true on success, false on failure
-    IGL_INLINE bool texture_from_file(const std::string filename, GLuint & id);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "texture_from_file.cpp"
-#endif
-
-#endif
-
-
-

+ 0 - 48
include/igl/png/texture_from_png.cpp

@@ -1,48 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Alec Jacobson <[email protected]>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "texture_from_png.h"
-
-#include "../opengl/report_gl_error.h"
-#include <stb_image.h>
-
-IGL_INLINE bool igl::png::texture_from_png(const std::string png_file, const bool flip, GLuint & id)
-{
-  int width,height,n;
-  unsigned char *data = stbi_load(png_file.c_str(), &width, &height, &n, 4);
-  if(data == NULL) {
-    return false;
-  }
-
-  // Why do I need to flip?
-  /*if(flip)
-  {
-    yimg.flip();
-  }*/
-
-  glGenTextures(1, &id);
-  glBindTexture(GL_TEXTURE_2D, id);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-  glTexImage2D(
-    GL_TEXTURE_2D, 0, GL_RGB,
-    width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
-  glBindTexture(GL_TEXTURE_2D, 0);
-
-  stbi_image_free(data);
-
-  return true;
-}
-
-IGL_INLINE bool igl::png::texture_from_png(const std::string png_file, GLuint & id)
-{
-  return texture_from_png(png_file,false,id);
-}
-
-

+ 0 - 36
include/igl/png/texture_from_png.h

@@ -1,36 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Alec Jacobson <[email protected]>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_TEXTURE_FROM_PNG_H
-#define IGL_PNG_TEXTURE_FROM_PNG_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <string>
-
-#include "../opengl/gl.h"
-
-namespace igl
-{
-  namespace png
-  {
-    /// Read an image from a .png file and use it as a texture
-    ///
-    /// @param[in] png_file  path to .png file
-    /// @param[in] flip  whether to flip the image vertically (A --> ∀)
-    /// @param[out] id  of generated openGL texture
-    /// @return true on success, false on failure
-    IGL_INLINE bool texture_from_png(const std::string png_file, const bool flip, GLuint & id);
-    /// \overload 
-    IGL_INLINE bool texture_from_png(const std::string png_file, GLuint & id);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "texture_from_png.cpp"
-#endif
-
-#endif

+ 0 - 42
include/igl/png/writePNG.h

@@ -1,42 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2016 Daniele Panozzo <[email protected]>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_PNG_WRITE_PNG_H
-#define IGL_PNG_WRITE_PNG_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <string>
-
-namespace igl
-{
-  namespace png
-  {
-    /// Writes an image to a png file
-    ///
-    /// @param[in] R  red channel
-    /// @param[in] G  green channel
-    /// @param[in] B  blue channel
-    /// @param[in] A  alpha channel
-    /// @param[in] png_file  path to .png file
-    /// Returns true on success, false on failure
-    ///
-    IGL_INLINE bool writePNG
-    (
-      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
-      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
-      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
-      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
-      const std::string png_file
-    );
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "writePNG.cpp"
-#endif
-
-#endif

+ 4 - 4
include/igl/png/readPNG.cpp → include/igl/stb/read_image.cpp

@@ -5,11 +5,11 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
-#include "readPNG.h"
+#include "read_image.h"
 #include <stb_image.h>
 #include <stb_image.h>
 
 
-IGL_INLINE bool igl::png::readPNG(
-  const std::string png_file,
+IGL_INLINE bool igl::stb::read_image(
+  const std::string image_file,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
@@ -17,7 +17,7 @@ IGL_INLINE bool igl::png::readPNG(
 )
 )
 {
 {
   int cols,rows,n;
   int cols,rows,n;
-  unsigned char *data = stbi_load(png_file.c_str(), &cols, &rows, &n, 4);
+  unsigned char *data = stbi_load(image_file.c_str(), &cols, &rows, &n, 4);
   if(data == NULL) {
   if(data == NULL) {
     return false;
     return false;
   }
   }

+ 52 - 0
include/igl/stb/read_image.h

@@ -0,0 +1,52 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <[email protected]>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_STB_READ_IMAGE_H
+#define IGL_STB_READ_IMAGE_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace stb
+  {
+    // Read an image from a file into 4 memory buffers
+    // 
+    // Supported file formats (based on STB):
+    //  
+    //    JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+    //    PNG 1/2/4/8/16-bit-per-channel
+    //    TGA (not sure what subset, if a subset)
+    //    BMP non-1bpp, non-RLE
+    //    PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+
+    //    GIF (*comp always reports as 4-channel)
+    //    HDR (radiance rgbE format)
+    //    PIC (Softimage PIC)
+    //    PNM (PPM and PGM binary only)
+    //
+    // Input:
+    //  image_file  path to .png file
+    // Output:
+    //  R,G,B,A texture channels
+    // Returns true on success, false on failure
+    //
+    IGL_INLINE bool read_image(const std::string image_file,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
+    );
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "read_image.cpp"
+#endif
+
+#endif

+ 41 - 7
include/igl/png/writePNG.cpp → include/igl/stb/write_image.cpp

@@ -5,23 +5,24 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // This Source Code Form is subject to the terms of the Mozilla Public License
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
-#include "writePNG.h"
+#include "write_image.h"
 #include <stb_image_write.h>
 #include <stb_image_write.h>
 #include <vector>
 #include <vector>
+#include "../pathinfo.h"
 
 
-IGL_INLINE bool igl::png::writePNG(
+IGL_INLINE bool igl::stb::write_image(
+  const std::string image_file,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
   const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
-  const std::string png_file
+  const int quality
 )
 )
 {
 {
   assert((R.rows() == G.rows()) && (G.rows() == B.rows()) && (B.rows() == A.rows()));
   assert((R.rows() == G.rows()) && (G.rows() == B.rows()) && (B.rows() == A.rows()));
   assert((R.cols() == G.cols()) && (G.cols() == B.cols()) && (B.cols() == A.cols()));
   assert((R.cols() == G.cols()) && (G.cols() == B.cols()) && (B.cols() == A.cols()));
 
 
   const int comp = 4;                                  // 4 Channels Red, Green, Blue, Alpha
   const int comp = 4;                                  // 4 Channels Red, Green, Blue, Alpha
-  const int stride_in_bytes = R.rows()*comp;           // Length of one row in bytes
   std::vector<unsigned char> data(R.size()*comp,0);     // The image itself;
   std::vector<unsigned char> data(R.size()*comp,0);     // The image itself;
 
 
   for (unsigned i = 0; i<R.rows();++i)
   for (unsigned i = 0; i<R.rows();++i)
@@ -34,10 +35,43 @@ IGL_INLINE bool igl::png::writePNG(
         data[(j * R.rows() * comp) + (i * comp) + 3] = A(i,R.cols()-1-j);
         data[(j * R.rows() * comp) + (i * comp) + 3] = A(i,R.cols()-1-j);
     }
     }
   }
   }
+  return write_image(image_file,R.rows(),R.cols(),data.data(),quality);
+}
 
 
-  stbi_write_png(png_file.c_str(), R.rows(), R.cols(), comp, data.data(), stride_in_bytes);
-
-  return true;
+IGL_INLINE bool igl::stb::write_image(
+  const std::string image_file,
+  const int width,
+  const int height,
+  const unsigned char * rgba_data,
+  const int quality)
+{
+  const int comp = 4;                                  // 4 Channels Red, Green, Blue, Alpha
+  const int stride_in_bytes = width*comp;           // Length of one row in bytes
+  using namespace std;
+  string d,b,e,f;
+  pathinfo(image_file,d,b,e,f);
+  if(e == "png")
+  {
+    return stbi_write_png(image_file.c_str(), width, height, comp, rgba_data, stride_in_bytes)!=0;
+  } else if( e == "tga") 
+  {
+    return stbi_write_tga(image_file.c_str(), width, height, comp, rgba_data)!=0;
+  } else if( e == "bmp") 
+  {
+    return stbi_write_bmp(image_file.c_str(), width, height, comp, rgba_data)!=0;
+  } else if( e == "jpg") 
+  {
+    return stbi_write_jpg(image_file.c_str(), width, height, comp, rgba_data,quality)!=0;
+  } else 
+  {
+    // unsupported file format
+    return false;  
+  }
+  // not yet.
+  //} else if( e == "hdr") 
+  // {
+  //  return stbi_write_hdr(image_file.c_str(), width, height, comp, rgba_data.rgba_data())!=0;
+  // }
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY

+ 67 - 0
include/igl/stb/write_image.h

@@ -0,0 +1,67 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <[email protected]>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_STB_WRITE_IMAGE_H
+#define IGL_STB_WRITE_IMAGE_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace stb
+  {
+    /// Writes an image to a file
+    /// 
+    /// Supported file formats (based on STB):
+    ///  
+    ///    JPEG 
+    ///    PNG 
+    ///    TGA 
+    ///    BMP 
+    /// 
+    /// @param[in] R  red channel
+    /// @param[in] G  green channel
+    /// @param[in] B  blue channel
+    /// @param[in] A  alpha channel
+    /// @param[in] image_file  path to image file
+    /// @param[in] quality  (only for jpg file) jpeg quality
+    /// @returns true on success, false on errors
+    ///
+    IGL_INLINE bool write_image
+    (
+      const std::string image_file,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
+      const int quality=90
+    );
+    /// Raw image writer.
+    ///
+    /// @param[in] image_file  path to image file
+    /// @param[in] width  image width
+    /// @param[in] height  image height
+    /// @param[in] rgba_data  raw image data
+    /// @param[in] quality  (only for jpg file) jpeg quality
+    /// @returns true on success, false on errors
+    ///
+    IGL_INLINE bool write_image(
+      const std::string image_file,
+      const int width,
+      const int height,
+      const unsigned char * rgba_data,
+      const int quality = 90);
+
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "write_image.cpp"
+#endif
+
+#endif

+ 127 - 0
tests/include/igl/stb/read_write.cpp

@@ -0,0 +1,127 @@
+#include <test_common.h>
+
+#include <catch2/catch.hpp>
+
+#include <igl/stb/write_image.h>
+#include <igl/stb/read_image.h>
+
+namespace {
+    // magick -size 17x29 gradient:white-black -depth 8 test.png
+    // xxd -i test.png
+    #include "test_png.h"
+    // convert test.png test.bmp
+    #include "test_bmp.h"
+    //convert -quality 100% test.png test.jpg
+    #include "test_jpg.h"
+    // convert test.png test.tga
+    #include "test_tga.h"
+    // convert test.png test.pgm
+    #include "test_pgm.h"
+
+    #include "test_reference.h"
+
+    static bool dump_to_file(const unsigned char *buf,int size,const char* fname)
+    {
+        //generate file:
+        FILE *out;
+        if(out=fopen(fname,"wb"))
+        {
+            bool r=(fwrite(buf,1,size,out)==size);
+            r=(fclose(out)==0)&&r;
+            return r;
+        } else {
+            return false;
+        }
+    }
+}
+
+TEST_CASE("read_image","[igl/stb]")
+{
+    // convert -verbose test.png -depth 8 -colorspace Gray -format pgm test.pgm
+    // xxd -i test.pgm # skip header
+    REQUIRE(dump_to_file(test_png,test_png_len,"test.png"));
+    REQUIRE(dump_to_file(test_bmp,test_bmp_len,"test.bmp"));
+    REQUIRE(dump_to_file(test_tga,test_tga_len,"test.tga"));
+    REQUIRE(dump_to_file(test_jpg,test_jpg_len,"test.jpg"));
+    REQUIRE(dump_to_file(test_pgm,test_pgm_len,"test.pgm"));
+
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
+    Eigen::Map<const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic, Eigen::RowMajor > > ref_image(ref_image_raw, 29, 17) ;
+
+    for(auto i:{"test.png","test.bmp","test.tga","test.jpg", "test.pgm"}) 
+    {
+        WHEN(i) {
+            REQUIRE(igl::stb::read_image(i,R,G,B,A));
+
+            //check the size
+            REQUIRE(R.rows()==17);
+            REQUIRE(R.cols()==29);
+
+            REQUIRE(G.rows()==17);
+            REQUIRE(G.cols()==29);
+
+            REQUIRE(B.rows()==17);
+            REQUIRE(B.cols()==29);
+
+            REQUIRE(A.rows()==17);
+            REQUIRE(A.cols()==29);
+
+            // check the contents, it is transposed and upside down 
+            for(int i=0;i<17;++i)
+                for(int j=0;j<29;++j)
+                {
+                    REQUIRE( (unsigned int)R(i,28-j) == (unsigned int)ref_image(j,i) );
+                    REQUIRE( (unsigned int)G(i,28-j) == (unsigned int)ref_image(j,i) );
+                    REQUIRE( (unsigned int)A(i,j) == 255 );
+                }
+        }
+    }
+}
+
+
+TEST_CASE("write_image","[igl/stb]")
+{
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R(17,29),G(17,29),B(17,29),A(17,29),A2(17,29);
+
+    for(int i=0;i<17;++i)
+        for(int j=0;j<29;++j)
+        {
+            R(i,j)=(i+j*17)%255;
+            G(i,j)=(i+j*17+1)%255;
+            B(i,j)=(i+j*17+2)%255;
+            A(i,j)=i+j;
+            A2(i,j)=255;
+        }
+
+    for(auto i:{"check.png","check.bmp","check.tga","check.jpg"}) 
+    {
+        WHEN(i) {
+
+            if(i=="check.png" || i=="check.tga")
+                REQUIRE(igl::stb::write_image(R, G, B, A, i, 100));
+            else // Alpha channel somehow affects other colors in BMP, even though it's not saved
+                REQUIRE(igl::stb::write_image(R, G, B, A2, i, 100));
+
+            // read it back
+            Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> _R,_G,_B,_A;
+            REQUIRE(igl::stb::read_image(i, _R,_G,_B,_A));
+
+            //only PNG and TGA files support alpha channel
+            if(i=="check.png" || i=="check.tga")
+                REQUIRE((A.array()==_A.array()).all());
+
+            if(i=="check.jpg")
+            {
+                // somehow jpeg loses information even with 100% quality
+                REQUIRE((R.cast<float>()-_R.cast<float>()).norm()<R.size()/20.);
+                REQUIRE((G.cast<float>()-_G.cast<float>()).norm()<G.size()/20.);
+                REQUIRE((B.cast<float>()-_B.cast<float>()).norm()<B.size()/20.);
+                
+            } else {
+                REQUIRE((R.array()==_R.array()).all());
+                REQUIRE((G.array()==_G.array()).all());
+                REQUIRE((B.array()==_B.array()).all());
+            }
+        }
+    }
+}

+ 147 - 0
tests/include/igl/stb/test_bmp.h

@@ -0,0 +1,147 @@
+unsigned char test_bmp[] = {
+  0x42, 0x4d, 0xbe, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x04,
+  0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1d, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+  0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x42, 0x47,
+  0x52, 0x73, 0x8f, 0xc2, 0xf5, 0x28, 0x51, 0xb8, 0x1e, 0x15, 0x1e, 0x85,
+  0xeb, 0x01, 0x33, 0x33, 0x33, 0x13, 0x66, 0x66, 0x66, 0x26, 0x66, 0x66,
+  0x66, 0x06, 0x99, 0x99, 0x99, 0x09, 0x3d, 0x0a, 0xd7, 0x03, 0x28, 0x5c,
+  0x8f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+  0x02, 0x00, 0x03, 0x03, 0x03, 0x00, 0x04, 0x04, 0x04, 0x00, 0x05, 0x05,
+  0x05, 0x00, 0x06, 0x06, 0x06, 0x00, 0x07, 0x07, 0x07, 0x00, 0x08, 0x08,
+  0x08, 0x00, 0x09, 0x09, 0x09, 0x00, 0x0a, 0x0a, 0x0a, 0x00, 0x0b, 0x0b,
+  0x0b, 0x00, 0x0c, 0x0c, 0x0c, 0x00, 0x0d, 0x0d, 0x0d, 0x00, 0x0e, 0x0e,
+  0x0e, 0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x10, 0x10, 0x10, 0x00, 0x11, 0x11,
+  0x11, 0x00, 0x12, 0x12, 0x12, 0x00, 0x13, 0x13, 0x13, 0x00, 0x14, 0x14,
+  0x14, 0x00, 0x15, 0x15, 0x15, 0x00, 0x16, 0x16, 0x16, 0x00, 0x17, 0x17,
+  0x17, 0x00, 0x18, 0x18, 0x18, 0x00, 0x19, 0x19, 0x19, 0x00, 0x1a, 0x1a,
+  0x1a, 0x00, 0x1b, 0x1b, 0x1b, 0x00, 0x1c, 0x1c, 0x1c, 0x00, 0x1d, 0x1d,
+  0x1d, 0x00, 0x1e, 0x1e, 0x1e, 0x00, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x20,
+  0x20, 0x00, 0x21, 0x21, 0x21, 0x00, 0x22, 0x22, 0x22, 0x00, 0x23, 0x23,
+  0x23, 0x00, 0x24, 0x24, 0x24, 0x00, 0x25, 0x25, 0x25, 0x00, 0x26, 0x26,
+  0x26, 0x00, 0x27, 0x27, 0x27, 0x00, 0x28, 0x28, 0x28, 0x00, 0x29, 0x29,
+  0x29, 0x00, 0x2a, 0x2a, 0x2a, 0x00, 0x2b, 0x2b, 0x2b, 0x00, 0x2c, 0x2c,
+  0x2c, 0x00, 0x2d, 0x2d, 0x2d, 0x00, 0x2e, 0x2e, 0x2e, 0x00, 0x2f, 0x2f,
+  0x2f, 0x00, 0x30, 0x30, 0x30, 0x00, 0x31, 0x31, 0x31, 0x00, 0x32, 0x32,
+  0x32, 0x00, 0x33, 0x33, 0x33, 0x00, 0x34, 0x34, 0x34, 0x00, 0x35, 0x35,
+  0x35, 0x00, 0x36, 0x36, 0x36, 0x00, 0x37, 0x37, 0x37, 0x00, 0x38, 0x38,
+  0x38, 0x00, 0x39, 0x39, 0x39, 0x00, 0x3a, 0x3a, 0x3a, 0x00, 0x3b, 0x3b,
+  0x3b, 0x00, 0x3c, 0x3c, 0x3c, 0x00, 0x3d, 0x3d, 0x3d, 0x00, 0x3e, 0x3e,
+  0x3e, 0x00, 0x3f, 0x3f, 0x3f, 0x00, 0x40, 0x40, 0x40, 0x00, 0x41, 0x41,
+  0x41, 0x00, 0x42, 0x42, 0x42, 0x00, 0x43, 0x43, 0x43, 0x00, 0x44, 0x44,
+  0x44, 0x00, 0x45, 0x45, 0x45, 0x00, 0x46, 0x46, 0x46, 0x00, 0x47, 0x47,
+  0x47, 0x00, 0x48, 0x48, 0x48, 0x00, 0x49, 0x49, 0x49, 0x00, 0x4a, 0x4a,
+  0x4a, 0x00, 0x4b, 0x4b, 0x4b, 0x00, 0x4c, 0x4c, 0x4c, 0x00, 0x4d, 0x4d,
+  0x4d, 0x00, 0x4e, 0x4e, 0x4e, 0x00, 0x4f, 0x4f, 0x4f, 0x00, 0x50, 0x50,
+  0x50, 0x00, 0x51, 0x51, 0x51, 0x00, 0x52, 0x52, 0x52, 0x00, 0x53, 0x53,
+  0x53, 0x00, 0x54, 0x54, 0x54, 0x00, 0x55, 0x55, 0x55, 0x00, 0x56, 0x56,
+  0x56, 0x00, 0x57, 0x57, 0x57, 0x00, 0x58, 0x58, 0x58, 0x00, 0x59, 0x59,
+  0x59, 0x00, 0x5a, 0x5a, 0x5a, 0x00, 0x5b, 0x5b, 0x5b, 0x00, 0x5c, 0x5c,
+  0x5c, 0x00, 0x5d, 0x5d, 0x5d, 0x00, 0x5e, 0x5e, 0x5e, 0x00, 0x5f, 0x5f,
+  0x5f, 0x00, 0x60, 0x60, 0x60, 0x00, 0x61, 0x61, 0x61, 0x00, 0x62, 0x62,
+  0x62, 0x00, 0x63, 0x63, 0x63, 0x00, 0x64, 0x64, 0x64, 0x00, 0x65, 0x65,
+  0x65, 0x00, 0x66, 0x66, 0x66, 0x00, 0x67, 0x67, 0x67, 0x00, 0x68, 0x68,
+  0x68, 0x00, 0x69, 0x69, 0x69, 0x00, 0x6a, 0x6a, 0x6a, 0x00, 0x6b, 0x6b,
+  0x6b, 0x00, 0x6c, 0x6c, 0x6c, 0x00, 0x6d, 0x6d, 0x6d, 0x00, 0x6e, 0x6e,
+  0x6e, 0x00, 0x6f, 0x6f, 0x6f, 0x00, 0x70, 0x70, 0x70, 0x00, 0x71, 0x71,
+  0x71, 0x00, 0x72, 0x72, 0x72, 0x00, 0x73, 0x73, 0x73, 0x00, 0x74, 0x74,
+  0x74, 0x00, 0x75, 0x75, 0x75, 0x00, 0x76, 0x76, 0x76, 0x00, 0x77, 0x77,
+  0x77, 0x00, 0x78, 0x78, 0x78, 0x00, 0x79, 0x79, 0x79, 0x00, 0x7a, 0x7a,
+  0x7a, 0x00, 0x7b, 0x7b, 0x7b, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x7d, 0x7d,
+  0x7d, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x7f, 0x7f, 0x7f, 0x00, 0x80, 0x80,
+  0x80, 0x00, 0x81, 0x81, 0x81, 0x00, 0x82, 0x82, 0x82, 0x00, 0x83, 0x83,
+  0x83, 0x00, 0x84, 0x84, 0x84, 0x00, 0x85, 0x85, 0x85, 0x00, 0x86, 0x86,
+  0x86, 0x00, 0x87, 0x87, 0x87, 0x00, 0x88, 0x88, 0x88, 0x00, 0x89, 0x89,
+  0x89, 0x00, 0x8a, 0x8a, 0x8a, 0x00, 0x8b, 0x8b, 0x8b, 0x00, 0x8c, 0x8c,
+  0x8c, 0x00, 0x8d, 0x8d, 0x8d, 0x00, 0x8e, 0x8e, 0x8e, 0x00, 0x8f, 0x8f,
+  0x8f, 0x00, 0x90, 0x90, 0x90, 0x00, 0x91, 0x91, 0x91, 0x00, 0x92, 0x92,
+  0x92, 0x00, 0x93, 0x93, 0x93, 0x00, 0x94, 0x94, 0x94, 0x00, 0x95, 0x95,
+  0x95, 0x00, 0x96, 0x96, 0x96, 0x00, 0x97, 0x97, 0x97, 0x00, 0x98, 0x98,
+  0x98, 0x00, 0x99, 0x99, 0x99, 0x00, 0x9a, 0x9a, 0x9a, 0x00, 0x9b, 0x9b,
+  0x9b, 0x00, 0x9c, 0x9c, 0x9c, 0x00, 0x9d, 0x9d, 0x9d, 0x00, 0x9e, 0x9e,
+  0x9e, 0x00, 0x9f, 0x9f, 0x9f, 0x00, 0xa0, 0xa0, 0xa0, 0x00, 0xa1, 0xa1,
+  0xa1, 0x00, 0xa2, 0xa2, 0xa2, 0x00, 0xa3, 0xa3, 0xa3, 0x00, 0xa4, 0xa4,
+  0xa4, 0x00, 0xa5, 0xa5, 0xa5, 0x00, 0xa6, 0xa6, 0xa6, 0x00, 0xa7, 0xa7,
+  0xa7, 0x00, 0xa8, 0xa8, 0xa8, 0x00, 0xa9, 0xa9, 0xa9, 0x00, 0xaa, 0xaa,
+  0xaa, 0x00, 0xab, 0xab, 0xab, 0x00, 0xac, 0xac, 0xac, 0x00, 0xad, 0xad,
+  0xad, 0x00, 0xae, 0xae, 0xae, 0x00, 0xaf, 0xaf, 0xaf, 0x00, 0xb0, 0xb0,
+  0xb0, 0x00, 0xb1, 0xb1, 0xb1, 0x00, 0xb2, 0xb2, 0xb2, 0x00, 0xb3, 0xb3,
+  0xb3, 0x00, 0xb4, 0xb4, 0xb4, 0x00, 0xb5, 0xb5, 0xb5, 0x00, 0xb6, 0xb6,
+  0xb6, 0x00, 0xb7, 0xb7, 0xb7, 0x00, 0xb8, 0xb8, 0xb8, 0x00, 0xb9, 0xb9,
+  0xb9, 0x00, 0xba, 0xba, 0xba, 0x00, 0xbb, 0xbb, 0xbb, 0x00, 0xbc, 0xbc,
+  0xbc, 0x00, 0xbd, 0xbd, 0xbd, 0x00, 0xbe, 0xbe, 0xbe, 0x00, 0xbf, 0xbf,
+  0xbf, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0xc1, 0xc1, 0xc1, 0x00, 0xc2, 0xc2,
+  0xc2, 0x00, 0xc3, 0xc3, 0xc3, 0x00, 0xc4, 0xc4, 0xc4, 0x00, 0xc5, 0xc5,
+  0xc5, 0x00, 0xc6, 0xc6, 0xc6, 0x00, 0xc7, 0xc7, 0xc7, 0x00, 0xc8, 0xc8,
+  0xc8, 0x00, 0xc9, 0xc9, 0xc9, 0x00, 0xca, 0xca, 0xca, 0x00, 0xcb, 0xcb,
+  0xcb, 0x00, 0xcc, 0xcc, 0xcc, 0x00, 0xcd, 0xcd, 0xcd, 0x00, 0xce, 0xce,
+  0xce, 0x00, 0xcf, 0xcf, 0xcf, 0x00, 0xd0, 0xd0, 0xd0, 0x00, 0xd1, 0xd1,
+  0xd1, 0x00, 0xd2, 0xd2, 0xd2, 0x00, 0xd3, 0xd3, 0xd3, 0x00, 0xd4, 0xd4,
+  0xd4, 0x00, 0xd5, 0xd5, 0xd5, 0x00, 0xd6, 0xd6, 0xd6, 0x00, 0xd7, 0xd7,
+  0xd7, 0x00, 0xd8, 0xd8, 0xd8, 0x00, 0xd9, 0xd9, 0xd9, 0x00, 0xda, 0xda,
+  0xda, 0x00, 0xdb, 0xdb, 0xdb, 0x00, 0xdc, 0xdc, 0xdc, 0x00, 0xdd, 0xdd,
+  0xdd, 0x00, 0xde, 0xde, 0xde, 0x00, 0xdf, 0xdf, 0xdf, 0x00, 0xe0, 0xe0,
+  0xe0, 0x00, 0xe1, 0xe1, 0xe1, 0x00, 0xe2, 0xe2, 0xe2, 0x00, 0xe3, 0xe3,
+  0xe3, 0x00, 0xe4, 0xe4, 0xe4, 0x00, 0xe5, 0xe5, 0xe5, 0x00, 0xe6, 0xe6,
+  0xe6, 0x00, 0xe7, 0xe7, 0xe7, 0x00, 0xe8, 0xe8, 0xe8, 0x00, 0xe9, 0xe9,
+  0xe9, 0x00, 0xea, 0xea, 0xea, 0x00, 0xeb, 0xeb, 0xeb, 0x00, 0xec, 0xec,
+  0xec, 0x00, 0xed, 0xed, 0xed, 0x00, 0xee, 0xee, 0xee, 0x00, 0xef, 0xef,
+  0xef, 0x00, 0xf0, 0xf0, 0xf0, 0x00, 0xf1, 0xf1, 0xf1, 0x00, 0xf2, 0xf2,
+  0xf2, 0x00, 0xf3, 0xf3, 0xf3, 0x00, 0xf4, 0xf4, 0xf4, 0x00, 0xf5, 0xf5,
+  0xf5, 0x00, 0xf6, 0xf6, 0xf6, 0x00, 0xf7, 0xf7, 0xf7, 0x00, 0xf8, 0xf8,
+  0xf8, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0xfa, 0xfa, 0xfa, 0x00, 0xfb, 0xfb,
+  0xfb, 0x00, 0xfc, 0xfc, 0xfc, 0x00, 0xfd, 0xfd, 0xfd, 0x00, 0xfe, 0xfe,
+  0xfe, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x12, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
+  0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
+  0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00,
+  0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x2e, 0x2e,
+  0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x2e, 0x2e, 0x00, 0x00, 0x00, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+  0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x00,
+  0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x00,
+  0x00, 0x00, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x00, 0x00, 0x00, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x00, 0x00, 0x00, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x00,
+  0x00, 0x00, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+  0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x00, 0x00, 0x00, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x00,
+  0x00, 0x00, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+  0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x9b, 0x9b,
+  0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x9b, 0x9b, 0x00, 0x00, 0x00, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0x00,
+  0x00, 0x00, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0x00, 0x00, 0x00, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0x00, 0x00, 0x00, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0x00,
+  0x00, 0x00, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0xd1, 0xd1,
+  0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+  0xd1, 0xd1, 0xd1, 0x00, 0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00,
+  0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+  0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0x00, 0x00, 0x00, 0xed, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+  0xed, 0xed, 0xed, 0x00, 0x00, 0x00, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+  0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00
+};
+unsigned int test_bmp_len = 1726;

+ 24 - 0
tests/include/igl/stb/test_jpg.h

@@ -0,0 +1,24 @@
+unsigned char test_jpg[] = {
+  0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
+  0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
+  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+  0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x1d,
+  0x00, 0x11, 0x01, 0x01, 0x11, 0x00, 0xff, 0xc4, 0x00, 0x15, 0x00, 0x01,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0xff, 0xc4, 0x00, 0x20, 0x10, 0x00, 0x01,
+  0x03, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x18, 0xd2, 0x55, 0x93, 0xa3, 0x02, 0x06, 0x17,
+  0x52, 0x65, 0xe1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f,
+  0x00, 0xaf, 0x97, 0x4e, 0x2a, 0x26, 0xe8, 0x92, 0x3a, 0x71, 0x51, 0x37,
+  0x44, 0x91, 0xd3, 0x8a, 0x89, 0xba, 0x24, 0xa6, 0xe5, 0xd2, 0x8a, 0x90,
+  0xbc, 0x24, 0x8e, 0x94, 0x54, 0x85, 0xe1, 0x24, 0x74, 0xa2, 0xa4, 0x2f,
+  0x09, 0x29, 0xb8, 0x74, 0x9e, 0x8e, 0x5f, 0xa8, 0xe9, 0x3d, 0x1c, 0xbf,
+  0x51, 0xd2, 0x7a, 0x39, 0x7e, 0xa9, 0xed, 0xe6, 0x2d, 0xd1, 0xdf, 0x36,
+  0xb8, 0x27, 0x31, 0x6e, 0x8e, 0xf9, 0xb5, 0xc1, 0x39, 0x8b, 0x74, 0x77,
+  0xcd, 0xae, 0x0b, 0xff, 0xd9
+};
+unsigned int test_jpg_len = 245;

+ 46 - 0
tests/include/igl/stb/test_pgm.h

@@ -0,0 +1,46 @@
+unsigned char test_pgm[] = {
+  0x50, 0x35, 0x0a, 0x31, 0x37, 0x20, 0x32, 0x39, 0x0a, 0x32, 0x35, 0x35,
+  0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+  0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+  0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+  0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+  0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+  0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+  0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
+  0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+unsigned int test_pgm_len = 506;

+ 27 - 0
tests/include/igl/stb/test_png.h

@@ -0,0 +1,27 @@
+unsigned char test_png[] = {
+  0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
+  0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1d,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x69, 0xc4, 0xd8, 0x5d, 0x00, 0x00, 0x00,
+  0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61,
+  0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a,
+  0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80,
+  0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a,
+  0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00,
+  0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00,
+  0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe5, 0x01, 0x05, 0x10,
+  0x01, 0x1a, 0x78, 0xbc, 0x92, 0x58, 0x00, 0x00, 0x00, 0x21, 0x49, 0x44,
+  0x41, 0x54, 0x28, 0xcf, 0x63, 0xfc, 0xcf, 0x80, 0x06, 0x58, 0xbe, 0x53,
+  0x49, 0xe4, 0x1b, 0xcd, 0x4c, 0xa6, 0x9d, 0xc8, 0xe0, 0x77, 0x33, 0x59,
+  0x2e, 0x64, 0xe4, 0x64, 0x20, 0x08, 0x00, 0xba, 0x56, 0x1a, 0x86, 0xef,
+  0x69, 0x45, 0x49, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64,
+  0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32,
+  0x30, 0x32, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x35, 0x54, 0x31, 0x36,
+  0x3a, 0x30, 0x31, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30,
+  0x45, 0xd2, 0x38, 0xae, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74,
+  0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00,
+  0x32, 0x30, 0x32, 0x31, 0x2d, 0x30, 0x31, 0x2d, 0x30, 0x35, 0x54, 0x31,
+  0x36, 0x3a, 0x30, 0x31, 0x3a, 0x32, 0x36, 0x2b, 0x30, 0x30, 0x3a, 0x30,
+  0x30, 0x34, 0x8f, 0x80, 0x12, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
+  0x44, 0xae, 0x42, 0x60, 0x82
+};
+unsigned int test_png_len = 281;

+ 46 - 0
tests/include/igl/stb/test_reference.h

@@ -0,0 +1,46 @@
+    static const unsigned char  
+      ref_image_raw[] = {
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+  0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+  0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+  0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+  0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+  0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+  0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
+  0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+      };
+

+ 46 - 0
tests/include/igl/stb/test_tga.h

@@ -0,0 +1,46 @@
+unsigned char test_tga[] = {
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x11, 0x00, 0x1d, 0x00, 0x08, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6,
+  0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+  0xf6, 0xf6, 0xf6, 0xf6, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+  0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xe4, 0xe4, 0xe4,
+  0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+  0xe4, 0xe4, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+  0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+  0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+  0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8,
+  0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+  0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
+  0xb6, 0xb6, 0xb6, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+  0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+  0xa4, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+  0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
+  0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
+  0x89, 0x89, 0x89, 0x89, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x76, 0x76, 0x76,
+  0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+  0x76, 0x76, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+  0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
+  0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
+  0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x37, 0x37, 0x37, 0x37,
+  0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
+  0x37, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
+  0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x1b,
+  0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
+  0x1b, 0x1b, 0x1b, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
+  0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x09, 0x09, 0x09,
+  0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+  0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned int test_tga_len = 511;

+ 2 - 2
tutorial/111_MatCap/main.cpp

@@ -1,6 +1,6 @@
 #include <igl/opengl/glfw/Viewer.h>
 #include <igl/opengl/glfw/Viewer.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/png/readPNG.h>
+#include <igl/stb/read_image.h>
 
 
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
   igl::read_triangle_mesh(
   igl::read_triangle_mesh(
     argc>1?argv[1]: TUTORIAL_SHARED_PATH "/armadillo.obj",V,F);
     argc>1?argv[1]: TUTORIAL_SHARED_PATH "/armadillo.obj",V,F);
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
-  igl::png::readPNG(argc>2?argv[2]: TUTORIAL_SHARED_PATH "/jade.png",R,G,B,A);
+  igl::stb::read_image(argc>2?argv[2]: TUTORIAL_SHARED_PATH "/jade.png",R,G,B,A);
   v.data().set_mesh(V,F);
   v.data().set_mesh(V,F);
   v.data().set_texture(R,G,B,A);
   v.data().set_texture(R,G,B,A);
   v.data().use_matcap = true;
   v.data().use_matcap = true;

+ 2 - 2
tutorial/113_Shadows/main.cpp

@@ -1,7 +1,7 @@
 #include <igl/opengl/glfw/Viewer.h>
 #include <igl/opengl/glfw/Viewer.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/triangulated_grid.h>
 #include <igl/triangulated_grid.h>
-#include <igl/png/readPNG.h>
+#include <igl/stb/read_image.h>
 #include <igl/get_seconds.h>
 #include <igl/get_seconds.h>
 #include <igl/PI.h>
 #include <igl/PI.h>
 #include <Eigen/Core>
 #include <Eigen/Core>
@@ -98,7 +98,7 @@ int main(int argc, char *argv[])
   if(argc>2)
   if(argc>2)
   {
   {
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
-    igl::png::readPNG(argv[2],R,G,B,A);
+    igl::stb::read_image(argv[2],R,G,B,A);
     // If more args, read them as light direction
     // If more args, read them as light direction
     if(argc>2+3)
     if(argc>2+3)
     {
     {

+ 4 - 4
tutorial/607_ScreenCapture/main.cpp

@@ -1,8 +1,8 @@
 #include <igl/readOFF.h>
 #include <igl/readOFF.h>
 #include <igl/opengl/glfw/Viewer.h>
 #include <igl/opengl/glfw/Viewer.h>
 #include <iostream>
 #include <iostream>
-#include <igl/png/writePNG.h>
-#include <igl/png/readPNG.h>
+#include <igl/stb/write_image.h>
+#include <igl/stb/read_image.h>
 
 
 // This function is called every time a keyboard button is pressed
 // This function is called every time a keyboard button is pressed
 bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
 bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier)
@@ -20,7 +20,7 @@ bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier
       viewer.data(),false,R,G,B,A);
       viewer.data(),false,R,G,B,A);
 
 
     // Save it to a PNG
     // Save it to a PNG
-    igl::png::writePNG(R,G,B,A,"out.png");
+    igl::stb::write_image("out.png",R,G,B,A);
   }
   }
 
 
   if (key == '2')
   if (key == '2')
@@ -29,7 +29,7 @@ bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
     Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
 
 
     // Read the PNG
     // Read the PNG
-    igl::png::readPNG("out.png",R,G,B,A);
+    igl::stb::read_image("out.png",R,G,B,A);
 
 
     // Replace the mesh with a triangulated square
     // Replace the mesh with a triangulated square
     Eigen::MatrixXd V(4,3);
     Eigen::MatrixXd V(4,3);

+ 2 - 2
tutorial/608_RayTrace/main.cpp

@@ -2,7 +2,7 @@
 #include <igl/massmatrix.h>
 #include <igl/massmatrix.h>
 #include <igl/invert_diag.h>
 #include <igl/invert_diag.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/png/writePNG.h>
+#include <igl/stb/write_image.h>
 #include <igl/PI.h>
 #include <igl/PI.h>
 #include <Eigen/Geometry>
 #include <Eigen/Geometry>
 // embree
 // embree
@@ -63,6 +63,6 @@ int main(int argc, char *argv[])
   std::cout<<"Rendered scene saved to "<<png_file<<std::endl;
   std::cout<<"Rendered scene saved to "<<png_file<<std::endl;
 
 
   // save to PNG file
   // save to PNG file
-  igl::png::writePNG(R,G,B,A,png_file);
+  igl::stb::write_image(png_file,R,G,B,A);
   return 0;
   return 0;
 }
 }

+ 4 - 4
tutorial/CMakeLists.txt

@@ -26,9 +26,9 @@ if(LIBIGL_TUTORIALS_CHAPTER1)
     igl_add_tutorial(108_MultipleViews igl::glfw)
     igl_add_tutorial(108_MultipleViews igl::glfw)
     igl_add_tutorial(109_ImGuizmo igl::imgui)
     igl_add_tutorial(109_ImGuizmo igl::imgui)
     igl_add_tutorial(110_MshView igl::glfw)
     igl_add_tutorial(110_MshView igl::glfw)
-    igl_add_tutorial(111_MatCap igl::glfw igl::png)
+    igl_add_tutorial(111_MatCap igl::glfw igl::stb)
     igl_add_tutorial(112_Selection igl::imgui)
     igl_add_tutorial(112_Selection igl::imgui)
-    igl_add_tutorial(113_Shadows igl::imgui igl::png)
+    igl_add_tutorial(113_Shadows igl::imgui igl::stb)
 endif()
 endif()
 
 
 # Chapter 2
 # Chapter 2
@@ -83,8 +83,8 @@ if(LIBIGL_TUTORIALS_CHAPTER6)
     igl_add_tutorial(604_Triangle igl::glfw igl_restricted::triangle)
     igl_add_tutorial(604_Triangle igl::glfw igl_restricted::triangle)
     igl_add_tutorial(605_Tetgen igl::glfw igl_copyleft::tetgen)
     igl_add_tutorial(605_Tetgen igl::glfw igl_copyleft::tetgen)
     igl_add_tutorial(606_AmbientOcclusion igl::glfw igl::embree)
     igl_add_tutorial(606_AmbientOcclusion igl::glfw igl::embree)
-    igl_add_tutorial(607_ScreenCapture igl::glfw igl::png)
-    igl_add_tutorial(608_RayTrace igl::png igl::embree)
+    igl_add_tutorial(607_ScreenCapture igl::glfw igl::stb)
+    igl_add_tutorial(608_RayTrace igl::stb igl::embree)
     igl_add_tutorial(609_Boolean igl::glfw igl_copyleft::cgal)
     igl_add_tutorial(609_Boolean igl::glfw igl_copyleft::cgal)
     igl_copy_dll(609_Boolean)
     igl_copy_dll(609_Boolean)
     igl_add_tutorial(610_CSGTree igl::glfw igl_copyleft::cgal)
     igl_add_tutorial(610_CSGTree igl::glfw igl_copyleft::cgal)