Пример #1
0
    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;
    }
Пример #2
0
/**
*  \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;
}
Пример #3
0
/**
 *  \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;
}
Пример #4
0
/**
*  \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;
}
Пример #5
0
/**
 *  \brief Generates a unique identifying string for this image which is used
 *         as a key in the image cache.
 */
QString MythUIImage::GenImageLabel(int w, int h) const
{
    QReadLocker updateLocker(&d->m_UpdateLock);
    return GenImageLabel(m_Filename, w, h);
}