示例#1
0
文件: webpage.cpp 项目: Cougar/mythtv
void WebPage::slotIconChanged(void)
{
    QIcon icon = m_browser->GetIcon();

    if (icon.isNull())
    {
        //FIXME use a default icon here?
        m_listItem->setImage(NULL);
    }
    else
    {
        if (m_listItem)
        {
            QPixmap pixmap = icon.pixmap(32, 32);
            QImage image = pixmap.toImage();
            image = image.scaled(
                QSize(32,32), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
            MythImage *mimage = GetMythPainter()->GetFormatImage();
            mimage->Assign(image);

            m_listItem->setImage(mimage);
        }
    }

    m_parent->m_pageList->Refresh();
}
示例#2
0
void ZMEvents::eventVisible(MythUIButtonListItem *item)
{
    if (!item)
        return;

    if (item->HasImage())
        return;

    Event *event = qVariantValue<Event*> (item->GetData());

    if (event)
    {
        QImage image;
        if (ZMClient *zm = ZMClient::get())
        {
            zm->getAnalyseFrame(event, 0, image);
            if (!image.isNull())
            {
                MythImage *mimage = GetMythPainter()->GetFormatImage();
                mimage->Assign(image);
                item->SetImage(mimage);
                mimage->SetChanged();
                mimage->DecrRef();
            }
        }
    }
}
示例#3
0
文件: mhi.cpp 项目: Olti/mythtv
// Called by the video player to redraw the image.
void MHIContext::UpdateOSD(InteractiveScreen *osdWindow,
                           MythPainter *osdPainter)
{
    if (!osdWindow || !osdPainter)
        return;

    QMutexLocker locker(&m_display_lock);
    m_updated = false;
    osdWindow->DeleteAllChildren();
    // Copy all the display items into the display.
    list<MHIImageData*>::iterator it = m_display.begin();
    for (int count = 0; it != m_display.end(); ++it, count++)
    {
        MHIImageData *data = *it;
        MythImage* image = osdPainter->GetFormatImage();
        if (!image)
            continue;

        image->Assign(data->m_image);
        MythUIImage *uiimage = new MythUIImage(osdWindow, QString("itv%1")
                                               .arg(count));
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(data->m_x, data->m_y,
                             data->m_image.width(), data->m_image.height()));
        }
        image->DecrRef();
    }
    osdWindow->OptimiseDisplayedArea();
    // N.B. bypasses OSD class hence no expiry set
    osdWindow->SetVisible(true);
}
示例#4
0
void SubtitleScreen::AddScaledImage(QImage &img, QRect &pos)
{
    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;

    QRect scaled = vo->GetImageRect(pos);
    if (scaled.size() != pos.size())
    {
        img = img.scaled(scaled.width(), scaled.height(),
                         Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }

    MythPainter *osd_painter = vo->GetOSDPainter();
    MythImage* image = NULL;
    if (osd_painter)
         image = osd_painter->GetFormatImage();

    if (image)
    {
        image->Assign(img);
        MythUIImage *uiimage = new MythUIImage(this, "dvd_button");
        if (uiimage)
        {
            m_refreshArea = true;
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(scaled));
        }
    }
}
示例#5
0
MythImage *AudioOutputGraph::GetImage(int64_t timecode) const
{
    QMutexLocker lock(&m_mutex);
    Buffer::range_t avail = m_buffer->Avail(timecode);

    LOG(VB_PLAYBACK, LOG_INFO, LOC +
        QString("(%1) using [%2..%3] avail [%4..%5]")
        .arg(timecode).arg(avail.first).arg(avail.second)
        .arg(m_buffer->First()).arg(m_buffer->Next()) );

    const int width = m_buffer->Samples(avail);
    if (width <= 0)
        return nullptr;

    const unsigned range = 1U << m_buffer->BitsPerChannel();
    const double threshold = 20 * log10(1.0 / range); // 16bit=-96.3296dB => ~6dB/bit
    const int height = (int)-ceil(threshold); // 96
    if (height <= 0)
        return nullptr;

    QImage image(width, height, QImage::Format_ARGB32);
    image.fill(0);

    const int channels = m_buffer->Channels();

    // Assume signed 16 bit/sample
    const int16_t *p = m_buffer->Data16(avail);

    for (int x = 0; x < width; ++x)
    {
        int left = p[0];
        int right = channels > 1 ? p[1] : left;
        p += channels;

        unsigned avg = qAbs(left) + qAbs(right);
        double db = 20 * log10( (double)(avg ? avg : 1) / range);

        int idb = (int)ceil(db);
        QRgb rgb = idb <= m_dBsilence ? qRgb(255, 255, 255)
                 : idb <= m_dBquiet   ? qRgb(  0, 255, 255)
                 : idb <= m_dBLoud    ? qRgb(  0, 255,   0)
                 : idb <= m_dbMax     ? qRgb(255, 255,   0)
                 :                      qRgb(255,   0,   0);

        int v = height - (int)(height * (db / threshold));
        if (v >= height)
            v = height - 1;
        else if (v < 0)
            v = 0;

        for (int y = 0; y <= v; ++y)
            image.setPixel(x, height - 1 - y, rgb);
    }

    MythImage *mi = new MythImage(m_painter);
    mi->Assign(image);
    return mi;
}
MythImage* MythQImagePainter::GetImageFromRect(const QSize &size, int radius,
                                               bool drawFill,
                                               const QColor &fillColor,
                                               bool drawLine,
                                               int lineWidth,
                                               const QColor &lineColor)
{
    if (size.width() <= 0 || size.height() <= 0)
        return NULL;

    QString incoming = QString("RECT") + QString::number(size.width()) +
                       QString::number(size.height()) +
                       QString::number(radius) + QString::number(drawFill) +
                       QString::number(fillColor.rgba()) +
                       QString::number(drawLine) + QString::number(lineWidth) +
                       QString::number(lineColor.rgba());

    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        return m_StringToImageMap[incoming];
    }

    QImage image(QSize(size.width(), size.height()), QImage::Format_ARGB32);
    image.fill(0x00000000);
    QPainter painter(&image);
    painter.setRenderHint(QPainter::Antialiasing);

    if (drawLine)
        painter.setPen(QPen(lineColor, lineWidth));
    else
        painter.setPen(QPen(Qt::NoPen));

    if (drawFill)
        painter.setBrush(QBrush(fillColor));
    else
        painter.setBrush(QBrush(Qt::NoBrush));

    if ((size.width() / 2) < radius)
        radius = size.width() / 2;

    if ((size.height() / 2) < radius)
        radius = size.height() / 2;

    QRect r(lineWidth / 2, lineWidth / 2, size.width() - lineWidth,
            size.height() - lineWidth);
    painter.drawRoundedRect(r, (qreal)radius, qreal(radius));
    painter.end();

    MythImage *im = GetFormatImage();
    im->Assign(image);
    m_StringToImageMap[incoming] = im;
    m_StringExpireList.push_back(incoming);
    ExpireImages(MAX_CACHE_ITEMS);
    return im;
}
示例#7
0
void Player::updateFrame(const unsigned char* buffer)
{
    QImage image(buffer, m_monitor.width, m_monitor.height, QImage::Format_RGB888);

    MythImage *img = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
    img->Assign(image);
    m_frameImage->SetImage(img);
    img->DecrRef();
}
示例#8
0
void ThumbFinder::updatePositionBar(int64_t frame)
{
    if (!m_positionImage)
        return;

    QSize size = m_positionImage->GetArea().size();
    QPixmap *pixmap = new QPixmap(size.width(), size.height());

    QPainter p(pixmap);
    QBrush brush(Qt::green);

    p.setBrush(brush);
    p.setPen(Qt::NoPen);
    p.fillRect(0, 0, size.width(), size.height(), brush);

    frm_dir_map_t::const_iterator it;

    brush.setColor(Qt::red);
    double startdelta, enddelta;

    for (it = m_deleteMap.begin(); it != m_deleteMap.end(); ++it)
    {
        if (it.key() != 0)
            startdelta = (m_archiveItem->duration * m_fps) / it.key();
        else
            startdelta = size.width();

        ++it;
        if (it == m_deleteMap.end())
        {
            LOG(VB_GENERAL, LOG_ERR, "ThumbFinder: found a start cut but no cut end");
            break;
        }

        if (it.key() != 0)
            enddelta = (m_archiveItem->duration * m_fps) / it.key();
        else
            enddelta = size.width();
        int start = (int) (size.width() / startdelta);
        int end = (int) (size.width() / enddelta);
        p.fillRect(start - 1, 0, end - start, size.height(), brush);
    }

    if (frame == 0)
        frame = 1;
    brush.setColor(Qt::yellow);
    int pos = (int) (size.width() / ((m_archiveItem->duration * m_fps) / frame));
    p.fillRect(pos, 0, 3, size.height(), brush);

    MythImage *image = GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
    image->Assign(*pixmap);
    m_positionImage->SetImage(image);

    p.end();
    delete pixmap;
}
示例#9
0
void TeletextScreen::OptimiseDisplayedArea(void)
{
    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;
    MythPainter *osd_painter = vo->GetOSDPainter();
    if (!osd_painter)
        return;

    QHashIterator<int, QImage*> it(m_rowImages);
    while (it.hasNext())
    {
        it.next();
        MythImage* image = osd_painter->GetFormatImage();
        if (!image || !it.value())
            continue;

        int row = it.key();
        image->Assign(*(it.value()));
        MythUIImage *uiimage = new MythUIImage(this, QString("ttrow%1")
                                                        .arg(row));
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(0, row * m_rowHeight,
                                      m_safeArea.width(), m_rowHeight * 2));
        }
    }

    QRegion visible;
    QListIterator<MythUIType *> i(m_ChildrenList);
    while (i.hasNext())
    {
        MythUIType *img = i.next();
        visible = visible.united(img->GetArea());
    }

    if (visible.isEmpty())
        return;

    QRect bounding  = visible.boundingRect();
    bounding = bounding.translated(m_safeArea.topLeft());
    bounding = m_safeArea.intersected(bounding);
    int left = m_safeArea.left() - bounding.left();
    int top  = m_safeArea.top()  - bounding.top();
    SetArea(MythRect(bounding));

    i.toFront();;
    while (i.hasNext())
    {
        MythUIType *img = i.next();
        img->SetArea(img->GetArea().translated(left, top));
    }
}
示例#10
0
void ZMEvents::eventChanged(MythUIButtonListItem *item)
{
    (void) item;

    if (m_eventNoText)
    {
        if (m_eventGrid->GetCount() > 0)
            m_eventNoText->SetText(QString("%1/%2")
                                   .arg(m_eventGrid->GetCurrentPos() + 1).arg(m_eventGrid->GetCount()));
        else
            m_eventNoText->SetText("0/0");
    }

    // update the images for all the visible items
    for (int x = m_eventGrid->GetCurrentPos() - m_eventGrid->GetVisibleCount();
            x < m_eventGrid->GetCurrentPos() + (int)m_eventGrid->GetVisibleCount(); x++)
    {
        if (x < 0 || x > (int)m_eventGrid->GetCount() - 1)
            continue;

        MythUIButtonListItem *gridItem = m_eventGrid->GetItemAt(x);
        if (gridItem && !gridItem->getImage())
        {
            if (x < 0 || x > (int)m_eventList->size() - 1)
                continue;

            Event *event = m_eventList->at(x);
            if (event)
            {
                QImage image;
                if (class ZMClient *zm = ZMClient::get())
                {
                    zm->getAnalyseFrame(event->monitorID,
                                        event->eventID,
                                        0, image);
                    if (!image.isNull())
                    {
                        MythImage *mimage = GetMythPainter()->GetFormatImage();
                        mimage->Assign(image);
                        gridItem->setImage(mimage);
                        mimage->SetChanged();
                    }
                }
            }
        }
    }
}
示例#11
0
bool ThumbFinder::getFrameImage(bool needKeyFrame, int64_t requiredPTS)
{
    AVPacket pkt;
    AVFrame orig;
    AVFrame retbuf;
    memset(&orig, 0, sizeof(AVFrame));
    memset(&retbuf, 0, sizeof(AVFrame));

    av_init_packet(&pkt);

    int frameFinished = 0;
    int keyFrame;
    int frameCount = 0;
    bool gotKeyFrame = false;

    while (av_read_frame(m_inputFC, &pkt) >= 0 && !frameFinished)
    {
        if (pkt.stream_index == m_videostream)
        {
            frameCount++;

            keyFrame = pkt.flags & AV_PKT_FLAG_KEY;

            if (m_startPTS == -1 && pkt.dts != AV_NOPTS_VALUE)
            {
                m_startPTS = pkt.dts;
                m_frameTime = pkt.duration;
            }

            if (keyFrame)
                gotKeyFrame = true;

            if (!gotKeyFrame && needKeyFrame)
            {
                av_packet_unref(&pkt);
                continue;
            }

            if (m_firstIFramePTS == -1)
                m_firstIFramePTS = pkt.dts;

            av_frame_unref(m_frame);
            frameFinished = 0;
            int ret = avcodec_receive_frame(m_codecCtx, m_frame);
            if (ret == 0)
                frameFinished = 1;
            if (ret == 0 || ret == AVERROR(EAGAIN))
                ret = avcodec_send_packet(m_codecCtx, &pkt);
            if (requiredPTS != -1 && pkt.dts != AV_NOPTS_VALUE && pkt.dts < requiredPTS)
                frameFinished = false;

            m_currentPTS = pkt.dts;
        }

        av_packet_unref(&pkt);
    }

    if (frameFinished)
    {
        av_image_fill_arrays(retbuf.data, retbuf.linesize, m_outputbuf,
            AV_PIX_FMT_RGB32, m_frameWidth, m_frameHeight, IMAGE_ALIGN);
        AVFrame *tmp = m_frame;

        m_deinterlacer->DeinterlaceSingle(tmp, tmp);

        m_copy.Copy(&retbuf, AV_PIX_FMT_RGB32, tmp, m_codecCtx->pix_fmt,
                    m_frameWidth, m_frameHeight);

        QImage img(m_outputbuf, m_frameWidth, m_frameHeight,
                   QImage::Format_RGB32);

        QByteArray ffile = m_frameFile.toLocal8Bit();
        if (!img.save(ffile.constData(), "JPEG"))
        {
            LOG(VB_GENERAL, LOG_ERR, "Failed to save thumb: " + m_frameFile);
        }

        if (m_updateFrame)
        {
            MythImage *mimage =
                GetMythMainWindow()->GetCurrentPainter()->GetFormatImage();
            mimage->Assign(img);
            m_frameImage->SetImage(mimage);
            mimage->DecrRef();
        }

        updateCurrentPos();
    }

    return true;
}
示例#12
0
void BDOverlayScreen::DisplayBDOverlay(BDOverlay *overlay)
{
    if (!overlay || !m_player)
        return;

    if (!overlay->m_data)
    {
        m_overlayArea = overlay->m_position;
        SetArea(MythRect(m_overlayArea));
        DeleteAllChildren();
        m_overlayMap.clear();
        SetRedraw();
        LOG(VB_PLAYBACK, LOG_INFO, LOC +
            QString("Initialised Size: %1x%2 (%3+%4) Plane: %5 Pts: %6")
                .arg(overlay->m_position.width())
                .arg(overlay->m_position.height())
                .arg(overlay->m_position.left())
                .arg(overlay->m_position.top())
                .arg(overlay->m_plane)
                .arg(overlay->m_pts));
        BDOverlay::DeleteOverlay(overlay);
        return;
    }

    if (!m_overlayArea.isValid())
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "Error: Overlay image submitted before initialisation.");
    }

    VideoOutput *vo = m_player->GetVideoOutput();
    if (!vo)
        return;

    QRect   rect = overlay->m_position;
    QString hash = QString("%1+%2+%3x%4")
                    .arg(rect.left()).arg(rect.top())
                    .arg(rect.width()).arg(rect.height());

    // remove if we already have this overlay
    if (m_overlayMap.contains(hash))
    {
        LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Removing %1 (%2 left)")
            .arg(hash).arg(m_overlayMap.size()));
        MythUIImage *old = m_overlayMap.take(hash);
        DeleteChild(old);
    }

    // convert the overlay palette to ARGB
    uint32_t *origpalette = (uint32_t *)(overlay->m_palette);
    QVector<unsigned int> palette;
    for (int i = 0; i < 256; i++)
    {
        int y  = (origpalette[i] >> 0) & 0xff;
        int cr = (origpalette[i] >> 8) & 0xff;
        int cb = (origpalette[i] >> 16) & 0xff;
        int a  = (origpalette[i] >> 24) & 0xff;
        int r  = int(y + 1.4022 * (cr - 128));
        int b  = int(y + 1.7710 * (cb - 128));
        int g  = int(1.7047 * y - (0.1952 * b) - (0.5647 * r));
        if (r < 0) r = 0;
        if (g < 0) g = 0;
        if (b < 0) b = 0;
        if (r > 0xff) r = 0xff;
        if (g > 0xff) g = 0xff;
        if (b > 0xff) b = 0xff;
        palette.push_back((a << 24) | (r << 16) | (g << 8) | b);
    }

    // convert the image to QImage
    QImage img(rect.size(), QImage::Format_Indexed8);
    memcpy(img.bits(), overlay->m_data, rect.width() * rect.height());
    img.setColorTable(palette);
    img.convertToFormat(QImage::Format_ARGB32);

    // add to screen
    QRect scaled = vo->GetImageRect(rect);
    if (scaled.size() != rect.size())
    {
        img = img.scaled(scaled.width(), scaled.height(),
                         Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }

    MythPainter *osd_painter = vo->GetOSDPainter();
    MythImage* image = NULL;
    if (osd_painter)
         image = osd_painter->GetFormatImage();

    if (image)
    {
        image->Assign(img);
        MythUIImage *uiimage = new MythUIImage(this, "bdoverlay");
        if (uiimage)
        {
            uiimage->SetImage(image);
            uiimage->SetArea(MythRect(scaled));
            m_overlayMap.insert(hash, uiimage);
            LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Added %1 (%2 tot)")
                .arg(hash).arg(m_overlayMap.size()));
        }
    }

    SetRedraw();
    BDOverlay::DeleteOverlay(overlay);
}
示例#13
0
/**
 * Update the various fields of a MythNotificationScreen.
 */
