comparison OrthancStone/Sources/Scene2D/Internals/OpenGLFloatTextureProgram.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Scene2D/Internals/OpenGLFloatTextureProgram.cpp@30deba7bc8e2
children 85e117739eca
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "OpenGLFloatTextureProgram.h"
23 #include "OpenGLShaderVersionDirective.h"
24
25 #include <OrthancException.h>
26 #include <Images/Image.h>
27 #include <Images/ImageProcessing.h>
28
29
30 static const char* FRAGMENT_SHADER =
31 ORTHANC_STONE_OPENGL_SHADER_VERSION_DIRECTIVE
32 "uniform float u_offset; \n"
33 "uniform float u_slope; \n"
34 "uniform float u_windowCenter; \n"
35 "uniform float u_windowWidth; \n"
36 "uniform bool u_invert; \n"
37 "uniform sampler2D u_texture; \n"
38 "varying vec2 v_texcoord; \n"
39 "void main() \n"
40 "{ \n"
41 " vec4 t = texture2D(u_texture, v_texcoord); \n"
42 " float v = (t.r * 256.0 + t.g) * 256.0; \n"
43 " v = v * u_slope + u_offset; \n" // (*)
44 " float a = u_windowCenter - u_windowWidth / 2.0; \n"
45 " float dy = 1.0 / u_windowWidth; \n"
46 " if (v <= a) \n"
47 " v = 0.0; \n"
48 " else \n"
49 " { \n"
50 " v = (v - a) * dy; \n"
51 " if (v >= 1.0) \n"
52 " v = 1.0; \n"
53 " } \n"
54 " if (u_invert) \n"
55 " v = 1.0 - v; \n"
56 " gl_FragColor = vec4(v, v, v, 1); \n"
57 "}";
58
59
60 namespace OrthancStone
61 {
62 namespace Internals
63 {
64 OpenGLFloatTextureProgram::Data::Data(
65 OpenGL::IOpenGLContext& context
66 , const Orthanc::ImageAccessor& texture
67 , bool isLinearInterpolation)
68 : texture_(context)
69 , offset_(0.0f)
70 , slope_(0.0f)
71 {
72 if (texture.GetFormat() != Orthanc::PixelFormat_Float32)
73 {
74 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
75 }
76
77 float minValue, maxValue;
78 Orthanc::ImageProcessing::GetMinMaxFloatValue(minValue, maxValue, texture);
79
80 offset_ = minValue;
81
82 if (LinearAlgebra::IsCloseToZero(maxValue - minValue))
83 {
84 slope_ = 1;
85 }
86 else
87 {
88 slope_ = (maxValue - minValue) / 65536.0f;
89 assert(!LinearAlgebra::IsCloseToZero(slope_));
90 }
91
92 const unsigned int width = texture.GetWidth();
93 const unsigned int height = texture.GetHeight();
94
95 Orthanc::Image converted(Orthanc::PixelFormat_RGB24, width, height, true);
96
97 for (unsigned int y = 0; y < height; y++)
98 {
99 const float *p = reinterpret_cast<const float*>(texture.GetConstRow(y));
100 uint8_t *q = reinterpret_cast<uint8_t*>(converted.GetRow(y));
101
102 for (unsigned int x = 0; x < width; x++)
103 {
104 /**
105 * At (*), the floating-point "value" is reconstructed as
106 * "value = texture * slope + offset".
107 * <=> texture = (value - offset) / slope
108 **/
109
110 float texture = (*p - offset_) / slope_;
111 if (texture < 0)
112 {
113 texture = 0;
114 }
115 else if (texture >= 65535.0f)
116 {
117 texture = 65535.0f;
118 }
119
120 uint16_t t = static_cast<uint16_t>(texture);
121
122 q[0] = t / 256; // red
123 q[1] = t % 256; // green
124 q[2] = 0; // blue is unused
125
126 p++;
127 q += 3;
128 }
129 }
130
131 texture_.Load(converted, isLinearInterpolation);
132 }
133
134
135 OpenGLFloatTextureProgram::OpenGLFloatTextureProgram(OpenGL::IOpenGLContext& context)
136 : program_(context, FRAGMENT_SHADER)
137 , context_(context)
138 {
139 }
140
141
142 void OpenGLFloatTextureProgram::Apply(Data& data,
143 const AffineTransform2D& transform,
144 float windowCenter,
145 float windowWidth,
146 bool invert)
147 {
148 if (!context_.IsContextLost())
149 {
150 OpenGLTextureProgram::Execution execution(program_, data.GetTexture(), transform);
151
152 glUniform1f(execution.GetUniformLocation("u_slope"), data.GetSlope());
153 glUniform1f(execution.GetUniformLocation("u_offset"), data.GetOffset());
154 glUniform1f(execution.GetUniformLocation("u_windowCenter"), windowCenter);
155 glUniform1f(execution.GetUniformLocation("u_windowWidth"), windowWidth);
156 glUniform1f(execution.GetUniformLocation("u_invert"), invert);
157
158 execution.DrawTriangles();
159 }
160 }
161 }
162 }