Mercurial > hg > orthanc-stone
view OrthancStone/Sources/Scene2D/GrayscaleWindowingSceneTracker.cpp @ 2135:6cc11bd11890 dicom-sr
integration mainline->dicom-sr
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 30 May 2024 21:31:55 +0200 |
parents | 16c01cc201e7 |
children | 7e8b918b0482 |
line wrap: on
line source
/** * Stone of Orthanc * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium * Copyright (C) 2021-2024 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 "GrayscaleWindowingSceneTracker.h" #include "../Scene2DViewport/ViewportController.h" #include "FloatTextureSceneLayer.h" #include <OrthancException.h> namespace OrthancStone { namespace { class GrayscaleLayerAccessor : public boost::noncopyable { private: std::unique_ptr<IViewport::ILock> lock_; FloatTextureSceneLayer* layer_; public: GrayscaleLayerAccessor(boost::weak_ptr<IViewport> viewportWeak, int layerIndex) : layer_(NULL) { boost::shared_ptr<IViewport> viewport = viewportWeak.lock(); if (viewport != NULL) { lock_.reset(viewport->Lock()); if (lock_->GetController().GetScene().HasLayer(layerIndex)) { ISceneLayer& layer = lock_->GetController().GetScene().GetLayer(layerIndex); if (layer.GetType() == ISceneLayer::Type_FloatTexture) { layer_ = &dynamic_cast<FloatTextureSceneLayer&>(layer); } } } } bool IsValid() const { return layer_ != NULL; } FloatTextureSceneLayer& GetLayer() const { if (layer_ == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else { return *layer_; } } void Invalidate() { if (lock_.get() != NULL) { lock_->Invalidate(); } } void BroadcastGrayscaleWindowingChanged(double center, double width) { if (lock_.get() != NULL) { lock_->GetController().BroadcastGrayscaleWindowingChanged(center, width); } } }; } void GrayscaleWindowingSceneTracker::SetWindowing(float center, float width) { if (active_) { boost::shared_ptr<IViewport> viewport = viewport_.lock(); GrayscaleLayerAccessor accessor(viewport, layerIndex_); if (accessor.IsValid()) { accessor.GetLayer().SetCustomWindowing(center, width); accessor.BroadcastGrayscaleWindowingChanged(center, width); accessor.Invalidate(); } } } GrayscaleWindowingSceneTracker::GrayscaleWindowingSceneTracker(boost::weak_ptr<IViewport> viewport, int layerIndex, const PointerEvent& event, unsigned int canvasWidth, unsigned int canvasHeight) : viewport_(viewport), layerIndex_(layerIndex), clickX_(event.GetMainPosition().GetX()), clickY_(event.GetMainPosition().GetY()) { active_ = false; if (canvasWidth > 3 && canvasHeight > 3) { boost::shared_ptr<IViewport> locked = viewport_.lock(); if (locked) { GrayscaleLayerAccessor accessor(locked, layerIndex_); if (accessor.IsValid()) { FloatTextureSceneLayer& layer = accessor.GetLayer(); layer.GetWindowing(originalCenter_, originalWidth_); float minValue, maxValue; layer.GetRange(minValue, maxValue); normalization_ = (maxValue - minValue) / static_cast<double>(std::min(canvasWidth, canvasHeight) - 1); active_ = true; } else { LOG(INFO) << "Cannot create GrayscaleWindowingSceneTracker on a non-float texture"; } } } } void GrayscaleWindowingSceneTracker::PointerMove(const PointerEvent& event, const Scene2D& scene) { if (active_) { const double x = event.GetMainPosition().GetX(); const double y = event.GetMainPosition().GetY(); float center = originalCenter_ + static_cast<float>((x - clickX_) * normalization_); float width = originalWidth_ + static_cast<float>((y - clickY_) * normalization_); if (width <= 1) { width = 1; } SetWindowing(center, width); } } void GrayscaleWindowingSceneTracker::Cancel(const Scene2D& scene) { SetWindowing(originalCenter_, originalWidth_); } }