Browse Source

Added PNG module and tutorial 607

Former-commit-id: c0e04685e2e9288dc093665a24c8822dd6bfd8b2
Sebastian Koch 9 years ago
parent
commit
b275c3672a

+ 5 - 0
python/CMakeLists.txt

@@ -112,6 +112,11 @@ if (LIBIGL_WITH_CGAL)
   list(APPEND SHARED_SOURCES "modules/copyleft/py_igl_cgal.cpp")
 endif ()
 
+if (LIBIGL_WITH_PNG)
+  add_definitions(-DPY_PNG)
+  list(APPEND SHARED_SOURCES "modules/py_igl_png.cpp")
+endif ()
+
 
 ## Prepare the python library
 add_library(pyigl SHARED

+ 16 - 0
python/modules/py_igl_png.cpp

@@ -0,0 +1,16 @@
+
+#include "../python_shared.h"
+
+#include <igl/png/readPNG.h>
+#include <igl/png/writePNG.h>
+
+
+void python_export_igl_png(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "png", "Wrappers for libigl functions that use png");
+
+  #include "../py_igl/png/py_readPNG.cpp"
+  #include "../py_igl/png/py_writePNG.cpp"
+
+}

+ 12 - 0
python/modules/py_igl_viewer.cpp

@@ -6,6 +6,7 @@
 #include <igl/viewer/Viewer.h>
 #include <igl/viewer/ViewerCore.h>
 #include <igl/viewer/ViewerData.h>
+#include <igl/viewer/OpenGL_state.h>
 #include <igl/serialize.h>
 
 void python_export_igl_viewer(py::module &m)
@@ -118,6 +119,16 @@ py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
 
     ;
 
+//////////////////////// OPENGL_State
+
+py::class_<igl::viewer::OpenGL_state> opengl_state_class(me, "OpenGL_state");
+
+    opengl_state_class
+    .def(py::init<>())
+    .def("init", &igl::viewer::OpenGL_state::init)
+
+    ;
+
 //////////////////////// CORE
 
 py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
@@ -311,6 +322,7 @@ py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
     .def(py::init<>())
     .def_readwrite("data", &igl::viewer::Viewer::data)
     .def_readwrite("core", &igl::viewer::Viewer::core)
+    .def_readwrite("opengl", &igl::viewer::Viewer::opengl)
     .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true)

+ 16 - 0
python/py_doc.cpp

@@ -620,6 +620,22 @@ const char *__doc_igl_planarize_quad_mesh = R"igl_Qu8mg5v7(// Inputs:
   // Output:
   //   Vout       #V by 3 eigen Matrix of planar mesh vertex 3D positions
   //)igl_Qu8mg5v7";
+const char *__doc_igl_png_readPNG = R"igl_Qu8mg5v7(// Read an image from a .png file into 4 memory buffers
+    //
+    // Input:
+    //  png_file  path to .png file
+    // Output:
+    //  R,G,B,A texture channels
+    // Returns true on success, false on failure
+    //)igl_Qu8mg5v7";
+const char *__doc_igl_png_writePNG = R"igl_Qu8mg5v7(// Writes an image to a png file
+    //
+    // Input:
+    //  R,G,B,A texture channels
+    // Output:
+    //  png_file  path to .png file
+    // Returns true on success, false on failure
+    //)igl_Qu8mg5v7";
 const char *__doc_igl_point_mesh_squared_distance = R"igl_Qu8mg5v7(// Compute distances from a set of points P to a triangle mesh (V,F)
   //
   // Inputs:

+ 2 - 0
python/py_doc.h

@@ -50,6 +50,8 @@ extern const char *__doc_igl_per_face_normals;
 extern const char *__doc_igl_per_face_normals_stable;
 extern const char *__doc_igl_per_vertex_normals;
 extern const char *__doc_igl_planarize_quad_mesh;
+extern const char *__doc_igl_png_readPNG;
+extern const char *__doc_igl_png_writePNG;
 extern const char *__doc_igl_point_mesh_squared_distance;
 extern const char *__doc_igl_polar_svd;
 extern const char *__doc_igl_principal_curvature;

+ 14 - 0
python/py_igl/png/py_readPNG.cpp

@@ -0,0 +1,14 @@
+
+m.def("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
+)
+{
+  return igl::png::readPNG(png_file, R, G, B, A);
+}, __doc_igl_png_readPNG,
+py::arg("png_file"), py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A"));
+

+ 15 - 0
python/py_igl/png/py_writePNG.cpp

@@ -0,0 +1,15 @@
+
+
+m.def("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
+)
+{
+  return igl::png::writePNG(R, G, B, A, png_file);
+}, __doc_igl_png_writePNG,
+py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A"), py::arg("png_file"));
+

+ 10 - 0
python/python_shared.cpp

@@ -30,6 +30,10 @@ extern void python_export_igl_triangle(py::module &);
 extern void python_export_igl_cgal(py::module &);
 #endif
 
