Mercurial > hg > orthanc-stone
changeset 768:55411e7da2f7
LookupTableTextureSceneLayer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 23 May 2019 20:04:33 +0200 |
parents | dce5b067d040 |
children | 4ba8892870a2 |
files | Framework/Scene2D/CairoCompositor.cpp Framework/Scene2D/ColorTextureSceneLayer.h Framework/Scene2D/ISceneLayer.h Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp Framework/Scene2D/Internals/CairoColorTextureRenderer.h Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp Framework/Scene2D/Internals/CairoLookupTableTextureRenderer.cpp Framework/Scene2D/Internals/CairoLookupTableTextureRenderer.h Framework/Scene2D/LookupTableTextureSceneLayer.cpp Framework/Scene2D/LookupTableTextureSceneLayer.h Framework/Toolbox/DicomInstanceParameters.cpp Framework/Toolbox/DicomInstanceParameters.h Resources/CMake/OrthancStoneConfiguration.cmake Samples/Sdl/Loader.cpp |
diffstat | 14 files changed, 528 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Scene2D/CairoCompositor.cpp Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/CairoCompositor.cpp Thu May 23 20:04:33 2019 +0200 @@ -24,6 +24,7 @@ #include "Internals/CairoColorTextureRenderer.h" #include "Internals/CairoFloatTextureRenderer.h" #include "Internals/CairoInfoPanelRenderer.h" +#include "Internals/CairoLookupTableTextureRenderer.h" #include "Internals/CairoPolylineRenderer.h" #include "Internals/CairoTextRenderer.h" @@ -60,6 +61,9 @@ case ISceneLayer::Type_FloatTexture: return new Internals::CairoFloatTextureRenderer(*this, layer); + case ISceneLayer::Type_LookupTableTexture: + return new Internals::CairoLookupTableTextureRenderer(*this, layer); + case ISceneLayer::Type_Text: { const TextSceneLayer& l = dynamic_cast<const TextSceneLayer&>(layer);
--- a/Framework/Scene2D/ColorTextureSceneLayer.h Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/ColorTextureSceneLayer.h Thu May 23 20:04:33 2019 +0200 @@ -28,6 +28,7 @@ class ColorTextureSceneLayer : public TextureBaseSceneLayer { public: + // If using RGBA32, premultiplied alpha is assumed ColorTextureSceneLayer(const Orthanc::ImageAccessor& texture); virtual ISceneLayer* Clone() const;
--- a/Framework/Scene2D/ISceneLayer.h Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/ISceneLayer.h Thu May 23 20:04:33 2019 +0200 @@ -37,7 +37,8 @@ Type_ColorTexture, Type_Polyline, Type_Text, - Type_FloatTexture + Type_FloatTexture, + Type_LookupTableTexture }; virtual ~ISceneLayer()
--- a/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp Thu May 23 20:04:33 2019 +0200 @@ -44,13 +44,17 @@ isLinearInterpolation_ = l.IsLinearInterpolation(); } - - void CairoColorTextureRenderer::Render(const AffineTransform2D& transform) + + void CairoColorTextureRenderer::RenderColorTexture(ICairoContextProvider& target, + const AffineTransform2D& transform, + CairoSurface& texture, + const AffineTransform2D& textureTransform, + bool isLinearInterpolation) { - cairo_t* cr = target_.GetCairoContext(); + cairo_t* cr = target.GetCairoContext(); AffineTransform2D t = - AffineTransform2D::Combine(transform, textureTransform_); + AffineTransform2D::Combine(transform, textureTransform); Matrix h = t.GetHomogeneousMatrix(); cairo_save(cr); @@ -60,9 +64,9 @@ cairo_transform(cr, &m); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cr, texture_.GetObject(), 0, 0); + cairo_set_source_surface(cr, texture.GetObject(), 0, 0); - if (isLinearInterpolation_) + if (isLinearInterpolation) { cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); }
--- a/Framework/Scene2D/Internals/CairoColorTextureRenderer.h Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/Internals/CairoColorTextureRenderer.h Thu May 23 20:04:33 2019 +0200 @@ -43,7 +43,17 @@ virtual void Update(const ISceneLayer& layer); - virtual void Render(const AffineTransform2D& transform); + virtual void Render(const AffineTransform2D& transform) + { + RenderColorTexture(target_, transform, texture_, + textureTransform_, isLinearInterpolation_); + } + + static void RenderColorTexture(ICairoContextProvider& target, + const AffineTransform2D& transform, + CairoSurface& texture, + const AffineTransform2D& textureTransform, + bool isLinearInterpolation); }; } }
--- a/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp Thu May 23 20:04:33 2019 +0200 @@ -21,6 +21,7 @@ #include "CairoFloatTextureRenderer.h" +#include "CairoColorTextureRenderer.h" #include "../FloatTextureSceneLayer.h" namespace OrthancStone @@ -84,33 +85,8 @@ void CairoFloatTextureRenderer::Render(const AffineTransform2D& transform) { - cairo_t* cr = target_.GetCairoContext(); - - AffineTransform2D t = - AffineTransform2D::Combine(transform, textureTransform_); - Matrix h = t.GetHomogeneousMatrix(); - - cairo_save(cr); - - cairo_matrix_t m; - cairo_matrix_init(&m, h(0, 0), h(1, 0), h(0, 1), h(1, 1), h(0, 2), h(1, 2)); - cairo_transform(cr, &m); - - cairo_set_operator(cr, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cr, texture_.GetObject(), 0, 0); - - if (isLinearInterpolation_) - { - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); - } - else - { - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); - } - - cairo_paint(cr); - - cairo_restore(cr); + CairoColorTextureRenderer::RenderColorTexture(target_, transform, texture_, + textureTransform_, isLinearInterpolation_); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoLookupTableTextureRenderer.cpp Thu May 23 20:04:33 2019 +0200 @@ -0,0 +1,108 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "CairoLookupTableTextureRenderer.h" + +#include "CairoColorTextureRenderer.h" +#include "../LookupTableTextureSceneLayer.h" + +#include <Core/OrthancException.h> + +namespace OrthancStone +{ + namespace Internals + { + void CairoLookupTableTextureRenderer::Update(const ISceneLayer& layer) + { + const LookupTableTextureSceneLayer& l = dynamic_cast<const LookupTableTextureSceneLayer&>(layer); + + textureTransform_ = l.GetTransform(); + isLinearInterpolation_ = l.IsLinearInterpolation(); + + const float a = l.GetMinValue(); + float slope; + + if (l.GetMinValue() >= l.GetMaxValue()) + { + slope = 0; + } + else + { + slope = 256.0f / (l.GetMaxValue() - l.GetMinValue()); + } + + const Orthanc::ImageAccessor& source = l.GetTexture(); + const unsigned int width = source.GetWidth(); + const unsigned int height = source.GetHeight(); + texture_.SetSize(width, height, true /* alpha channel is enabled */); + + Orthanc::ImageAccessor target; + texture_.GetWriteableAccessor(target); + + const std::vector<uint8_t>& lut = l.GetLookupTable(); + if (lut.size() != 4 * 256) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + assert(source.GetFormat() == Orthanc::PixelFormat_Float32 && + target.GetFormat() == Orthanc::PixelFormat_BGRA32 && + sizeof(float) == 4); + + for (unsigned int y = 0; y < height; y++) + { + const float* p = reinterpret_cast<const float*>(source.GetConstRow(y)); + uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); + + for (unsigned int x = 0; x < width; x++) + { + float v = (*p - a) * slope; + if (v <= 0) + { + v = 0; + } + else if (v >= 255) + { + v = 255; + } + + uint8_t vv = static_cast<uint8_t>(v); + + q[0] = lut[4 * vv + 2]; // B + q[1] = lut[4 * vv + 1]; // G + q[2] = lut[4 * vv + 0]; // R + q[3] = lut[4 * vv + 3]; // A + + p++; + q += 4; + } + } + + cairo_surface_mark_dirty(texture_.GetObject()); + } + + void CairoLookupTableTextureRenderer::Render(const AffineTransform2D& transform) + { + CairoColorTextureRenderer::RenderColorTexture(target_, transform, texture_, + textureTransform_, isLinearInterpolation_); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoLookupTableTextureRenderer.h Thu May 23 20:04:33 2019 +0200 @@ -0,0 +1,53 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Viewport/CairoSurface.h" +#include "CompositorHelper.h" +#include "ICairoContextProvider.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoLookupTableTextureRenderer : public CompositorHelper::ILayerRenderer + { + private: + ICairoContextProvider& target_; + CairoSurface texture_; + AffineTransform2D textureTransform_; + bool isLinearInterpolation_; + + public: + CairoLookupTableTextureRenderer(ICairoContextProvider& target, + const ISceneLayer& layer) : + target_(target) + { + Update(layer); + } + + virtual void Update(const ISceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform); + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/LookupTableTextureSceneLayer.cpp Thu May 23 20:04:33 2019 +0200 @@ -0,0 +1,183 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "LookupTableTextureSceneLayer.h" + +#include <Core/Images/Image.h> +#include <Core/Images/ImageProcessing.h> +#include <Core/OrthancException.h> + +namespace OrthancStone +{ + static void StringToVector(std::vector<uint8_t>& target, + const std::string& source) + { + target.resize(source.size()); + + for (size_t i = 0; i < source.size(); i++) + { + target[i] = source[i]; + } + } + + + LookupTableTextureSceneLayer::LookupTableTextureSceneLayer(const Orthanc::ImageAccessor& texture) + { + { + std::auto_ptr<Orthanc::ImageAccessor> t( + new Orthanc::Image(Orthanc::PixelFormat_Float32, + texture.GetWidth(), + texture.GetHeight(), + false)); + + Orthanc::ImageProcessing::Convert(*t, texture); + SetTexture(t.release()); + } + + SetLookupTableGrayscale(1); + SetRange(0, 1); + } + + + void LookupTableTextureSceneLayer::SetLookupTableGrayscale(float alpha) + { + std::vector<uint8_t> rgb(3 * 256); + + for (size_t i = 0; i < 256; i++) + { + rgb[3 * i] = i; + rgb[3 * i + 1] = i; + rgb[3 * i + 2] = i; + } + + SetLookupTableRgb(rgb, alpha); + } + + + void LookupTableTextureSceneLayer::SetLookupTableRgb(const std::vector<uint8_t>& lut, + float alpha) + { + if (lut.size() != 3 * 256 || + alpha < 0 || + alpha > 1) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + lut_.resize(4 * 256); + + for (size_t i = 0; i < 256; i++) + { + // Premultiplied alpha + + if (i == 0) + { + // Make zero transparent + lut_[4 * i] = 0; // R + lut_[4 * i + 1] = 0; // G + lut_[4 * i + 2] = 0; // B + lut_[4 * i + 3] = 0; // A + } + else + { + float r = static_cast<float>(lut[3 * i]) * alpha; + float g = static_cast<float>(lut[3 * i + 1]) * alpha; + float b = static_cast<float>(lut[3 * i + 2]) * alpha; + + lut_[4 * i] = static_cast<uint8_t>(std::floor(r)); + lut_[4 * i + 1] = static_cast<uint8_t>(std::floor(g)); + lut_[4 * i + 2] = static_cast<uint8_t>(std::floor(b)); + lut_[4 * i + 3] = static_cast<uint8_t>(std::floor(alpha * 255.0f)); + } + } + + IncrementRevision(); + } + + + void LookupTableTextureSceneLayer::SetLookupTableRgb(const std::string& lut, + float alpha) + { + std::vector<uint8_t> tmp; + StringToVector(tmp, lut); + SetLookupTableRgb(tmp, alpha); + } + + + void LookupTableTextureSceneLayer::SetLookupTable(const std::vector<uint8_t>& lut) + { + if (lut.size() != 4 * 256) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + lut_ = lut; + + IncrementRevision(); + } + + + void LookupTableTextureSceneLayer::SetLookupTable(const std::string& lut) + { + std::vector<uint8_t> tmp; + StringToVector(tmp, lut); + SetLookupTable(tmp); + } + + + void LookupTableTextureSceneLayer::SetRange(float minValue, + float maxValue) + { + if (minValue > maxValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else + { + minValue_ = minValue; + maxValue_ = maxValue; + IncrementRevision(); + } + } + + + void LookupTableTextureSceneLayer::FitRange() + { + Orthanc::ImageProcessing::GetMinMaxFloatValue(minValue_, maxValue_, GetTexture()); + assert(minValue_ <= maxValue_); + + IncrementRevision(); + } + + + ISceneLayer* LookupTableTextureSceneLayer::Clone() const + { + std::auto_ptr<LookupTableTextureSceneLayer> cloned + (new LookupTableTextureSceneLayer(GetTexture())); + + cloned->CopyParameters(*this); + cloned->minValue_ = minValue_; + cloned->maxValue_ = maxValue_; + cloned->lut_ = lut_; + + return cloned.release(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/LookupTableTextureSceneLayer.h Thu May 23 20:04:33 2019 +0200 @@ -0,0 +1,79 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "TextureBaseSceneLayer.h" + +namespace OrthancStone +{ + class LookupTableTextureSceneLayer : public TextureBaseSceneLayer + { + private: + ImageWindowing windowing_; + float minValue_; + float maxValue_; + std::vector<uint8_t> lut_; + + public: + // The pixel format must be "Flot32" + LookupTableTextureSceneLayer(const Orthanc::ImageAccessor& texture); + + void SetLookupTableGrayscale(float alpha); + + void SetLookupTableRgb(const std::vector<uint8_t>& lut, + float alpha); + + void SetLookupTableRgb(const std::string& lut, + float alpha); + + void SetLookupTable(const std::vector<uint8_t>& lut); + + void SetLookupTable(const std::string& lut); + + void SetRange(float minValue, + float maxValue); + + void FitRange(); + + float GetMinValue() const + { + return minValue_; + } + + float GetMaxValue() const + { + return maxValue_; + } + + const std::vector<uint8_t>& GetLookupTable() const + { + return lut_; + } + + virtual ISceneLayer* Clone() const; + + virtual Type GetType() const + { + return Type_LookupTableTexture; + } + }; +}
--- a/Framework/Toolbox/DicomInstanceParameters.cpp Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Toolbox/DicomInstanceParameters.cpp Thu May 23 20:04:33 2019 +0200 @@ -320,7 +320,24 @@ } - TextureBaseSceneLayer* DicomInstanceParameters::CreateTexture(const Orthanc::ImageAccessor& pixelData) const + Orthanc::ImageAccessor* DicomInstanceParameters::ConvertToFloat(const Orthanc::ImageAccessor& pixelData) const + { + std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, + pixelData.GetWidth(), + pixelData.GetHeight(), + false)); + Orthanc::ImageProcessing::Convert(*converted, pixelData); + + // Correct rescale slope/intercept if need be + data_.ApplyRescale(*converted, (pixelData.GetFormat() == Orthanc::PixelFormat_Grayscale32)); + + return converted.release(); + } + + + + TextureBaseSceneLayer* DicomInstanceParameters::CreateTexture + (const Orthanc::ImageAccessor& pixelData) const { assert(sizeof(float) == 4); @@ -338,26 +355,16 @@ } else { - if (sourceFormat != Orthanc::PixelFormat_Grayscale16 && - sourceFormat != Orthanc::PixelFormat_Grayscale32 && - sourceFormat != Orthanc::PixelFormat_SignedGrayscale16) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); - } + // This is the case of a grayscale frame. Convert it to Float32. + std::auto_ptr<FloatTextureSceneLayer> texture; - std::auto_ptr<FloatTextureSceneLayer> texture; - + if (pixelData.GetFormat() == Orthanc::PixelFormat_Float32) { - // This is the case of a grayscale frame. Convert it to Float32. - std::auto_ptr<Orthanc::Image> converted(new Orthanc::Image(Orthanc::PixelFormat_Float32, - pixelData.GetWidth(), - pixelData.GetHeight(), - false)); - Orthanc::ImageProcessing::Convert(*converted, pixelData); - - // Correct rescale slope/intercept if need be - data_.ApplyRescale(*converted, (sourceFormat == Orthanc::PixelFormat_Grayscale32)); - + texture.reset(new FloatTextureSceneLayer(pixelData)); + } + else + { + std::auto_ptr<Orthanc::ImageAccessor> converted(ConvertToFloat(pixelData)); texture.reset(new FloatTextureSceneLayer(*converted)); } @@ -370,4 +377,21 @@ return texture.release(); } } + + + LookupTableTextureSceneLayer* DicomInstanceParameters::CreateLookupTableTexture + (const Orthanc::ImageAccessor& pixelData) const + { + std::auto_ptr<FloatTextureSceneLayer> texture; + + if (pixelData.GetFormat() == Orthanc::PixelFormat_Float32) + { + return new LookupTableTextureSceneLayer(pixelData); + } + else + { + std::auto_ptr<Orthanc::ImageAccessor> converted(ConvertToFloat(pixelData)); + return new LookupTableTextureSceneLayer(*converted); + } + } }
--- a/Framework/Toolbox/DicomInstanceParameters.h Thu May 23 16:57:33 2019 +0200 +++ b/Framework/Toolbox/DicomInstanceParameters.h Thu May 23 20:04:33 2019 +0200 @@ -22,7 +22,7 @@ #pragma once #include "../StoneEnumerations.h" -#include "../Scene2D/TextureBaseSceneLayer.h" +#include "../Scene2D/LookupTableTextureSceneLayer.h" #include "../Toolbox/CoordinateSystem3D.h" #include <Core/IDynamicObject.h> @@ -72,6 +72,9 @@ }; + Orthanc::ImageAccessor* ConvertToFloat(const Orthanc::ImageAccessor& pixelData) const; + + Data data_; @@ -181,5 +184,7 @@ } TextureBaseSceneLayer* CreateTexture(const Orthanc::ImageAccessor& pixelData) const; + + LookupTableTextureSceneLayer* CreateLookupTableTexture(const Orthanc::ImageAccessor& pixelData) const; }; }
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Thu May 23 16:57:33 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Thu May 23 20:04:33 2019 +0200 @@ -380,10 +380,12 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoInfoPanelRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoLookupTableTextureRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoPolylineRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoTextRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CompositorHelper.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/FixedPointAligner.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/LookupTableTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/PanSceneTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/PointerEvent.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/PolylineSceneLayer.cpp
--- a/Samples/Sdl/Loader.cpp Thu May 23 16:57:33 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Thu May 23 20:04:33 2019 +0200 @@ -33,6 +33,7 @@ #include "../../Framework/Scene2D/CairoCompositor.h" #include "../../Framework/Scene2D/Scene2D.h" #include "../../Framework/Scene2D/PolylineSceneLayer.h" +#include "../../Framework/Scene2D/LookupTableTextureSceneLayer.h" #include "../../Framework/StoneInitialization.h" #include "../../Framework/Toolbox/GeometryToolbox.h" #include "../../Framework/Toolbox/SlicesSorter.h" @@ -50,6 +51,9 @@ #include <Core/Toolbox.h> +#include <EmbeddedResources.h> + + namespace OrthancStone { class IVolumeSlicer : public boost::noncopyable @@ -174,7 +178,25 @@ { const DicomInstanceParameters& parameters = GetDicomParameters(projection_, sliceIndex_); ImageBuffer3D::SliceReader reader(image_, projection_, sliceIndex_); - texture.reset(parameters.CreateTexture(reader.GetAccessor())); + + static unsigned int i = 1; + + if (i % 2) + { + texture.reset(parameters.CreateTexture(reader.GetAccessor())); + } + else + { + std::string lut; + Orthanc::EmbeddedResources::GetFileResource(lut, Orthanc::EmbeddedResources::COLORMAP_HOT); + + std::auto_ptr<LookupTableTextureSceneLayer> tmp(parameters.CreateLookupTableTexture(reader.GetAccessor())); + tmp->FitRange(); + tmp->SetLookupTableRgb(lut, 1); + texture.reset(tmp.release()); + } + + i++; } const CoordinateSystem3D& system = geometry_.GetProjectionGeometry(projection_);