QPixmap ImageRegistry::pixmap( const QString& image, const QSize& size, TomahawkUtils::ImageMode mode, float opacity, QColor tint ) { if ( size.width() < 0 || size.height() < 0 ) { Q_ASSERT( false ); return QPixmap(); } QHash< qint64, QPixmap > subsubcache; QHash< int, QHash< qint64, QPixmap > > subcache; if ( s_cache.contains( image ) ) { subcache = s_cache.value( image ); if ( subcache.contains( mode ) ) { subsubcache = subcache.value( mode ); const qint64 ck = cacheKey( size, opacity, tint ); if ( subsubcache.contains( ck ) ) { return subsubcache.value( ck ); } } } // Image not found in cache. Let's load it. QPixmap pixmap; if ( image.toLower().endsWith( ".svg" ) ) { QSvgRenderer svgRenderer( image ); QPixmap p( size.isNull() || size.height() == 0 || size.width() == 0 ? svgRenderer.defaultSize() : size ); p.fill( Qt::transparent ); QPainter pixPainter( &p ); pixPainter.setOpacity( opacity ); svgRenderer.render( &pixPainter ); pixPainter.end(); if ( tint.alpha() > 0 ) p = TomahawkUtils::tinted( p, tint ); pixmap = p; } else pixmap = QPixmap( image ); if ( !pixmap.isNull() ) { switch ( mode ) { case TomahawkUtils::RoundedCorners: pixmap = TomahawkUtils::createRoundedImage( pixmap, size ); break; default: break; } if ( !size.isNull() && pixmap.size() != size ) { if ( size.width() == 0 ) { pixmap = pixmap.scaledToHeight( size.height(), Qt::SmoothTransformation ); } else if ( size.height() == 0 ) { pixmap = pixmap.scaledToWidth( size.width(), Qt::SmoothTransformation ); } else pixmap = pixmap.scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); } putInCache( image, size, mode, opacity, pixmap, tint ); } return pixmap; }
/** * \brief Load the image(s), wraps LoadImage() */ bool MythUIImage::Load(bool allowLoadInBackground, bool forceStat) { d->m_UpdateLock.lockForRead(); QSize bForceSize = m_ForceSize; QString bFilename = m_Filename; bFilename.detach(); d->m_UpdateLock.unlock(); QString filename = bFilename; if (bFilename.isEmpty()) { Clear(); SetRedraw(); return false; } Clear(); // SetRedraw(); // if (!IsVisible(true)) // return false; int w = -1; int h = -1; if (!bForceSize.isNull()) { if (bForceSize.width() != -1) w = bForceSize.width(); if (bForceSize.height() != -1) h = bForceSize.height(); } QString imagelabel; int j = 0; for (int i = m_LowNum; i <= m_HighNum && !m_animatedImage; i++) { if (!m_animatedImage && m_HighNum != m_LowNum && bFilename.contains("%1")) filename = bFilename.arg(i); imagelabel = GenImageLabel(filename, w, h); // Only load in the background if allowed and the image is // not already in our mem cache ImageCacheMode cacheMode = kCacheCheckMemoryOnly; if (forceStat) cacheMode = (ImageCacheMode) ((int)kCacheCheckMemoryOnly | (int)kCacheForceStat); ImageCacheMode cacheMode2 = (!forceStat) ? kCacheNormal : (ImageCacheMode) ((int)kCacheNormal | (int)kCacheForceStat); if ((allowLoadInBackground) && (!GetMythUI()->LoadCacheImage(filename, imagelabel, GetPainter(), cacheMode)) && (!getenv("DISABLETHREADEDMYTHUIIMAGE"))) { VERBOSE(VB_GUI|VB_FILE|VB_EXTRA, LOC + QString( "Load(), spawning thread to load '%1'").arg(filename)); ImageLoadThread *bImgThread = new ImageLoadThread( this, bFilename, filename, i, bForceSize, cacheMode2); GetMythUI()->GetImageThreadPool()->start(bImgThread); } else { // Perform a blocking load VERBOSE(VB_GUI|VB_FILE|VB_EXTRA, LOC + QString( "Load(), loading '%1' in foreground").arg(filename)); QString tmpFilename; if ((filename.startsWith("/")) || (filename.startsWith("http://")) || (filename.startsWith("https://")) || (filename.startsWith("ftp://"))) tmpFilename = filename; MythImageReader imageReader(tmpFilename); if (imageReader.supportsAnimation()) { LoadAnimatedImage( imageReader, filename, bForceSize, cacheMode2); } else { MythImage *image = LoadImage( imageReader, filename, bForceSize, cacheMode2); if (image) { if (bForceSize.isNull()) SetSize(image->size()); m_ImagesLock.lock(); m_Images[j] = image; m_ImagesLock.unlock(); SetRedraw(); d->m_UpdateLock.lockForWrite(); m_LastDisplay = QTime::currentTime(); d->m_UpdateLock.unlock(); } else { m_ImagesLock.lock(); m_Images[j] = NULL; m_ImagesLock.unlock(); } } } ++j; } return true; }
/** * \brief Load an animated image */ bool MythUIImage::LoadAnimatedImage( MythImageReader &imageReader, const QString &imFile, QSize bForceSize, int cacheMode) { bool result = false; m_loadingImagesLock.lock(); // Check to see if the image is being loaded by us in another thread if ((m_loadingImages.contains(imFile)) && (m_loadingImages[imFile] == this)) { VERBOSE(VB_GUI|VB_FILE|VB_EXTRA, LOC + QString( "MythUIImage::LoadAnimatedImage(%1), this " "file is already being loaded by this same MythUIImage in " "another thread.").arg(imFile)); m_loadingImagesLock.unlock(); return result; } // Check to see if the exact same image is being loaded anywhere else while (m_loadingImages.contains(imFile)) m_loadingImagesCond.wait(&m_loadingImagesLock); m_loadingImages[imFile] = this; m_loadingImagesLock.unlock(); QString filename = QString("frame-%1-") + imFile; QString frameFilename; QVector<MythImage *> images; QVector<int> delays; int imageCount = 1; QString imageLabel; int w = -1; int h = -1; if (!bForceSize.isNull()) { if (bForceSize.width() != -1) w = bForceSize.width(); if (bForceSize.height() != -1) h = bForceSize.height(); } while (imageReader.canRead()) { frameFilename = filename.arg(imageCount); imageLabel = GenImageLabel(frameFilename, w, h); MythImage *im = LoadImage( imageReader, frameFilename, bForceSize, (ImageCacheMode) cacheMode); if (!im) break; images.append(im); delays.append(imageReader.nextImageDelay()); imageCount++; } if (images.size()) { m_animatedImage = true; SetImages(images); if ((m_Delay == -1) && (imageReader.supportsAnimation()) && (delays.size())) { SetDelays(delays); } result = true; } m_loadingImagesLock.lock(); m_loadingImages.remove(imFile); m_loadingImagesCond.wakeAll(); m_loadingImagesLock.unlock(); return result; }
/** * \brief Assign a set of MythImages to the widget for animation. * Use is strongly discouraged, use SetFilepattern() instead. * */ void MythUIImage::SetImages(QVector<MythImage *> *images) { Clear(); QWriteLocker updateLocker(&d->m_UpdateLock); QSize aSize = GetFullArea().size(); m_imageProperties.isThemeImage = false; QVector<MythImage *>::iterator it; for (it = images->begin(); it != images->end(); ++it) { MythImage *im = (*it); if (!im) { QMutexLocker locker(&m_ImagesLock); m_Images[m_Images.size()] = im; continue; } im->IncrRef(); QSize forceSize = m_imageProperties.forceSize; if (!forceSize.isNull()) { int w = (forceSize.width() <= 0) ? im->width() : forceSize.width(); int h = (forceSize.height() <= 0) ? im->height() : forceSize.height(); im->Resize(QSize(w, h), m_imageProperties.preserveAspect); } if (m_imageProperties.isReflected && !im->IsReflected()) im->Reflect(m_imageProperties.reflectAxis, m_imageProperties.reflectShear, m_imageProperties.reflectScale, m_imageProperties.reflectLength, m_imageProperties.reflectSpacing); if (m_imageProperties.isGreyscale && !im->isGrayscale()) im->ToGreyscale(); if (m_imageProperties.isOriented && !im->IsOriented()) im->Orientation(m_imageProperties.orientation); m_ImagesLock.lock(); m_Images[m_Images.size()] = im; m_ImagesLock.unlock(); aSize = aSize.expandedTo(im->size()); } SetImageCount(1, m_Images.size()); if (m_imageProperties.forceSize.isNull()) SetSize(aSize); MythRect rect(GetFullArea()); rect.setSize(aSize); SetMinArea(rect); m_CurPos = 0; m_animatedImage = true; m_Initiator = m_EnableInitiator; SetRedraw(); }