+#ifdef PY_PNG
+extern void python_export_igl_png(py::module &);
+#endif
+
 PYBIND11_PLUGIN(pyigl) {
     py::module m("pyigl", R"pyigldoc(
         Python wrappers for libigl
@@ -88,6 +92,8 @@ PYBIND11_PLUGIN(pyigl) {
            per_face_normals
            per_vertex_normals
            planarize_quad_mesh
+           png_readPNG
+           png_writePNG
            point_mesh_squared_distance
            polar_svd
            principal_curvature
@@ -142,5 +148,9 @@ PYBIND11_PLUGIN(pyigl) {
     python_export_igl_cgal(m);
     #endif
 
+    #ifdef PY_PNG
+    python_export_igl_png(m);
+    #endif
+
     return m.ptr();
 }

+ 4 - 1
python/scripts/generate_bindings.py

@@ -63,6 +63,9 @@ def map_parameter_types(name, cpp_type, parsed_types, errors, enum_types):
     if cpp_type.startswith("MatY"):
         result.append("Eigen::SparseMatrix<double>&")
         skip_parsing = True
+    if cpp_type.startswith("Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>"):
+        result.append("Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>")
+        skip_parsing = True
     if cpp_type == "std::vector<std::vector<Scalar> > &":
         result.append("std::vector<std::vector<double> > &")
         skip_parsing = True
@@ -298,4 +301,4 @@ if __name__ == '__main__':
         for k in l:
             fs.write("%s: %i \n" %(k, len(files[k])))
             fs.writelines("\n".join(files[k]))
-            fs.write("\n\n\n")
+            fs.write("\n\n\n")

+ 8 - 0
python/scripts/python_shared.mako

@@ -30,6 +30,10 @@ extern void python_export_igl_triangle(py::module &);
 extern void python_export_igl_cgal(py::module &);
 #endif
 
+#ifdef PY_PNG
+extern void python_export_igl_png(py::module &);
+#endif
+
 PYBIND11_PLUGIN(pyigl) {
     py::module m("pyigl", R"pyigldoc(
         Python wrappers for libigl
@@ -74,5 +78,9 @@ PYBIND11_PLUGIN(pyigl) {
     python_export_igl_cgal(m);
     #endif
 
+    #ifdef PY_PNG
+    python_export_igl_png(m);
+    #endif
+
     return m.ptr();
 }

+ 77 - 0
python/tutorial/607_ScreenCapture.py

@@ -0,0 +1,77 @@
+import sys, os
+
+# Add the igl library to the modules search path
+sys.path.insert(0, os.getcwd() + "/../")
+import pyigl as igl
+
+from shared import TUTORIAL_SHARED_PATH, check_dependencies
+
+dependencies = ["png", "viewer"]
+check_dependencies(dependencies)
+
+
+def key_down(viewer, key, modifier):
+    if key == ord('1'):
+        # Allocate temporary buffers
+        R = igl.eigen.MatrixXuc(1280, 800)
+        G = igl.eigen.MatrixXuc(1280, 800)
+        B = igl.eigen.MatrixXuc(1280, 800)
+        A = igl.eigen.MatrixXuc(1280, 800)
+
+        # Draw the scene in the buffers
+        viewer.core.draw_buffer(viewer.data, viewer.opengl, False, R, G, B, A)
+
+        # Save it to a PNG
+        igl.png.writePNG(R, G, B, A, "out.png")
+    elif key == ord('2'):
+        # Allocate temporary buffers
+        R = igl.eigen.MatrixXuc()
+        G = igl.eigen.MatrixXuc()
+        B = igl.eigen.MatrixXuc()
+        A = igl.eigen.MatrixXuc()
+
+        # Read the PNG
+        igl.png.readPNG("out.png", R, G, B, A)
+
+        # Replace the mesh with a triangulated square
+        V = igl.eigen.MatrixXd([[-0.5, -0.5, 0],
+                                [0.5, -0.5, 0],
+                                [0.5, 0.5, 0],
+                                [-0.5, 0.5, 0]])
+
+        F = igl.eigen.MatrixXi([[0, 1, 2], [2, 3, 0]])
+
+        UV = igl.eigen.MatrixXd([[0, 0], [1, 0], [1, 1], [0, 1]])
+
+        viewer.data.clear()
+        viewer.data.set_mesh(V, F)
+        viewer.data.set_uv(UV)
+        viewer.core.align_camera_center(V)
+        viewer.core.show_texture = True
+
+        # Use the image as a texture
+        viewer.data.set_texture(R, G, B)
+
+    else:
+        return False
+
+    return True
+
+
+if __name__ == "__main__":
+    V = igl.eigen.MatrixXd()
+    F = igl.eigen.MatrixXi()
+
+    # Load meshes in OFF format
+    igl.readOFF(TUTORIAL_SHARED_PATH + "bunny.off", V, F)
+
+    viewer = igl.viewer.Viewer()
+
+    print(
+        "Usage: Press 1 to render the scene and save it in a png. \nPress 2 to load the saved png and use it as a texture.")
+
+    viewer.callback_key_down = key_down
+    viewer.data.set_mesh(V, F)
+    viewer.launch()
+
+    os.remove("out.png")