Skip to content

Commit

Permalink
Add opacity parameter to image cache
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Dec 5, 2018
1 parent ce5636a commit ad4b876
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 23 deletions.
4 changes: 3 additions & 1 deletion python/core/auto_generated/qgsimagecache.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
19 changes: 13 additions & 6 deletions src/core/qgsimagecache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@

///@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 )
{
}

bool QgsImageCacheEntry::isEqual( const QgsAbstractContentCacheEntry *other ) const
{
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;
Expand Down Expand Up @@ -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;

Expand All @@ -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 )
{
Expand Down Expand Up @@ -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!)
Expand Down Expand Up @@ -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 );

This comment has been minimized.

Copy link
@nyalldawson

nyalldawson Dec 5, 2018

Collaborator

@nirvn FYI - this method is very inefficient. You should use QgsImageOperation::multiplyOpacity instead.


// render image at desired size -- null size means original size
if ( !size.isValid() || size.isNull() || im.size() == size )
return im;
Expand Down
13 changes: 9 additions & 4 deletions src/core/qgsimagecache.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,22 @@ 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;

//! 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;

Expand Down Expand Up @@ -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.
Expand All @@ -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;
Expand Down
Loading

0 comments on commit ad4b876

Please sign in to comment.