changeset 344:5050be0f646b

renamed class OnTheFlyPyramidsCache as DecodedPyramidCache
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 10 Dec 2024 13:11:58 +0100
parents af8ebf590a29
children e1d9a00d6f64
files Applications/CMakeLists.txt Framework/Inputs/DecodedPyramidCache.cpp Framework/Inputs/DecodedPyramidCache.h Framework/Inputs/OnTheFlyPyramidsCache.cpp Framework/Inputs/OnTheFlyPyramidsCache.h ViewerPlugin/CMakeLists.txt ViewerPlugin/Plugin.cpp
diffstat 7 files changed, 364 insertions(+), 364 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/CMakeLists.txt	Tue Dec 10 13:07:25 2024 +0100
+++ b/Applications/CMakeLists.txt	Tue Dec 10 13:11:58 2024 +0100
@@ -114,13 +114,13 @@
   ${ORTHANC_WSI_DIR}/Framework/ImageToolbox.cpp
   ${ORTHANC_WSI_DIR}/Framework/ImagedVolumeParameters.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/CytomineImage.cpp
+  ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedPyramidCache.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedTiledPyramid.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramid.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidInstance.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidLevel.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/HierarchicalTiff.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramid.cpp
-  ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramidsCache.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/OpenSlideLibrary.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/OpenSlidePyramid.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/PlainTiff.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Inputs/DecodedPyramidCache.cpp	Tue Dec 10 13:11:58 2024 +0100
@@ -0,0 +1,240 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2024 Orthanc Team SRL, 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 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 "../PrecompiledHeadersWSI.h"
+#include "DecodedPyramidCache.h"
+
+
+static std::unique_ptr<OrthancWSI::DecodedPyramidCache>  singleton_;
+
+namespace OrthancWSI
+{
+  class DecodedPyramidCache::CachedPyramid : public boost::noncopyable
+  {
+  private:
+    std::unique_ptr<DecodedTiledPyramid>  pyramid_;
+    size_t                                memory_;
+
+  public:
+    explicit CachedPyramid(DecodedTiledPyramid* pyramid) :
+      pyramid_(pyramid)
+    {
+      if (pyramid == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      }
+      else
+      {
+        memory_ = pyramid->GetMemoryUsage();
+      }
+    }
+
+    DecodedTiledPyramid& GetPyramid() const
+    {
+      assert(pyramid_ != NULL);
+      return *pyramid_;
+    }
+
+    size_t GetMemoryUsage() const
+    {
+      return memory_;
+    }
+  };
+
+
+  bool DecodedPyramidCache::SanityCheck()
+  {
+    return (cache_.GetSize() < maxCount_ &&
+            (cache_.IsEmpty() || maxMemory_ == 0 || memoryUsage_ <= maxMemory_));
+  }
+
+
+  void DecodedPyramidCache::MakeRoom(size_t memory)
+  {
+    // Mutex must be locked
+
+    while (cache_.GetSize() >= maxCount_ ||
+           (!cache_.IsEmpty() &&
+            maxMemory_ != 0 &&
+            memoryUsage_ + memory > maxMemory_))
+    {
+      CachedPyramid* oldest = NULL;
+      cache_.RemoveOldest(oldest);
+
+      if (oldest == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+      else
+      {
+        memoryUsage_ -= oldest->GetMemoryUsage();
+        delete oldest;
+      }
+    }
+
+    assert(SanityCheck());
+  }
+
+
+  DecodedPyramidCache::CachedPyramid * DecodedPyramidCache::Store(FrameIdentifier identifier,
+                                                                      DecodedTiledPyramid *pyramid)
+  {
+    // Mutex must be locked
+
+    std::unique_ptr<CachedPyramid> payload(new CachedPyramid(pyramid));
+    CachedPyramid* result = payload.get();
+
+    MakeRoom(payload->GetMemoryUsage());
+
+    memoryUsage_ += payload->GetMemoryUsage();
+
+    // Add a new element to the cache and make it the most
+    // recently used entry
+    cache_.Add(identifier, payload.release());
+
+    assert(SanityCheck());
+    return result;
+  }
+
+
+  DecodedPyramidCache::DecodedPyramidCache(IPyramidFetcher *fetcher,
+                                               size_t maxCount,
+                                               size_t maxMemory):
+    fetcher_(fetcher),
+    maxCount_(maxCount),
+    maxMemory_(maxMemory),  // 256 MB
+    memoryUsage_(0)
+  {
+    if (fetcher == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+
+    if (maxCount == 0)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+    }
+
+    assert(SanityCheck());
+  }
+
+
+  DecodedPyramidCache::~DecodedPyramidCache()
+  {
+    while (!cache_.IsEmpty())
+    {
+      CachedPyramid* pyramid = NULL;
+      cache_.RemoveOldest(pyramid);
+
+      if (pyramid != NULL)
+      {
+        delete pyramid;
+      }
+    }
+  }
+
+
+  void DecodedPyramidCache::InitializeInstance(IPyramidFetcher *fetcher,
+                                                 size_t maxSize,
+                                                 size_t maxMemory)
+  {
+    if (singleton_.get() == NULL)
+    {
+      singleton_.reset(new DecodedPyramidCache(fetcher, maxSize, maxMemory));
+    }
+    else
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+  }
+
+
+  void DecodedPyramidCache::FinalizeInstance()
+  {
+    if (singleton_.get() == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      singleton_.reset(NULL);
+    }
+  }
+
+
+  DecodedPyramidCache & DecodedPyramidCache::GetInstance()
+  {
+    if (singleton_.get() == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+    else
+    {
+      return *singleton_;
+    }
+  }
+
+
+  DecodedPyramidCache::Accessor::Accessor(DecodedPyramidCache& that,
+                                            const std::string &instanceId,
+                                            unsigned int frameNumber):
+    lock_(that.mutex_),
+    identifier_(instanceId, frameNumber),
+    pyramid_(NULL)
+  {
+    if (that.cache_.Contains(identifier_, pyramid_))
+    {
+      if (pyramid_ == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+
+      // Tag the series as the most recently used
+      that.cache_.MakeMostRecent(identifier_);
+    }
+    else
+    {
+      // Unlock the mutex as creating the pyramid is a time-consuming operation
+      lock_.unlock();
+
+      std::unique_ptr<DecodedTiledPyramid> payload(that.fetcher_->Fetch(instanceId, frameNumber));
+
+      // Re-lock, as we now modify the cache
+      lock_.lock();
+      pyramid_ = that.Store(identifier_, payload.release());
+    }
+  }
+
+
+  DecodedTiledPyramid & DecodedPyramidCache::Accessor::GetPyramid() const
+  {
+    if (IsValid())
+    {
+      return pyramid_->GetPyramid();
+    }
+    else
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Framework/Inputs/DecodedPyramidCache.h	Tue Dec 10 13:11:58 2024 +0100
@@ -0,0 +1,116 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2024 Orthanc Team SRL, 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 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 "DecodedTiledPyramid.h"
+
+#include <Cache/LeastRecentlyUsedIndex.h>
+
+#include <boost/thread/mutex.hpp>
+
+
+namespace OrthancWSI
+{
+  class DecodedPyramidCache : public boost::noncopyable
+  {
+  public:
+    class IPyramidFetcher : public boost::noncopyable
+    {
+    public:
+      virtual ~IPyramidFetcher()
+      {
+      }
+
+      virtual DecodedTiledPyramid* Fetch(const std::string& instanceId,
+                                         unsigned int frameNumber) = 0;
+    };
+
+  private:
+    class CachedPyramid;
+
+    typedef std::pair<std::string, unsigned int> FrameIdentifier;  // Associates an instance ID with a frame number
+
+    typedef Orthanc::LeastRecentlyUsedIndex<FrameIdentifier, CachedPyramid*>  Cache;
+
+    std::unique_ptr<IPyramidFetcher> fetcher_;
+
+    boost::mutex  mutex_;
+    size_t        maxCount_;
+    size_t        maxMemory_;
+    size_t        memoryUsage_;
+    Cache         cache_;
+
+    bool SanityCheck();
+
+    void MakeRoom(size_t memory);
+
+    CachedPyramid* Store(FrameIdentifier identifier,
+                         DecodedTiledPyramid* pyramid);
+
+    DecodedPyramidCache(IPyramidFetcher* fetcher /* takes ownership */,
+                          size_t maxCount,
+                          size_t maxMemory);
+
+  public:
+    ~DecodedPyramidCache();
+
+    static void InitializeInstance(IPyramidFetcher* fetcher,
+                                   size_t maxSize,
+                                   size_t maxMemory);
+
+    static void FinalizeInstance();
+
+    static DecodedPyramidCache& GetInstance();
+
+    class Accessor : public boost::noncopyable
+    {
+    private:
+      boost::mutex::scoped_lock lock_;
+      FrameIdentifier           identifier_;
+      CachedPyramid*            pyramid_;
+
+    public:
+      Accessor(DecodedPyramidCache& that,
+               const std::string& instanceId,
+               unsigned int frameNumber);
+
+      bool IsValid() const
+      {
+        return pyramid_ != NULL;
+      }
+
+      const std::string& GetInstanceId() const
+      {
+        return identifier_.first;
+      }
+
+      unsigned int GetFrameNumber() const
+      {
+        return identifier_.second;
+      }
+
+      DecodedTiledPyramid& GetPyramid() const;
+    };
+  };
+}
--- a/Framework/Inputs/OnTheFlyPyramidsCache.cpp	Tue Dec 10 13:07:25 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2024 Orthanc Team SRL, 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 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 "../PrecompiledHeadersWSI.h"
-#include "OnTheFlyPyramidsCache.h"
-
-
-static std::unique_ptr<OrthancWSI::OnTheFlyPyramidsCache>  singleton_;
-
-namespace OrthancWSI
-{
-  class OnTheFlyPyramidsCache::CachedPyramid : public boost::noncopyable
-  {
-  private:
-    std::unique_ptr<DecodedTiledPyramid>  pyramid_;
-    size_t                                memory_;
-
-  public:
-    explicit CachedPyramid(DecodedTiledPyramid* pyramid) :
-      pyramid_(pyramid)
-    {
-      if (pyramid == NULL)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
-      }
-      else
-      {
-        memory_ = pyramid->GetMemoryUsage();
-      }
-    }
-
-    DecodedTiledPyramid& GetPyramid() const
-    {
-      assert(pyramid_ != NULL);
-      return *pyramid_;
-    }
-
-    size_t GetMemoryUsage() const
-    {
-      return memory_;
-    }
-  };
-
-
-  bool OnTheFlyPyramidsCache::SanityCheck()
-  {
-    return (cache_.GetSize() < maxCount_ &&
-            (cache_.IsEmpty() || maxMemory_ == 0 || memoryUsage_ <= maxMemory_));
-  }
-
-
-  void OnTheFlyPyramidsCache::MakeRoom(size_t memory)
-  {
-    // Mutex must be locked
-
-    while (cache_.GetSize() >= maxCount_ ||
-           (!cache_.IsEmpty() &&
-            maxMemory_ != 0 &&
-            memoryUsage_ + memory > maxMemory_))
-    {
-      CachedPyramid* oldest = NULL;
-      cache_.RemoveOldest(oldest);
-
-      if (oldest == NULL)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-      else
-      {
-        memoryUsage_ -= oldest->GetMemoryUsage();
-        delete oldest;
-      }
-    }
-
-    assert(SanityCheck());
-  }
-
-
-  OnTheFlyPyramidsCache::CachedPyramid * OnTheFlyPyramidsCache::Store(FrameIdentifier identifier,
-                                                                      DecodedTiledPyramid *pyramid)
-  {
-    // Mutex must be locked
-
-    std::unique_ptr<CachedPyramid> payload(new CachedPyramid(pyramid));
-    CachedPyramid* result = payload.get();
-
-    MakeRoom(payload->GetMemoryUsage());
-
-    memoryUsage_ += payload->GetMemoryUsage();
-
-    // Add a new element to the cache and make it the most
-    // recently used entry
-    cache_.Add(identifier, payload.release());
-
-    assert(SanityCheck());
-    return result;
-  }
-
-
-  OnTheFlyPyramidsCache::OnTheFlyPyramidsCache(IPyramidFetcher *fetcher,
-                                               size_t maxCount,
-                                               size_t maxMemory):
-    fetcher_(fetcher),
-    maxCount_(maxCount),
-    maxMemory_(maxMemory),  // 256 MB
-    memoryUsage_(0)
-  {
-    if (fetcher == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
-    }
-
-    if (maxCount == 0)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
-    }
-
-    assert(SanityCheck());
-  }
-
-
-  OnTheFlyPyramidsCache::~OnTheFlyPyramidsCache()
-  {
-    while (!cache_.IsEmpty())
-    {
-      CachedPyramid* pyramid = NULL;
-      cache_.RemoveOldest(pyramid);
-
-      if (pyramid != NULL)
-      {
-        delete pyramid;
-      }
-    }
-  }
-
-
-  void OnTheFlyPyramidsCache::InitializeInstance(IPyramidFetcher *fetcher,
-                                                 size_t maxSize,
-                                                 size_t maxMemory)
-  {
-    if (singleton_.get() == NULL)
-    {
-      singleton_.reset(new OnTheFlyPyramidsCache(fetcher, maxSize, maxMemory));
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-  }
-
-
-  void OnTheFlyPyramidsCache::FinalizeInstance()
-  {
-    if (singleton_.get() == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-    else
-    {
-      singleton_.reset(NULL);
-    }
-  }
-
-
-  OnTheFlyPyramidsCache & OnTheFlyPyramidsCache::GetInstance()
-  {
-    if (singleton_.get() == NULL)
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-    else
-    {
-      return *singleton_;
-    }
-  }
-
-
-  OnTheFlyPyramidsCache::Accessor::Accessor(OnTheFlyPyramidsCache& that,
-                                            const std::string &instanceId,
-                                            unsigned int frameNumber):
-    lock_(that.mutex_),
-    identifier_(instanceId, frameNumber),
-    pyramid_(NULL)
-  {
-    if (that.cache_.Contains(identifier_, pyramid_))
-    {
-      if (pyramid_ == NULL)
-      {
-        throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
-      }
-
-      // Tag the series as the most recently used
-      that.cache_.MakeMostRecent(identifier_);
-    }
-    else
-    {
-      // Unlock the mutex as creating the pyramid is a time-consuming operation
-      lock_.unlock();
-
-      std::unique_ptr<DecodedTiledPyramid> payload(that.fetcher_->Fetch(instanceId, frameNumber));
-
-      // Re-lock, as we now modify the cache
-      lock_.lock();
-      pyramid_ = that.Store(identifier_, payload.release());
-    }
-  }
-
-
-  DecodedTiledPyramid & OnTheFlyPyramidsCache::Accessor::GetPyramid() const
-  {
-    if (IsValid())
-    {
-      return pyramid_->GetPyramid();
-    }
-    else
-    {
-      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
-    }
-  }
-}
--- a/Framework/Inputs/OnTheFlyPyramidsCache.h	Tue Dec 10 13:07:25 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/**
- * Orthanc - A Lightweight, RESTful DICOM Store
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2023 Osimis S.A., Belgium
- * Copyright (C) 2024-2024 Orthanc Team SRL, 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 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 "DecodedTiledPyramid.h"
-
-#include <Cache/LeastRecentlyUsedIndex.h>
-
-#include <boost/thread/mutex.hpp>
-
-
-namespace OrthancWSI
-{
-  class OnTheFlyPyramidsCache : public boost::noncopyable
-  {
-  public:
-    class IPyramidFetcher : public boost::noncopyable
-    {
-    public:
-      virtual ~IPyramidFetcher()
-      {
-      }
-
-      virtual DecodedTiledPyramid* Fetch(const std::string& instanceId,
-                                         unsigned int frameNumber) = 0;
-    };
-
-  private:
-    class CachedPyramid;
-
-    typedef std::pair<std::string, unsigned int> FrameIdentifier;  // Associates an instance ID with a frame number
-
-    typedef Orthanc::LeastRecentlyUsedIndex<FrameIdentifier, CachedPyramid*>  Cache;
-
-    std::unique_ptr<IPyramidFetcher> fetcher_;
-
-    boost::mutex  mutex_;
-    size_t        maxCount_;
-    size_t        maxMemory_;
-    size_t        memoryUsage_;
-    Cache         cache_;
-
-    bool SanityCheck();
-
-    void MakeRoom(size_t memory);
-
-    CachedPyramid* Store(FrameIdentifier identifier,
-                         DecodedTiledPyramid* pyramid);
-
-    OnTheFlyPyramidsCache(IPyramidFetcher* fetcher /* takes ownership */,
-                          size_t maxCount,
-                          size_t maxMemory);
-
-  public:
-    ~OnTheFlyPyramidsCache();
-
-    static void InitializeInstance(IPyramidFetcher* fetcher,
-                                   size_t maxSize,
-                                   size_t maxMemory);
-
-    static void FinalizeInstance();
-
-    static OnTheFlyPyramidsCache& GetInstance();
-
-    class Accessor : public boost::noncopyable
-    {
-    private:
-      boost::mutex::scoped_lock lock_;
-      FrameIdentifier           identifier_;
-      CachedPyramid*            pyramid_;
-
-    public:
-      Accessor(OnTheFlyPyramidsCache& that,
-               const std::string& instanceId,
-               unsigned int frameNumber);
-
-      bool IsValid() const
-      {
-        return pyramid_ != NULL;
-      }
-
-      const std::string& GetInstanceId() const
-      {
-        return identifier_.first;
-      }
-
-      unsigned int GetFrameNumber() const
-      {
-        return identifier_.second;
-      }
-
-      DecodedTiledPyramid& GetPyramid() const;
-    };
-  };
-}
--- a/ViewerPlugin/CMakeLists.txt	Tue Dec 10 13:07:25 2024 +0100
+++ b/ViewerPlugin/CMakeLists.txt	Tue Dec 10 13:11:58 2024 +0100
@@ -195,12 +195,12 @@
   ${ORTHANC_WSI_DIR}/Framework/DicomToolbox.cpp
   ${ORTHANC_WSI_DIR}/Framework/Enumerations.cpp
   ${ORTHANC_WSI_DIR}/Framework/ImageToolbox.cpp
+  ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedPyramidCache.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DecodedTiledPyramid.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramid.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidInstance.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/DicomPyramidLevel.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramid.cpp
-  ${ORTHANC_WSI_DIR}/Framework/Inputs/OnTheFlyPyramidsCache.cpp
   ${ORTHANC_WSI_DIR}/Framework/Inputs/PyramidWithRawTiles.cpp
   ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Reader.cpp
   ${ORTHANC_WSI_DIR}/Framework/Jpeg2000Writer.cpp
--- a/ViewerPlugin/Plugin.cpp	Tue Dec 10 13:07:25 2024 +0100
+++ b/ViewerPlugin/Plugin.cpp	Tue Dec 10 13:11:58 2024 +0100
@@ -28,7 +28,7 @@
 #include "RawTile.h"
 #include "../Framework/Inputs/DecodedTiledPyramid.h"
 #include "../Framework/Inputs/OnTheFlyPyramid.h"
-#include "../Framework/Inputs/OnTheFlyPyramidsCache.h"
+#include "../Framework/Inputs/DecodedPyramidCache.h"
 #include "../Framework/ImageToolbox.h"
 
 #include <Compatibility.h>  // For std::unique_ptr
@@ -53,7 +53,7 @@
 
 namespace OrthancWSI
 {
-  class OrthancPyramidFrameFetcher : public OnTheFlyPyramidsCache::IPyramidFetcher
+  class OrthancPyramidFrameFetcher : public DecodedPyramidCache::IPyramidFetcher
   {
   private:
     std::unique_ptr<OrthancStone::IOrthancConnection>  orthanc_;
@@ -303,7 +303,7 @@
     throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
   }
 
-  OrthancWSI::OnTheFlyPyramidsCache::Accessor accessor(OrthancWSI::OnTheFlyPyramidsCache::GetInstance(), instanceId, frameNumber);
+  OrthancWSI::DecodedPyramidCache::Accessor accessor(OrthancWSI::DecodedPyramidCache::GetInstance(), instanceId, frameNumber);
 
   unsigned int totalWidth = accessor.GetPyramid().GetLevelWidth(0);
   unsigned int totalHeight = accessor.GetPyramid().GetLevelHeight(0);
@@ -386,7 +386,7 @@
   std::unique_ptr<Orthanc::ImageAccessor> tile;
 
   {
-    OrthancWSI::OnTheFlyPyramidsCache::Accessor accessor(OrthancWSI::OnTheFlyPyramidsCache::GetInstance(), instanceId, frameNumber);
+    OrthancWSI::DecodedPyramidCache::Accessor accessor(OrthancWSI::DecodedPyramidCache::GetInstance(), instanceId, frameNumber);
     if (!accessor.IsValid())
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource);
@@ -571,7 +571,7 @@
     OrthancPlugins::SetDescription(ORTHANC_PLUGIN_NAME, "Provides a Web viewer of whole-slide microscopic images within Orthanc.");
 
     OrthancWSI::DicomPyramidCache::InitializeInstance(10 /* Number of pyramids to be cached - TODO parameter */);
-    OrthancWSI::OnTheFlyPyramidsCache::InitializeInstance(
+    OrthancWSI::DecodedPyramidCache::InitializeInstance(
       new OrthancWSI::OrthancPyramidFrameFetcher(new OrthancWSI::OrthancPluginConnection(), false /* TODO PARAMETER */),
       10 /* TODO - PARAMETER */,
       256 * 1024 * 1024 /* TODO - PARAMETER */);
@@ -669,7 +669,7 @@
 
   ORTHANC_PLUGINS_API void OrthancPluginFinalize()
   {
-    OrthancWSI::OnTheFlyPyramidsCache::FinalizeInstance();
+    OrthancWSI::DecodedPyramidCache::FinalizeInstance();
     OrthancWSI::DicomPyramidCache::FinalizeInstance();
     OrthancWSI::RawTile::FinalizeTranscoderSemaphore();
   }