Add opacity parameter to image cache

This commit is contained in:
nirvn 2018-12-04 14:29:39 +07:00 committed by Mathieu Pellerin
parent ce5636afed
commit ad4b876866
5 changed files with 50 additions and 23 deletions

View File

@ -35,7 +35,7 @@ QgsImageCache is not usually directly created, but rather accessed through
Constructor for QgsImageCache, with the specified ``parent`` object.
%End
QImage pathAsImage( const QString &path, QSize size, bool keepAspectRatio, bool &fitsInCache /Out/ );
QImage pathAsImage( const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, 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
@ -49,6 +49,8 @@ original raster image size (with no resampling).
If ``keepAspectRatio`` is true, then the original raster aspect ratio will be maintained during
any resampling operations.
An ``opacity`` parameter dictates the opacity of the image.
If the resultant raster was of a sufficiently small size to store in the cache, then ``fitsInCache``
will be set to true.
%End

View File

@ -41,10 +41,11 @@
///@cond PRIVATE
QgsImageCacheEntry::QgsImageCacheEntry( const QString &path, QSize size, const bool keepAspectRatio )
QgsImageCacheEntry::QgsImageCacheEntry( const QString &path, QSize size, const bool keepAspectRatio, const double opacity )
: QgsAbstractContentCacheEntry( path )
, size( size )
, keepAspectRatio( keepAspectRatio )
, opacity( opacity )
{
}
@ -52,7 +53,7 @@ bool QgsImageCacheEntry::isEqual( const QgsAbstractContentCacheEntry *other ) co
{
const QgsImageCacheEntry *otherImage = dynamic_cast< const QgsImageCacheEntry * >( other );
// cheapest checks first!
if ( !otherImage || otherImage->keepAspectRatio != keepAspectRatio || otherImage->size != size || otherImage->path != path )
if ( !otherImage || otherImage->keepAspectRatio != keepAspectRatio || otherImage->size != size || otherImage->path != path || otherImage->opacity != opacity )
return false;
return true;
@ -99,13 +100,13 @@ QgsImageCache::QgsImageCache( QObject *parent )
connect( this, &QgsAbstractContentCacheBase::remoteContentFetched, this, &QgsImageCache::remoteImageFetched );
}
QImage QgsImageCache::pathAsImage( const QString &file, const QSize size, const bool keepAspectRatio, bool &fitsInCache )
QImage QgsImageCache::pathAsImage( const QString &file, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache )
{
QMutexLocker locker( &mMutex );
fitsInCache = true;
QgsImageCacheEntry *currentEntry = findExistingEntry( new QgsImageCacheEntry( file, size, keepAspectRatio ) );
QgsImageCacheEntry *currentEntry = findExistingEntry( new QgsImageCacheEntry( file, size, keepAspectRatio, opacity ) );
QImage result;
@ -115,7 +116,7 @@ QImage QgsImageCache::pathAsImage( const QString &file, const QSize size, const
if ( currentEntry->image.isNull() )
{
long cachedDataSize = 0;
result = renderImage( file, size, keepAspectRatio );
result = renderImage( file, size, keepAspectRatio, opacity );
cachedDataSize += result.width() * result.height() * 32;
if ( cachedDataSize > mMaxCacheSize / 2 )
{
@ -161,7 +162,7 @@ QSize QgsImageCache::originalSize( const QString &path ) const
return QSize();
}
QImage QgsImageCache::renderImage( const QString &path, QSize size, const bool keepAspectRatio ) const
QImage QgsImageCache::renderImage( const QString &path, QSize size, const bool keepAspectRatio, const double opacity ) const
{
QImage im;
// direct read if path is a file -- maybe more efficient than going the bytearray route? (untested!)
@ -211,6 +212,12 @@ QImage QgsImageCache::renderImage( const QString &path, QSize size, const bool k
}
}
if ( !im.hasAlphaChannel() )
im = im.convertToFormat( QImage::Format_ARGB32 );
if ( opacity < 1.0 )
QgsSymbolLayerUtils::multiplyImageOpacity( &im, opacity );
// render image at desired size -- null size means original size
if ( !size.isValid() || size.isNull() || im.size() == size )
return im;

View File

@ -41,12 +41,12 @@ class CORE_EXPORT QgsImageCacheEntry : public QgsAbstractContentCacheEntry
public:
/**
* Constructor for QgsImageCacheEntry, corresponding to the specified image \a path and \a size.
* Constructor for QgsImageCacheEntry, corresponding to the specified image \a path , \a size and \a opacity.
*
* If \a keepAspectRatio is true then the original raster aspect ratio will always be preserved
* when resizing.
*/
QgsImageCacheEntry( const QString &path, QSize size, bool keepAspectRatio ) ;
QgsImageCacheEntry( const QString &path, QSize size, bool keepAspectRatio, double opacity ) ;
//! Rendered image size
QSize size;
@ -54,6 +54,9 @@ class CORE_EXPORT QgsImageCacheEntry : public QgsAbstractContentCacheEntry
//! True if original raster aspect ratio was kept during resizing
bool keepAspectRatio = true;
//! Rendered image opacity
double opacity = 1.0;
//! Rendered, resampled image.
QImage image;
@ -108,10 +111,12 @@ class CORE_EXPORT QgsImageCache : public QgsAbstractContentCache< QgsImageCacheE
* If \a keepAspectRatio is true, then the original raster aspect ratio will be maintained during
* any resampling operations.
*
* An \a opacity parameter dictates the opacity of the image.
*
* If the resultant raster was of a sufficiently small size to store in the cache, then \a fitsInCache
* will be set to true.
*/
QImage pathAsImage( const QString &path, QSize size, bool keepAspectRatio, bool &fitsInCache SIP_OUT );
QImage pathAsImage( const QString &path, const QSize size, const bool keepAspectRatio, const double opacity, bool &fitsInCache SIP_OUT );
/**
* Returns the original size (in pixels) of the image at the specified \a path.
@ -134,7 +139,7 @@ class CORE_EXPORT QgsImageCache : public QgsAbstractContentCache< QgsImageCacheE
private:
QImage renderImage( const QString &path, QSize size, const bool keepAspectRatio ) const;
QImage renderImage( const QString &path, QSize size, const bool keepAspectRatio, const double opacity ) const;
//! SVG content to be rendered if SVG file was not found.
QByteArray mMissingSvg;

File diff suppressed because one or more lines are too long

View File

@ -66,7 +66,7 @@ class TestQgsImageCache(unittest.TestCase):
def testRemoteImage(self):
"""Test fetching remote image."""
url = 'http://localhost:{}/qgis_local_server/sample_image.png'.format(str(TestQgsImageCache.port))
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), True)
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), 1.0, True)
# first should be waiting image
self.assertTrue(self.imageCheck('Remote Image', 'waiting_image', image))
@ -74,7 +74,7 @@ class TestQgsImageCache(unittest.TestCase):
self.waitForFetch()
# second should be correct image
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), True)
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), 1.0, True)
self.assertTrue(self.imageCheck('Remote Image', 'remote_image', image))
self.assertEqual(QgsApplication.imageCache().originalSize(url), QSize(511, 800))
@ -82,7 +82,7 @@ class TestQgsImageCache(unittest.TestCase):
def testRemoteImageMissing(self):
"""Test fetching remote image with bad url"""
url = 'http://localhost:{}/qgis_local_server/xxx.png'.format(str(TestQgsImageCache.port)) # oooo naughty
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), True)
image, in_cache = QgsApplication.imageCache().pathAsImage(url, QSize(100, 100), 1.0, True)
self.assertTrue(self.imageCheck('Remote image missing', 'waiting_image', image))