Skip to content
Permalink
Browse files

[FEATURE][API] Add a content cache for raster images

This new class QgsImageCache is the equivalent of QgsSvgCache
but for raster images.

QgsImageCache stores pre-rendered resampled versions of raster
image files, allowing efficient reuse without incurring the
cost of resampling on every render.

Additionally, it offers the other benefits QgsSvgCache has,
such as thread safety, ability to transparently download remote
images, and support for base64 encoded strings.
  • Loading branch information
nyalldawson authored and nirvn committed Dec 3, 2018
1 parent cdba8f5 commit 84838d1ec6f8499bfb74ca4ecf01fd082517ec98
Showing with 788 additions and 5 deletions.
  1. +0 −1 python/core/auto_generated/qgsabstractcontentcache.sip.in
  2. +11 −0 python/core/auto_generated/qgsapplication.sip.in
  3. +71 −0 python/core/auto_generated/qgsimagecache.sip.in
  4. +1 −0 python/core/core_auto.sip
  5. +1 −1 scripts/spell_check/spelling.dat
  6. +2 −0 src/core/CMakeLists.txt
  7. +2 −3 src/core/qgsabstractcontentcache.h
  8. +8 −0 src/core/qgsapplication.cpp
  9. +12 −0 src/core/qgsapplication.h
  10. +195 −0 src/core/qgsimagecache.cpp
  11. +135 −0 src/core/qgsimagecache.h
  12. +1 −0 tests/src/core/CMakeLists.txt
  13. +237 −0 tests/src/core/testqgsimagecache.cpp
  14. +1 −0 tests/src/python/CMakeLists.txt
  15. +111 −0 tests/src/python/test_qgsimagecache.py
  16. BIN tests/testdata/control_images/image_cache/expected_imagecache_base64/expected_imagecache_base64.png
  17. BIN ...estdata/control_images/image_cache/expected_imagecache_base64/expected_imagecache_base64_mask.png
  18. BIN ...ontrol_images/image_cache/expected_imagecache_changed_after/expected_imagecache_changed_after.png
  19. BIN ...l_images/image_cache/expected_imagecache_changed_after/expected_imagecache_changed_after_mask.png
  20. BIN ...trol_images/image_cache/expected_imagecache_changed_before/expected_imagecache_changed_before.png
  21. BIN ...images/image_cache/expected_imagecache_changed_before/expected_imagecache_changed_before_mask.png
  22. BIN tests/testdata/control_images/image_cache/expected_null_image/expected_null_image.png
  23. BIN tests/testdata/control_images/image_cache/expected_null_image/expected_null_image_mask.png
  24. BIN tests/testdata/control_images/image_cache/expected_remote_image/expected_remote_image.png
  25. BIN tests/testdata/control_images/image_cache/expected_remote_image/expected_remote_image_mask.png
  26. BIN tests/testdata/control_images/image_cache/expected_waiting_image/expected_waiting_image.png
  27. BIN tests/testdata/control_images/image_cache/expected_waiting_image/expected_waiting_image_mask.png
  28. BIN tests/testdata/qgis_local_server/sample_image.png
  29. BIN tests/testdata/sample_image2.png
@@ -33,7 +33,6 @@ Constructor for QgsAbstractContentCacheEntry for an entry relating to the specif
virtual ~QgsAbstractContentCacheEntry();



QString path;

QDateTime fileModified;
@@ -649,7 +649,18 @@ providers that may add items to the browser tree.
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement
within SVG files.

.. seealso:: :py:func:`imageCache`

.. versionadded:: 3.0
%End

static QgsImageCache *imageCache();
%Docstring
Returns the application's image cache, used for caching resampled versions of raster images.

.. seealso:: :py:func:`svgCache`

.. versionadded:: 3.6
%End

static QgsNetworkContentFetcherRegistry *networkContentFetcherRegistry();
@@ -0,0 +1,71 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsimagecache.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/






