changeset 2061:6ea5f40ea0e9 deep-learning

added ImageProcessingProgram
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 03 May 2023 16:34:34 +0200
parents 86e0e92a2e0d
children f5db73779f2d
files OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake OrthancStone/Sources/OpenGL/ImageProcessingProgram.cpp OrthancStone/Sources/OpenGL/ImageProcessingProgram.h OrthancStone/Sources/OpenGL/OpenGLTexture.cpp
diffstat 4 files changed, 261 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake	Wed May 03 16:15:50 2023 +0200
+++ b/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake	Wed May 03 16:34:34 2023 +0200
@@ -505,6 +505,8 @@
     ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLTextureArray.cpp
     ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLFramebuffer.h
     ${ORTHANC_STONE_ROOT}/OpenGL/OpenGLFramebuffer.cpp
+    ${ORTHANC_STONE_ROOT}/OpenGL/ImageProcessingProgram.h
+    ${ORTHANC_STONE_ROOT}/OpenGL/ImageProcessingProgram.cpp
     ${ORTHANC_STONE_ROOT}/Scene2D/OpenGLCompositor.h
     ${ORTHANC_STONE_ROOT}/Scene2D/OpenGLCompositor.cpp
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancStone/Sources/OpenGL/ImageProcessingProgram.cpp	Wed May 03 16:34:34 2023 +0200
@@ -0,0 +1,174 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2022 Osimis S.A., Belgium
+ * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "ImageProcessingProgram.h"
+
+#include "OpenGLFramebuffer.h"
+
+#include <OrthancException.h>
+
+
+static const unsigned int DIMENSIONS = 2;  // Number of dimensions (we draw in 2D)
+static const unsigned int VERTICES = 6;  // 2 triangles in 2D (each triangle has 3 vertices)
+
+
+static const float TRIANGLES[DIMENSIONS * VERTICES] = {
+  // First triangle
+  -1.0f, -1.0f,
+  1.0f,  -1.0f,
+  -1.0f,  1.0f,
+  // Second triangle
+  -1.0f,  1.0f,
+  1.0f,  -1.0f,
+  1.0f,   1.0f
+};
+
+
+/**
+ * "varying" indicates variables that are shader by the vertex shader
+ * and the fragment shader. The reason for "v_position" is that
+ * "a_position" (position in the target frame buffer) ranges from -1
+ * to 1, whereas texture samplers range from 0 to 1.
+ **/
+static const char* VERTEX_SHADER =
+  "in vec2 a_position;                        \n"
+  "out vec2 v_position;                       \n"
+  "void main() {                              \n"
+  "  v_position = (a_position + 1.0) / 2.0;   \n"
+  "  gl_Position = vec4(a_position, 0, 1.0);  \n"
+  "}                                          \n";
+
+
+namespace OrthancStone
+{
+  namespace OpenGL
+  {
+    void ImageProcessingProgram::SetupPosition()
+    {
+      glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
+      glBufferData(GL_ARRAY_BUFFER, sizeof(float) * DIMENSIONS * VERTICES, TRIANGLES, GL_STATIC_DRAW);
+      GLint positionLocation = program_.GetAttributeLocation("a_position");
+      glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
+      glEnableVertexAttribArray(positionLocation);
+    }
+
+
+    ImageProcessingProgram::ImageProcessingProgram(IOpenGLContext& context,
+                                                   const std::string& fragmentShader) :
+      program_(context),
+      quad_vertexbuffer(0)
+    {
+      if (context.IsContextLost())
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                        "OpenGL context has been lost");
+      }
+
+      context.MakeCurrent();
+
+      std::string version;
+
+#if ORTHANC_ENABLE_WASM == 1
+      /**
+       * "#version 300 es" corresponds to:
+       * - OpenGL ES version 3.0: https://registry.khronos.org/OpenGL-Refpages/es3.0/
+       * - WebGL version 2.0
+       * - GLSL ES version 3.00.6
+       * - Based on version GLSL version 3.0
+       *
+       * Explanation for "highp":
+       * https://emscripetn.org/docs/optimizing/Optimizing-WebGL.html
+       * https://webglfundamentals.org/webgl/lessons/webgl-qna-when-to-choose-highp--mediump--lowp-in-shaders.html
+       **/
+      version = ("#version 300 es\n"
+                 "precision highp float;\n"
+                 "precision highp sampler2D;\n"
+                 "precision highp sampler2DArray;\n");
+#else
+      /**
+       * "#version 130" corresponds to:
+       * - OpenGL version 3.0
+       * - GLSL version 1.30.10
+       **/
+      version = "#version 130\n";
+#endif
+
+      program_.CompileShaders(version + VERTEX_SHADER, version + fragmentShader);
+
+      glGenBuffers(1, &quad_vertexbuffer);
+      if (quad_vertexbuffer == 0)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                        "Cannot create OpenGL buffer");
+      }
+    }
+
+
+    ImageProcessingProgram::~ImageProcessingProgram()
+    {
+      glDeleteBuffers(1, &quad_vertexbuffer);
+    }
+
+
+    void ImageProcessingProgram::Use(OpenGLTexture& target,
+                                     OpenGLFramebuffer& framebuffer,
+                                     bool checkStatus)
+    {
+      program_.Use(checkStatus);
+      framebuffer.SetTarget(target);
+      SetupPosition();
+    }
+
+
+    void ImageProcessingProgram::Use(OpenGLTextureArray& target,
+                                     unsigned int targetLayer,
+                                     OpenGLFramebuffer& framebuffer,
+                                     bool checkStatus)
+    {
+      program_.Use(checkStatus);
+      framebuffer.SetTarget(target, targetLayer);
+      SetupPosition();
+    }
+
+
+    void ImageProcessingProgram::Render()
+    {
+      glClearColor(0.0, 0.0, 0.0, 1.0);
+      glClear(GL_COLOR_BUFFER_BIT);
+
+#if 1
+      glDrawArrays(GL_TRIANGLES, 0, VERTICES);
+#else
+      // Simpler, but not available in WebGL
+      glBegin(GL_QUADS);
+      glVertex2f(-1,  1); // vertex 1
+      glVertex2f(-1, -1); // vertex 2
+      glVertex2f( 1, -1); // vertex 3
+      glVertex2f( 1,  1); // vertex 4
+      glEnd();
+#endif
+
+      ORTHANC_OPENGL_CHECK("glDrawArrays()");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancStone/Sources/OpenGL/ImageProcessingProgram.h	Wed May 03 16:34:34 2023 +0200
@@ -0,0 +1,73 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2022 Osimis S.A., Belgium
+ * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "OpenGLProgram.h"
+
+
+namespace OrthancStone
+{
+  namespace OpenGL
+  {
+    class OpenGLFramebuffer;
+    class OpenGLTexture;
+    class OpenGLTextureArray;
+
+    class ImageProcessingProgram : public boost::noncopyable
+    {
+    private:
+      OpenGLProgram  program_;
+      GLuint         quad_vertexbuffer;
+
+      void SetupPosition();
+
+    public:
+      ImageProcessingProgram(IOpenGLContext& context,
+                             const std::string& fragmentShader);
+
+      ~ImageProcessingProgram();
+
+      void Use(OpenGLTexture& target,
+               OpenGLFramebuffer& framebuffer,
+               bool checkStatus);
+
+      void Use(OpenGLTextureArray& target,
+               unsigned int targetLayer,
+               OpenGLFramebuffer& framebuffer,
+               bool checkStatus);
+
+      void Render();
+
+      GLint GetUniformLocation(const std::string& name)
+      {
+        return program_.GetUniformLocation(name);
+      }
+
+      GLint GetAttributeLocation(const std::string& name)
+      {
+        return program_.GetAttributeLocation(name);
+      }
+    };
+  }
+}
--- a/OrthancStone/Sources/OpenGL/OpenGLTexture.cpp	Wed May 03 16:15:50 2023 +0200
+++ b/OrthancStone/Sources/OpenGL/OpenGLTexture.cpp	Wed May 03 16:34:34 2023 +0200
@@ -45,17 +45,20 @@
       format_(Orthanc::PixelFormat_Grayscale8),
       isLinearInterpolation_(false)
     {
-      if (!context_.IsContextLost())
+      if (context.IsContextLost())
       {
-        // Generate a texture object
-        glGenTextures(1, &texture_);
-        ORTHANC_OPENGL_CHECK("glGenTextures()");
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                        "OpenGL context has been lost");
+      }
 
-        if (texture_ == 0)
-        {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
-            "Cannot create an OpenGL texture");
-        }
+      // Generate a texture object
+      glGenTextures(1, &texture_);
+      ORTHANC_OPENGL_CHECK("glGenTextures()");
+
+      if (texture_ == 0)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
+                                        "Cannot create an OpenGL texture");
       }
     }