void MythNotificationScreen::Init(void)
{
    if (!m_refresh) // nothing got changed so far, return
        return;

    AdjustYPosition();

    if (m_artworkImage && (m_update & kImage))
    {
        if (!m_imagePath.isNull())
        {
            // We have a path to the image, use it
            m_artworkImage->SetFilename(m_imagePath);
            m_artworkImage->Load();
        }
        else if (!m_image.isNull())
        {
            // We don't have a path to the image, but the image itself
            MythImage *img = m_artworkImage->GetPainter()->GetFormatImage();
            img->Assign(m_image);
            m_artworkImage->SetImage(img);
            img->DecrRef();
        }
        else
        {
            // Will default to displaying whatever placeholder image is defined
            // in the xml by the themer, means we can show _something_ rather than
            // a big empty hole. Generally you always want to call Reset() in
            // these circumstances
            m_artworkImage->Reset();
        }
    }

    if (m_update != kNone)
    {
        InfoMap tmap;

        tmap["title"]               = m_title;
        if (m_update & kImage)
        {
            tmap["image"]           = m_imagePath;
        }
        tmap["origin"]              = m_origin;
        tmap["description"]         = m_description;
        tmap["extra"]               = m_extra;
        if (m_update & kDuration)
        {
            tmap["progress_text"]   = m_progresstext;
            tmap["progress"]        = QString("%1").arg((int)(m_progress * 100));
        }
        SetTextFromMap(tmap);
    }

    if (m_update & kMetaData)
    {
        if (m_titleText && m_title.isNull())
        {
            m_titleText->Reset();
        }
        if (m_originText && m_origin.isNull())
        {
            m_originText->Reset();
        }
        if (m_descriptionText && m_description.isNull())
        {
            m_descriptionText->Reset();
        }
        if (m_extraText && m_extra.isNull())
        {
            m_extraText->Reset();
        }
    }

    if (m_update & kDuration)
    {
        if (m_progresstextText && m_progresstext.isEmpty())
        {
            m_progresstextText->Reset();
        }
        if (m_progressBar)
        {
            if (m_progress >= 0)
            {
                m_progressBar->SetStart(0);
                m_progressBar->SetTotal(100);
                m_progressBar->SetUsed(100 * m_progress);
            }
            else
            {
                // Same as above, calling Reset() allows for a sane, themer defined
                //default to be displayed
                m_progressBar->Reset();
            }
        }
    }

    if (m_progressBar)
    {
        m_progressBar->SetVisible((m_content & kDuration) != 0);

    }

    SetErrorState();

    if (m_mediaState && (m_update & kImage))
    {
        m_mediaState->DisplayState(m_update & kNoArtwork ? "noartwork" : "ok");
        LOG(VB_GUI, LOG_DEBUG, LOC + QString("Init: Set media state to %1").arg(m_update & kNoArtwork ? "noartwork" : "ok"));
    }

    // No field will be refreshed the next time unless specified otherwise
    m_update = kNone;

    if (GetScreenStack() && !m_added)
    {
        GetScreenStack()->AddScreen(this);
        m_added = true;
    }
    m_refresh = false;
}
示例#14
0
void SubtitleScreen::DisplayAVSubtitles(void)
{
    if (!m_player || !m_subreader)
        return;

    AVSubtitles* subs = m_subreader->GetAVSubtitles();
    QMutexLocker lock(&(subs->lock));
    if (subs->buffers.empty() && (kDisplayAVSubtitle != m_subtitleType))
        return;

    VideoOutput    *videoOut = m_player->GetVideoOutput();
    VideoFrame *currentFrame = videoOut ? videoOut->GetLastShownFrame() : NULL;

    if (!currentFrame || !videoOut)
        return;

    float tmp = 0.0;
    QRect dummy;
    videoOut->GetOSDBounds(dummy, m_safeArea, tmp, tmp, tmp);

    while (!subs->buffers.empty())
    {
        const AVSubtitle subtitle = subs->buffers.front();
        if (subtitle.start_display_time > currentFrame->timecode)
            break;

        ClearDisplayedSubtitles();
        subs->buffers.pop_front();
        for (std::size_t i = 0; i < subtitle.num_rects; ++i)
        {
            AVSubtitleRect* rect = subtitle.rects[i];

            bool displaysub = true;
            if (subs->buffers.size() > 0 &&
                subs->buffers.front().end_display_time <
                currentFrame->timecode)
            {
                displaysub = false;
            }

            if (displaysub && rect->type == SUBTITLE_BITMAP)
            {
                // AVSubtitleRect's image data's not guaranteed to be 4 byte
                // aligned.

                QSize img_size(rect->w, rect->h);
                QRect img_rect(rect->x, rect->y, rect->w, rect->h);
                QRect display(rect->display_x, rect->display_y,
                              rect->display_w, rect->display_h);

                // XSUB and some DVD/DVB subs are based on the original video
                // size before the video was converted. We need to guess the
                // original size and allow for the difference

                int right  = rect->x + rect->w;
                int bottom = rect->y + rect->h;
                if (subs->fixPosition || (currentFrame->height < bottom) ||
                   (currentFrame->width  < right))
                {
                    int sd_height = 576;
                    if ((m_player->GetFrameRate() > 26.0f) && bottom <= 480)
                        sd_height = 480;
                    int height = ((currentFrame->height <= sd_height) &&
                                  (bottom <= sd_height)) ? sd_height :
                                 ((currentFrame->height <= 720) && bottom <= 720)
                                   ? 720 : 1080;
                    int width  = ((currentFrame->width  <= 720) &&
                                  (right <= 720)) ? 720 :
                                 ((currentFrame->width  <= 1280) &&
                                  (right <= 1280)) ? 1280 : 1920;
                    display = QRect(0, 0, width, height);
                }

                QRect scaled = videoOut->GetImageRect(img_rect, &display);
                QImage qImage(img_size, QImage::Format_ARGB32);
                for (int y = 0; y < rect->h; ++y)
                {
                    for (int x = 0; x < rect->w; ++x)
                    {
                        const uint8_t color = rect->pict.data[0][y*rect->pict.linesize[0] + x];
                        const uint32_t pixel = *((uint32_t*)rect->pict.data[1]+color);
                        qImage.setPixel(x, y, pixel);
                    }
                }

                if (scaled.size() != img_size)
                {
                    qImage = qImage.scaled(scaled.width(), scaled.height(),
                             Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
                }

                MythPainter *osd_painter = videoOut->GetOSDPainter();
                MythImage* image = NULL;
                if (osd_painter)
                   image = osd_painter->GetFormatImage();

                long long displayfor = subtitle.end_display_time -
                                       subtitle.start_display_time;
                if (displayfor == 0)
                    displayfor = 60000;
                displayfor = (displayfor < 50) ? 50 : displayfor;
                long long late = currentFrame->timecode -
                                 subtitle.start_display_time;
                MythUIImage *uiimage = NULL;
                if (image)
                {
                    image->Assign(qImage);
                    QString name = QString("avsub%1").arg(i);
                    uiimage = new MythUIImage(this, name);
                    if (uiimage)
                    {
                        m_refreshArea = true;
                        uiimage->SetImage(image);
                        uiimage->SetArea(MythRect(scaled));
                        m_expireTimes.insert(uiimage,
                                     currentFrame->timecode + displayfor);
                    }
                }
                if (uiimage)
                {
                    LOG(VB_PLAYBACK, LOG_INFO, LOC +
                        QString("Display %1AV subtitle for %2ms")
                        .arg(subtitle.forced ? "FORCED " : "")
                        .arg(displayfor));
                    if (late > 50)
                        LOG(VB_PLAYBACK, LOG_INFO, LOC +
                            QString("AV Sub was %1ms late").arg(late));
                }
            }
#ifdef USING_LIBASS
            else if (displaysub && rect->type == SUBTITLE_ASS)
            {
                InitialiseAssTrack(m_player->GetDecoder()->GetTrack(kTrackTypeSubtitle));
                AddAssEvent(rect->ass);
            }
#endif
        }
        m_subreader->FreeAVSubtitle(subtitle);
    }
#ifdef USING_LIBASS
    RenderAssTrack(currentFrame->timecode);
#endif
}
MythImage *MythQImagePainter::GetImageFromString(const QString &msg,
                                                 int flags, const QRect &r,
                                                 const MythFontProperties &font)
{
    QString incoming = font.GetHash() + QString::number(r.width()) +
                       QString::number(r.height()) +
                       QString::number(flags) +
                       QString::number(font.color().rgba()) + msg;

    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        return m_StringToImageMap[incoming];
    }

    MythImage *im = GetFormatImage();

    QPoint drawOffset;
    font.GetOffset(drawOffset);

    QImage pm(r.size(), QImage::Format_ARGB32);
    QColor fillcolor = font.color();
    if (font.hasOutline())
    {
        QColor outlineColor;
        int outlineSize, outlineAlpha;

        font.GetOutline(outlineColor, outlineSize, outlineAlpha);

        fillcolor = outlineColor;
    }
    fillcolor.setAlpha(0);
    pm.fill(fillcolor.rgba());

    QPainter tmp(&pm);
    tmp.setFont(font.face());

    if (font.hasShadow())
    {
        QPoint shadowOffset;
        QColor shadowColor;
        int shadowAlpha;

        font.GetShadow(shadowOffset, shadowColor, shadowAlpha);

        QRect a = QRect(0, 0, r.width(), r.height());
        a.translate(shadowOffset.x() + drawOffset.x(),
                    shadowOffset.y() + drawOffset.y());

        shadowColor.setAlpha(shadowAlpha);
        tmp.setPen(shadowColor);
        tmp.drawText(a, flags, msg);
    }

    if (font.hasOutline())
    {
        QColor outlineColor;
        int outlineSize, outlineAlpha;

        font.GetOutline(outlineColor, outlineSize, outlineAlpha);

        /* FIXME: use outlineAlpha */
        int outalpha = 16;

        QRect a = QRect(0, 0, r.width(), r.height());
        a.translate(-outlineSize + drawOffset.x(),
                    -outlineSize + drawOffset.y());

        outlineColor.setAlpha(outalpha);
        tmp.setPen(outlineColor);
        tmp.drawText(a, flags, msg);

        for (int i = (0 - outlineSize + 1); i <= outlineSize; i++)
        {
            a.translate(1, 0);
            tmp.drawText(a, flags, msg);
        }

        for (int i = (0 - outlineSize + 1); i <= outlineSize; i++)
        {
            a.translate(0, 1);
            tmp.drawText(a, flags, msg);
        }

        for (int i = (0 - outlineSize + 1); i <= outlineSize; i++)
        {
            a.translate(-1, 0);
            tmp.drawText(a, flags, msg);
        }

        for (int i = (0 - outlineSize + 1); i <= outlineSize; i++)
        {
            a.translate(0, -1);
            tmp.drawText(a, flags, msg);
        }
    }

    tmp.setPen(font.color());
    tmp.drawText(drawOffset.x(), drawOffset.y(), r.width(), r.height(),
                 flags, msg);

    tmp.end();

    im->Assign(pm);

    m_StringToImageMap[incoming] = im;
    m_StringExpireList.push_back(incoming);
    ExpireImages(MAX_CACHE_ITEMS);
    return im;
}
示例#16
0
MythImage *MythPainter::GetImageFromTextLayout(const LayoutVector &layouts,
                                               const FormatVector &formats,
                                               const MythFontProperties &font,
                                               QRect &canvas, QRect &dest)
{
    LayoutVector::const_iterator Ipara;

    QString incoming = QString::number(canvas.x()) +
                       QString::number(canvas.y()) +
                       QString::number(canvas.width()) +
                       QString::number(canvas.height()) +
                       QString::number(dest.width()) +
                       QString::number(dest.height()) +
                       font.GetHash();

    for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara)
        incoming += (*Ipara)->text();

    MythImage *im = NULL;
    if (m_StringToImageMap.contains(incoming))
    {
        m_StringExpireList.remove(incoming);
        m_StringExpireList.push_back(incoming);
        im = m_StringToImageMap[incoming];
        if (im)
            im->IncrRef();
    }
    else
    {
        im = GetFormatImage();
        im->SetFileName("GetImageFromTextLayout");

        QImage pm(canvas.size(), QImage::Format_ARGB32_Premultiplied);
        pm.fill(0);

        QPainter painter(&pm);
        if (!painter.isActive())
        {
            LOG(VB_GENERAL, LOG_ERR, "MythPainter::GetImageFromTextLayout: "
                "Invalid canvas.");
            return im;
        }

        QRect    clip;
        clip.setSize(canvas.size());

        QFont tmpfont = font.face();
        tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
        painter.setFont(tmpfont);
        painter.setRenderHint(QPainter::Antialiasing);

        if (font.hasShadow())
        {
            QRect  shadowRect;
            QPoint shadowOffset;
            QColor shadowColor;
            int    shadowAlpha;

            font.GetShadow(shadowOffset, shadowColor, shadowAlpha);
            shadowColor.setAlpha(shadowAlpha);

            MythPoint  shadow(shadowOffset);
            shadow.NormPoint(); // scale it to screen resolution

            shadowRect = canvas;
            shadowRect.translate(shadow.x(), shadow.y());

            painter.setPen(shadowColor);
            for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara)
                (*Ipara)->draw(&painter, shadowRect.topLeft(), formats, clip);
        }

        painter.setPen(QPen(font.GetBrush(), 0));
        for (Ipara = layouts.begin(); Ipara != layouts.end(); ++Ipara)
            (*Ipara)->draw(&painter, canvas.topLeft(), formats, clip);

        painter.end();

        pm.setOffset(canvas.topLeft());
        im->Assign(pm.copy(0, 0, dest.width(), dest.height()));

        im->IncrRef();
        m_SoftwareCacheSize += im->bytesPerLine() * im->height();
        m_StringToImageMap[incoming] = im;
        m_StringExpireList.push_back(incoming);
        ExpireImages(m_MaxSoftwareCacheSize);
    }
    return im;
}