class QgsImageCache : QgsAbstractContentCacheBase
{
%Docstring
A cache for images derived from raster files.

QgsImageCache stores pre-rendered resampled versions of raster image files, allowing efficient
reuse without incurring the cost of resampling on every render.

QgsImageCache is not usually directly created, but rather accessed through
:py:func:`QgsApplication.imageCache()`

.. versionadded:: 3.6
%End

%TypeHeaderCode
#include "qgsimagecache.h"
%End
public:

QgsImageCache( QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsImageCache, with the specified ``parent`` object.
%End

QImage pathAsImage( const QString &path, QSize size, bool keepAspectRatio, bool &fitsInCache /Out/ );
%Docstring
Returns the specified ``path`` rendered as an image. If possible, a pre-existing cached
version of the image will be used. If not, the image is fetched and resampled to the desired
size, and then the result cached for subsequent lookups.

``path`` may be a local file, remote (HTTP) url, or a base 64 encoded string (with a "base64:" prefix).

The ``size`` parameter dictates the target size of the image. An invalid size indicates the
original raster image size (with no resampling).

If ``keepAspectRatio`` is true, then the original raster aspect ratio will be maintained during
any resampling operations.

If the resultant raster was of a sufficiently small size to store in the cache, then ``fitsInCache``
will be set to true.
%End

signals:

void remoteImageFetched( const QString &url );
%Docstring
Emitted when the cache has finished retrieving an image file from a remote ``url``.
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsimagecache.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -332,6 +332,7 @@
%Include auto_generated/qgsgeometryvalidator.sip
%Include auto_generated/qgsgml.sip
%Include auto_generated/qgsgmlschema.sip
%Include auto_generated/qgsimagecache.sip
%Include auto_generated/qgsmaplayer.sip
%Include auto_generated/qgsmaplayerlegend.sip
%Include auto_generated/qgsmaplayermodel.sip
@@ -6554,7 +6554,7 @@ stength:strength
steriods:steroids
sterotypes:stereotypes
stilus:stylus
stingent:stringent
stingent:stringent:*
stiring:stirring
stirng:string
stirngs:strings
@@ -214,6 +214,7 @@ SET(QGIS_CORE_SRCS
qgshistogram.cpp
qgshstoreutils.cpp
qgshtmlutils.cpp
qgsimagecache.cpp
qgsinterval.cpp
qgsjsonutils.cpp
qgslabelfeature.cpp
@@ -616,6 +617,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsgeometryvalidator.h
qgsgml.h
qgsgmlschema.h
qgsimagecache.h
qgsmaplayer.h
qgsmaplayerlegend.h
qgsmaplayermodel.h
@@ -52,8 +52,6 @@ class CORE_EXPORT QgsAbstractContentCacheEntry

virtual ~QgsAbstractContentCacheEntry() = default;

QgsAbstractContentCacheEntry() = delete;

//! QgsAbstractContentCacheEntry cannot be copied.
QgsAbstractContentCacheEntry( const QgsAbstractContentCacheEntry &rh ) = delete;
//! QgsAbstractContentCacheEntry cannot be copied.
@@ -176,7 +174,7 @@ class CORE_EXPORT QgsAbstractContentCacheBase: public QObject
#ifndef SIP_RUN

/**
* \class QgsAbstractContentCacheBase
* \class QgsAbstractContentCache
* \ingroup core
*
* Abstract base class for file content caches, such as SVG or raster image caches.
@@ -560,6 +558,7 @@ class CORE_EXPORT QgsAbstractContentCache : public QgsAbstractContentCacheBase
QString mTypeString;

friend class TestQgsSvgCache;
friend class TestQgsImageCache;
};

#endif
@@ -30,6 +30,7 @@
#include "qgstaskmanager.h"
#include "qgsfieldformatterregistry.h"
#include "qgssvgcache.h"
#include "qgsimagecache.h"
#include "qgscolorschemeregistry.h"
#include "qgspainteffectregistry.h"
#include "qgsprojectstorageregistry.h"
@@ -1772,6 +1773,11 @@ QgsSvgCache *QgsApplication::svgCache()
return members()->mSvgCache;
}

QgsImageCache *QgsApplication::imageCache()
{
return members()->mImageCache;
}

QgsNetworkContentFetcherRegistry *QgsApplication::networkContentFetcherRegistry()
{
return members()->mNetworkContentFetcherRegistry;
@@ -1842,6 +1848,7 @@ QgsApplication::ApplicationMembers::ApplicationMembers()
mActionScopeRegistry = new QgsActionScopeRegistry();
mFieldFormatterRegistry = new QgsFieldFormatterRegistry();
mSvgCache = new QgsSvgCache();
mImageCache = new QgsImageCache();
mColorSchemeRegistry = new QgsColorSchemeRegistry();
mPaintEffectRegistry = new QgsPaintEffectRegistry();
mSymbolLayerRegistry = new QgsSymbolLayerRegistry();
@@ -1878,6 +1885,7 @@ QgsApplication::ApplicationMembers::~ApplicationMembers()
delete mRasterRendererRegistry;
delete mRendererRegistry;
delete mSvgCache;
delete mImageCache;
delete mSymbolLayerRegistry;
delete mTaskManager;
delete mNetworkContentFetcherRegistry;
@@ -34,6 +34,7 @@ class QgsPaintEffectRegistry;
class QgsProjectStorageRegistry;
class QgsRendererRegistry;
class QgsSvgCache;
class QgsImageCache;
class QgsSymbolLayerRegistry;
class QgsRasterRendererRegistry;
class QgsGpsConnectionRegistry;
@@ -595,10 +596,20 @@ class CORE_EXPORT QgsApplication : public QApplication
/**
* Returns the application's SVG cache, used for caching SVG images and handling parameter replacement
* within SVG files.
*
* \see imageCache()
* \since QGIS 3.0
*/
static QgsSvgCache *svgCache();

/**
* Returns the application's image cache, used for caching resampled versions of raster images.
*
* \see svgCache()
* \since QGIS 3.6
*/
static QgsImageCache *imageCache();

/**
* Returns the application's network content registry used for fetching temporary files during QGIS session
* \since QGIS 3.2
@@ -867,6 +878,7 @@ class CORE_EXPORT QgsApplication : public QApplication
QgsRendererRegistry *mRendererRegistry = nullptr;
QgsRuntimeProfiler *mProfiler = nullptr;
QgsSvgCache *mSvgCache = nullptr;
QgsImageCache *mImageCache = nullptr;
QgsSymbolLayerRegistry *mSymbolLayerRegistry = nullptr;
QgsTaskManager *mTaskManager = nullptr;
QgsLayoutItemRegistry *mLayoutItemRegistry = nullptr;

0 comments on commit 84838d1

Please sign in to comment.
You can’t perform that action at this time.