static MythImage *LoadImage(MythPainter *painter, // Must be a copy for thread safety ImageProperties imProps, ImageCacheMode cacheMode, // Included only to check address, could be // replaced by generating a unique value for // each MythUIImage object? const MythUIImage *parent, bool &aborted, MythImageReader *imageReader = NULL) { QString cacheKey = GenImageLabel(imProps); if (!PreLoad(cacheKey, parent)) { aborted = true; return NULL; } QString filename = imProps.filename; MythImage *image = NULL; bool bResize = false; bool bFoundInCache = false; int w = -1; int h = -1; if (!imProps.forceSize.isNull()) { if (imProps.forceSize.width() != -1) w = imProps.forceSize.width(); if (imProps.forceSize.height() != -1) h = imProps.forceSize.height(); bResize = true; } if (!imageReader) { image = GetMythUI()->LoadCacheImage(filename, cacheKey, painter, cacheMode); } if (image) { if (VERBOSE_LEVEL_CHECK(VB_GUI | VB_FILE, LOG_INFO)) { image->IncrRef(); int cnt = image->DecrRef(); LOG(VB_GUI | VB_FILE, LOG_INFO, QString("ImageLoader::LoadImage(%1) Found in cache, " "RefCount = %2") .arg(cacheKey).arg(cnt)); } if (imProps.isReflected) image->setIsReflected(true); if (imProps.isOriented) image->setIsOriented(true); bFoundInCache = true; } else { LOG(VB_GUI | VB_FILE, LOG_INFO, QString("ImageLoader::LoadImage(%1) NOT Found in cache. " "Loading Directly").arg(cacheKey)); image = painter->GetFormatImage(); bool ok = false; if (imageReader) ok = image->Load(imageReader); else ok = image->Load(filename); if (!ok) { image->DecrRef(); image = NULL; } } if (image && image->isNull()) { LOG(VB_GUI | VB_FILE, LOG_INFO, QString("ImageLoader::LoadImage(%1) Image is NULL") .arg(filename)); image->DecrRef(); image = NULL; } if (image && !bFoundInCache) { if (imProps.isReflected) image->Reflect(imProps.reflectAxis, imProps.reflectShear, imProps.reflectScale, imProps.reflectLength, imProps.reflectSpacing); if (imProps.isGreyscale) image->ToGreyscale(); if (imProps.isOriented) image->Orientation(imProps.orientation); // Even if an explicit size wasn't defined this image may still need // to be scaled because of a difference between the theme resolution // and the screen resolution. We want to avoid scaling twice. if (!bResize && imProps.isThemeImage) { float wmult; // Width multipler float hmult; // Height multipler GetMythUI()->GetScreenSettings(wmult, hmult); if (wmult != 1.0f || hmult != 1.0f) { w = image->size().width() * wmult; h = image->size().height() * hmult; bResize = true; } } if (bResize) image->Resize(QSize(w, h), imProps.preserveAspect); if (imProps.isMasked) { QRect imageArea = image->rect(); QRect maskArea = imProps.GetMaskImageRect(); // Crop the mask to the image int x = 0; int y = 0; if (maskArea.width() > imageArea.width()) x = (maskArea.width() - imageArea.width()) / 2; if (maskArea.height() > imageArea.height()) y = (maskArea.height() - imageArea.height()) / 2; if (x > 0 || y > 0) imageArea.translate(x, y); QImage mask = imProps.GetMaskImageSubset(imageArea); image->setAlphaChannel(mask.alphaChannel()); } if (!imageReader) GetMythUI()->CacheImage(cacheKey, image); } if (image) image->SetChanged(); PostLoad(cacheKey); return image; }
/** * \copydoc MythUIType::DrawSelf() */ void MythUIImage::DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect) { m_ImagesLock.lock(); if (m_Images.size() > 0) { d->m_UpdateLock.lockForWrite(); if (m_CurPos >= (uint)m_Images.size()) m_CurPos = 0; if (!m_Images[m_CurPos]) { unsigned int origPos = m_CurPos; m_CurPos++; while (!m_Images[m_CurPos] && m_CurPos != origPos) { m_CurPos++; if (m_CurPos >= (uint)m_Images.size()) m_CurPos = 0; } } QRect area = GetArea().toQRect(); area.translate(xoffset, yoffset); int alpha = CalcAlpha(alphaMod); MythImage *currentImage = m_Images[m_CurPos]; if (currentImage) currentImage->UpRef(); m_ImagesLock.unlock(); d->m_UpdateLock.unlock(); if (!currentImage) return; d->m_UpdateLock.lockForRead(); QRect currentImageArea = currentImage->rect(); if (!m_ForceSize.isNull()) area.setSize(area.size().expandedTo(currentImage->size())); // Centre image in available space int x = 0; int y = 0; if (area.width() > currentImageArea.width()) x = (area.width() - currentImageArea.width()) / 2; if (area.height() > currentImageArea.height()) y = (area.height() - currentImageArea.height()) / 2; if (x > 0 || y > 0) area.translate(x,y); QRect srcRect; m_cropRect.CalculateArea(GetArea()); if (!m_cropRect.isEmpty()) srcRect = m_cropRect.toQRect(); else srcRect = currentImageArea; p->DrawImage(area, currentImage, srcRect, alpha); currentImage->DownRef(); d->m_UpdateLock.unlock(); } else m_ImagesLock.unlock(); }
/** * \copydoc MythUIType::DrawSelf() */ void MythUIImage::DrawSelf(MythPainter *p, int xoffset, int yoffset, int alphaMod, QRect clipRect) { m_ImagesLock.lock(); if (m_Images.size() > 0) { d->m_UpdateLock.lockForWrite(); if (m_CurPos >= (uint)m_Images.size()) m_CurPos = 0; if (!m_Images[m_CurPos]) { unsigned int origPos = m_CurPos; m_CurPos++; while (!m_Images[m_CurPos] && m_CurPos != origPos) { m_CurPos++; if (m_CurPos >= (uint)m_Images.size()) m_CurPos = 0; } } QRect area = GetArea().toQRect(); area.translate(xoffset, yoffset); int alpha = CalcAlpha(alphaMod); MythImage *currentImage = m_Images[m_CurPos]; if (currentImage) currentImage->IncrRef(); m_ImagesLock.unlock(); d->m_UpdateLock.unlock(); if (!currentImage) return; d->m_UpdateLock.lockForRead(); QRect currentImageArea = currentImage->rect(); if (!m_imageProperties.forceSize.isNull()) area.setSize(area.size().expandedTo(currentImage->size())); // Centre image in available space, accounting for zoom int x = 0, y = 0; QRect visibleImage = m_Effects.GetExtent(currentImageArea.size()); if (area.width() > visibleImage.width()) x = area.width() / 2 + visibleImage.topLeft().x(); if (area.height() > visibleImage.height()) y = area.height() / 2 + visibleImage.topLeft().y(); if ((x > 0 || y > 0)) area.translate(x, y); QRect srcRect; m_imageProperties.cropRect.CalculateArea(GetFullArea()); if (!m_imageProperties.cropRect.isEmpty()) srcRect = m_imageProperties.cropRect.toQRect(); else srcRect = currentImageArea; p->DrawImage(area, currentImage, srcRect, alpha); currentImage->DecrRef(); d->m_UpdateLock.unlock(); } else m_ImagesLock.unlock(); }
/** * \brief Load an image */ MythImage *MythUIImage::LoadImage( MythImageReader &imageReader, const QString &imFile, QSize bForceSize, int cacheMode) { QString filename = imFile; m_loadingImagesLock.lock(); // Check to see if the image is being loaded by us in another thread if ((m_loadingImages.contains(filename)) && (m_loadingImages[filename] == this)) { VERBOSE(VB_GUI|VB_FILE|VB_EXTRA, LOC + QString( "MythUIImage::LoadImage(%1), this " "file is already being loaded by this same MythUIImage in " "another thread.").arg(filename)); m_loadingImagesLock.unlock(); return NULL; } // Check to see if the exact same image is being loaded anywhere else while (m_loadingImages.contains(filename)) m_loadingImagesCond.wait(&m_loadingImagesLock); m_loadingImages[filename] = this; m_loadingImagesLock.unlock(); VERBOSE(VB_GUI|VB_FILE, LOC + QString("LoadImage(%2) Object %3") .arg(filename).arg(objectName())); MythImage *image = NULL; bool bForceResize = false; bool bFoundInCache = false; 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(); bForceResize = true; } imagelabel = GenImageLabel(filename, w, h); if (!imageReader.supportsAnimation()) { image = GetMythUI()->LoadCacheImage( filename, imagelabel, GetPainter(), (ImageCacheMode) cacheMode); } if (image) { image->UpRef(); VERBOSE(VB_GUI|VB_FILE, LOC + QString("LoadImage found in cache :%1: RefCount = %2") .arg(imagelabel).arg(image->RefCount())); if (m_isReflected) image->setIsReflected(true); bFoundInCache = true; } else { VERBOSE(VB_GUI|VB_FILE, LOC + QString("LoadImage Not Found in cache. " "Loading Directly :%1:").arg(filename)); image = GetPainter()->GetFormatImage(); image->UpRef(); bool ok = false; if (imageReader.supportsAnimation()) ok = image->Load(imageReader); else ok = image->Load(filename); if (!ok) { image->DownRef(); m_loadingImagesLock.lock(); m_loadingImages.remove(filename); m_loadingImagesCond.wakeAll(); m_loadingImagesLock.unlock(); return NULL; } } if (!bFoundInCache) { if (bForceResize) image->Resize(QSize(w, h), m_preserveAspect); if (m_isMasked) { QRect imageArea = image->rect(); QRect maskArea = m_maskImage->rect(); // Crop the mask to the image int x = 0; int y = 0; if (maskArea.width() > imageArea.width()) x = (maskArea.width() - imageArea.width()) / 2; if (maskArea.height() > imageArea.height()) y = (maskArea.height() - imageArea.height()) / 2; if (x > 0 || y > 0) imageArea.translate(x,y); d->m_UpdateLock.lockForWrite(); QImage mask = m_maskImage->copy(imageArea); d->m_UpdateLock.unlock(); image->setAlphaChannel(mask.alphaChannel()); } if (m_isReflected) image->Reflect(m_reflectAxis, m_reflectShear, m_reflectScale, m_reflectLength, m_reflectSpacing); if (m_isGreyscale) image->ToGreyscale(); if (!imageReader.supportsAnimation()) GetMythUI()->CacheImage(imagelabel, image); } if (image->isNull()) { VERBOSE(VB_GUI|VB_FILE, LOC + QString("LoadImage Image is NULL :%1:") .arg(filename)); image->DownRef(); Reset(); m_loadingImagesLock.lock(); m_loadingImages.remove(filename); m_loadingImagesCond.wakeAll(); m_loadingImagesLock.unlock(); return NULL; } image->SetChanged(); m_loadingImagesLock.lock(); m_loadingImages.remove(filename); m_loadingImagesCond.wakeAll(); m_loadingImagesLock.unlock(); return image; }