Ticket #5176: 0001-Added-Ken-Burns-Effect-for-mythgallery.patch

File 0001-Added-Ken-Burns-Effect-for-mythgallery.patch, 22.8 KB (added by beirdo, 10 years ago)

against trunk [25659]

  • mythplugins/configure

    From ee5ed7909903082aea69138fefbebea58bc9f69e Mon Sep 17 00:00:00 2001
    From: Gavin Hurlbut <gjhurlbu@gmail.com>
    Date: Tue, 13 Jul 2010 11:31:15 -0700
    Subject: [PATCH 1/2] Added Ken Burns Effect for mythgallery
    
    Patches taken from #5176
    
    diff --git a/mythplugins/configure b/mythplugins/configure
    index 2d6543d..029eebe 100755
    a b fftw 
    117117sdl
    118118exif
    119119newexif
     120fdlib
    120121"
    121122
    122123enable $PLUGIN_LIST $CONFIG_LIST
    MythBrowser related options: 
    160161
    161162MythGallery related options:
    162163  --enable-mythgallery     build the mythgallery plugin [$gallery]
     164  --enable-fdlib           enable face recognition libary [$fdlib]
    163165  --enable-exif            enable reading of EXIF headers [$exif]
    164166  --enable-new-exif        use libexif > version 0.6.9 [$newexif]
    165167
    for opt do 
    247249  ;;
    248250  --disable-new-exif) disable newexif
    249251  ;;
     252  --enable-fdlib) enable fdlib
     253  ;;
     254  --disable-fdlib) disable fdlib
     255  ;; 
    250256  --enable-all)
    251257      enable $PLUGIN_LIST $CONFIG_LIST
    252258  ;;
    if ! disabled weather; then 
    453459    check_pl_lib "SOAP::Lite"  || disable_weather "SOAP::Lite"
    454460fi
    455461
     462if test "$fdlib" != "no" ; then
     463    fdlib="no"
     464    if has_library libfd ; then
     465        if has_header fdlib.h ; then
     466            fdlib="yes"
     467        fi
     468    fi
     469fi
     470
    456471if test "$music" != "no" ; then
    457472    vorbis="no"
    458473    if has_header ogg/ogg.h && has_header vorbis/vorbisenc.h && has_header vorbis/vorbisfile.h && has_header vorbis/codec.h && has_library libogg && has_library libvorbisfile && has_library libvorbisenc && has_library libvorbis ; then
    if test "$gallery" = "yes" ; then 
    702717    if test "$exif" = "no" ; then
    703718        echo "        EXIF           support will not be included in MythGallery"
    704719    fi
     720   
     721    if test "$fdlib" = "yes" ; then
     722        echo "        fdlib          support will be included in MythGallery"
     723        echo "#define FDLIB_SUPPORT 1" >> ./mythgallery/mythgallery/config.h
     724        echo "LIBS += -lfd" >> ./mythgallery/mythgallery/config.pro
     725    fi
     726
     727    if test "$fdlib" = "no" ; then
     728        echo "        fdlib          support will not be included in MythGallery"
     729    fi
    705730fi
    706731
    707732###########################################################
  • mythplugins/mythgallery/README

    diff --git a/mythplugins/mythgallery/README b/mythplugins/mythgallery/README
    index 6b0fc9c..4f30e3a 100644
    a b packages from your favorite package repository usually provides this. 
    3535Current, EXIF support only consists of auto-rotating images if the camera
    3636sets the orientation tag (My Canon S400 does)
    3737
     38You can also enable fdlib support using
     39./configure --enable-fdlib
     40fdlib - is a facial recognition library that is used as part of the ken
     41burns slide show effect. It tries to ensure that slide shows pan/zoom
     42to peoples faces rather than their feet or off to the background.
     43fdlib can be downloaded from:
     44http://www.kyb.mpg.de/bs/people/kienzle/fdlib/fdlib.htm
     45It will require the gcc compatibility packages. Once downloaded
     46fdlib.h should be installed in your headers directory (/usr/include)
     47libfd.so should be installed in your libs directory (/usr/lib)
     48fdlib.dat should be installed in your current working directory when
     49mythfrontend is started for me it was (/home/myth). Please note that
     50this is not probably not the same directory where mythfrontend actually
     51resides. If fdlib does not find fdlib.dat, it will fail silently and just
     52not find any faces.
     53
    38542) Next type 'qmake mythgallery.pro' then 'make' in the
    3955main distribution directory.
    4056
  • mythplugins/mythgallery/mythgallery/gallerysettings.cpp

    diff --git a/mythplugins/mythgallery/mythgallery/gallerysettings.cpp b/mythplugins/mythgallery/mythgallery/gallerysettings.cpp
    index 1da908c..d8faab7 100644
    a b static HostComboBox *SlideshowOpenGLTransition() 
    105105    gc->addSelection("flutter (gl)");
    106106    gc->addSelection("cube (gl)");
    107107    gc->addSelection("random (gl)");
     108    gc->addSelection("Ken Burns (gl)");
    108109    gc->setHelpText(QObject::tr("This is the type of OpenGL transition used "
    109110                    "between pictures in slideshow mode."));
    110111    return gc;
    static HostComboBox *SlideshowOpenGLTransition() 
    113114static HostSpinBox *SlideshowOpenGLTransitionLength()
    114115{
    115116    HostSpinBox *gc = new HostSpinBox(
    116         "SlideshowOpenGLTransitionLength", 500, 10000, 500);
     117        "SlideshowOpenGLTransitionLength", 500, 30000, 500);
    117118    gc->setLabel(QObject::tr("Duration of OpenGL Transition (milliseconds)"));
    118119    gc->setValue(2000);
    119120    return gc;
    static HostComboBox *SlideshowBackground() 
    159160
    160161static HostSpinBox *SlideshowDelay()
    161162{
    162     HostSpinBox *gc = new HostSpinBox("SlideshowDelay", 1, 600, 1);
     163    HostSpinBox *gc = new HostSpinBox("SlideshowDelay", 0, 600, 1);
    163164    gc->setLabel(QObject::tr("Slideshow Delay"));
    164165    gc->setValue(5);
    165166    gc->setHelpText(QObject::tr("This is the number of seconds to display each "
  • mythplugins/mythgallery/mythgallery/glsingleview.cpp

    diff --git a/mythplugins/mythgallery/mythgallery/glsingleview.cpp b/mythplugins/mythgallery/mythgallery/glsingleview.cpp
    index f237d6f..ff4c596 100644
    a b using namespace std; 
    3131#include <QImage>
    3232#include <QDir>
    3333#include <QPainter>
     34#include <qbuffer.h>
    3435
    3536// MythTV plugin headers
    3637#include <mythcontext.h>
    using namespace std; 
    3839#include <mythuihelper.h>
    3940
    4041// MythGallery headers
     42#include "config.h"
    4143#include "glsingleview.h"
    4244#include "galleryutil.h"
    4345
     46#ifdef FDLIB_SUPPORT
     47#include <fdlib.h>
     48#endif
     49
    4450#define LOC QString("GLView: ")
    4551#define LOC_ERR QString("GLView, Error: ")
    4652
    GLSingleView::GLSingleView(ThumbList itemList, int *pos, int slideShow, 
    95101      // Unshared effect state variables
    96102      m_effect_cube_xrot(0.0f),
    97103      m_effect_cube_yrot(0.0f),
    98       m_effect_cube_zrot(0.0f)
     104      m_effect_cube_zrot(0.0f),
     105      m_effect_kenBurns_image_ready(true),
     106      m_effect_kenBurns_initialized(false),
     107      m_effect_kenBurns_new_image_started(true)
    99108{
    100109    m_scaleMax = (ScaleMax) gCoreContext->GetNumSetting("GalleryScaleMax", 0);
    101110
    void GLSingleView::RegisterEffects(void) 
    707716    m_effect_map.insert("slide (gl)",      "EffectSlide");
    708717    m_effect_map.insert("flutter (gl)",    "EffectFlutter");
    709718    m_effect_map.insert("cube (gl)",       "EffectCube");
     719    m_effect_map.insert("Ken Burns (gl)",  "EffectKenBurns");
    710720}
    711721
    712722void GLSingleView::RunEffect(const QString &effect)
    void GLSingleView::RunEffect(const QString &effect) 
    729739        EffectFlutter();
    730740    else if (effect == "EffectCube")
    731741        EffectCube();
     742    else if (effect == "EffectKenBurns")
     743        EffectKenBurns();
    732744    else //if (effect == "EffectNone")
    733745        EffectNone();
    734746}
    void GLSingleView::EffectCube(void) 
    12121224    m_effect_current_frame++;
    12131225}
    12141226
     1227void GLSingleView::EffectKenBurns(void)
     1228{
     1229
     1230    float single_image_pct = 0.75;
     1231    float trans_pct = 1.0 - single_image_pct;
     1232    float scale_max, x_loc, y_loc;
     1233    float scale_factor = 0;
     1234
     1235    //initialize effect   
     1236    if (!m_effect_kenBurns_initialized)
     1237    {
     1238               
     1239        m_effect_kenBurns_initialized = !m_effect_kenBurns_initialized;
     1240        m_effect_kenBurns_item = NULL;
     1241        // Need to load images in the background to keep effect smooth
     1242        m_effect_kenBurns_imageLoadThread = new KenBurnsImageLoader(this, m_itemList, m_texSize, m_screenSize);
     1243        //Since total image time is longer/different than effect time, create image timers
     1244        m_effect_kenBurns_image_time[m_texCur ? 0 : 1].restart();
     1245        // Pan image to a random location
     1246        FindRandXY(m_effect_kenBurns_location_x[0], m_effect_kenBurns_location_y[0]);
     1247        // Since first two images are preloaded, hardcode  them to zoom in
     1248        m_effect_kenBurns_projection[0] = 1;
     1249        m_effect_kenBurns_projection[1] = 1;
     1250        m_effect_kenBurns_image_timeout = m_effect_transition_timeout +
     1251                (m_effect_transition_timeout * trans_pct);
     1252        m_effect_kenBurns_face_x = 0.0;
     1253        m_effect_kenBurns_face_y = 0.0;
     1254    }
     1255
     1256    if (m_effect_frame_time.elapsed() >= m_effect_transition_timeout)
     1257    {
     1258        // Effect timed out, move new image to old image but don't load new image yet...
     1259        m_tex1First = !m_tex1First;
     1260        m_texCur      = (m_texCur) ? 0 : 1;
     1261        m_effect_current_frame  = 0;
     1262        m_effect_frame_time.restart();
     1263
     1264        m_effect_kenBurns_image_ready = false;
     1265        m_effect_kenBurns_face_x = 0.0;
     1266        m_effect_kenBurns_face_y = 0.0;
     1267
     1268        // Find next image to be loaded
     1269        int oldpos = m_pos;
     1270
     1271        while (true)
     1272        {
     1273            m_pos = m_slideshow_sequence->next();
     1274            m_effect_kenBurns_item = m_itemList.at(m_pos);
     1275            if (m_effect_kenBurns_item)
     1276            {
     1277                // Skip movies
     1278                if (QFile::exists(m_effect_kenBurns_item->GetPath()) && !GalleryUtil::IsMovie(m_effect_kenBurns_item->GetPath()))
     1279                {
     1280                    break;
     1281                }
     1282            }
     1283            if (m_pos == oldpos)
     1284            {
     1285                // No valid items!!!
     1286                close();
     1287            }
     1288        }
     1289        m_effect_kenBurns_imageLoadThread->Initialize(m_pos);
     1290        m_effect_kenBurns_imageLoadThread->start();
     1291    }
     1292
     1293    float t[2], elapsed[2], s[2], effect_pct;
     1294    elapsed[m_texCur] = m_effect_kenBurns_image_time[m_texCur].elapsed();
     1295    elapsed[m_texCur ? 0 : 1] = m_effect_kenBurns_image_time[m_texCur ? 0 : 1].elapsed();
     1296    //progress linearly
     1297    t[m_texCur] = elapsed[m_texCur] / m_effect_kenBurns_image_timeout;
     1298    t[m_texCur ? 0 : 1] = elapsed[m_texCur ? 0 : 1] / m_effect_kenBurns_image_timeout;
     1299    //progress faster initially then slowing down- this is needed to ensure images zoom faster than they pan and
     1300    //therefore stay completely on the screen
     1301    s[m_texCur] = sqrt(elapsed[m_texCur]) / sqrt(m_effect_kenBurns_image_timeout);
     1302    s[m_texCur ? 0 : 1] = sqrt(elapsed[m_texCur ? 0 : 1]) / sqrt(m_effect_kenBurns_image_timeout);
     1303   
     1304    effect_pct = m_effect_frame_time.elapsed() *  m_effect_transition_timeout_inv;
     1305
     1306    // Load new image if its ready
     1307    if (effect_pct > single_image_pct && m_effect_kenBurns_image_ready)
     1308    {
     1309        if (!m_effect_kenBurns_new_image_started)
     1310        {                       
     1311            if (m_effect_kenBurns_item) //Do not create textures for first two images, since they are preloaded
     1312            {
     1313                m_texItem[!m_tex1First].SetItem(m_effect_kenBurns_item, m_effect_kenBurns_orig_image_size);
     1314                m_texItem[!m_tex1First].ScaleTo(m_screenSize, m_scaleMax);
     1315                m_texItem[!m_tex1First].Init(m_effect_kenBurns_image);
     1316                UpdateLCD(m_effect_kenBurns_item);
     1317               
     1318                // If there is no face in this image
     1319                if ((m_effect_kenBurns_face_x == 0.0) && (m_effect_kenBurns_face_x == 0.0))
     1320                {
     1321                    //choose the location and projection (zoom in or out) randomly
     1322                    FindRandXY(m_effect_kenBurns_location_x[m_texCur], m_effect_kenBurns_location_y[m_texCur]);
     1323                    m_effect_kenBurns_projection[m_texCur] = 1 + (int)((2.0f * rand() / (RAND_MAX + 1.0f)));
     1324                }
     1325                //else if the face is  close to center
     1326                else if ((m_effect_kenBurns_face_x < 0.25) && (m_effect_kenBurns_face_x > -0.25) &&
     1327                        (m_effect_kenBurns_face_y < 0.25) && (m_effect_kenBurns_face_y > -0.25))
     1328                {                   
     1329                    //start at random location and zoom out to face in center
     1330                    FindRandXY(m_effect_kenBurns_location_x[m_texCur], m_effect_kenBurns_location_y[m_texCur]);
     1331                    m_effect_kenBurns_projection[m_texCur] = 0;
     1332                }
     1333                else
     1334                {
     1335                    //start in center and zoom in to face random location
     1336                    m_effect_kenBurns_location_x[m_texCur] = m_effect_kenBurns_face_x;
     1337                    m_effect_kenBurns_location_y[m_texCur] = m_effect_kenBurns_face_y;
     1338                    m_effect_kenBurns_projection[m_texCur] = 1;               
     1339                }
     1340            }
     1341            else  //No item, must be 1 of the first two preloaded items
     1342            {
     1343                //start at random location and zoom out to face in center
     1344                FindRandXY(m_effect_kenBurns_location_x[m_texCur], m_effect_kenBurns_location_y[m_texCur]);
     1345                m_effect_kenBurns_projection[m_texCur] = 1;
     1346            }
     1347
     1348            m_effect_kenBurns_image_time[m_texCur].restart();
     1349            m_effect_kenBurns_new_image_started = true;
     1350        }
     1351        if (m_effect_kenBurns_projection[m_texCur] == 1) // Zoom in image
     1352        {
     1353            // Start in center and pan out
     1354            x_loc = m_effect_kenBurns_location_x[m_texCur] * t[m_texCur];
     1355            y_loc = m_effect_kenBurns_location_y[m_texCur] * t[m_texCur];               
     1356            scale_max = FindMaxScale(x_loc,y_loc);
     1357            scale_factor =      1.0f + (scale_max * s[m_texCur]);
     1358        }
     1359        else // Zoom out image
     1360        {
     1361            // Start at random location and pan to center
     1362            x_loc = m_effect_kenBurns_location_x[m_texCur] -  m_effect_kenBurns_location_x[m_texCur] * t[m_texCur];
     1363            y_loc = m_effect_kenBurns_location_y[m_texCur] -  m_effect_kenBurns_location_y[m_texCur] * t[m_texCur];
     1364            scale_max = FindMaxScale(x_loc,y_loc);
     1365            scale_factor =      1.0f + scale_max -  (scale_max * t[m_texCur]);
     1366        }
     1367
     1368        glMatrixMode(GL_MODELVIEW);
     1369        glLoadIdentity();
     1370        glTranslatef(x_loc, y_loc, 0.0f);
     1371
     1372        m_texItem[m_texCur].MakeQuad((effect_pct-single_image_pct)*4, scale_factor);
     1373    }
     1374   
     1375    //Load old picture
     1376    if (m_effect_kenBurns_projection[m_texCur ? 0 : 1] == 1)// Zoom in image
     1377    {
     1378        x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
     1379        y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
     1380        scale_max = FindMaxScale(x_loc,y_loc);
     1381        scale_factor =  1.0f + (scale_max * s[m_texCur ? 0 : 1]);
     1382    }
     1383    else // Zoom out image
     1384    {
     1385        x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] - 
     1386            m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
     1387        y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] - 
     1388            m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1];
     1389        scale_max = FindMaxScale(x_loc,y_loc);
     1390        scale_factor =  1.0f + scale_max -  (scale_max * t[m_texCur ? 0 : 1]);
     1391    }
     1392
     1393    glMatrixMode(GL_MODELVIEW);
     1394    glLoadIdentity();
     1395    glTranslatef(x_loc, y_loc, 0.0f);
     1396
     1397    if (effect_pct<= single_image_pct)
     1398    {
     1399        m_effect_kenBurns_new_image_started=false;
     1400        m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f, scale_factor); //
     1401    }
     1402    else // Fade out image
     1403    {
     1404        m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f - ((effect_pct-single_image_pct)*4), scale_factor);
     1405
     1406    }
     1407   
     1408    m_effect_current_frame++;
     1409}
     1410
    12151411void GLSingleView::SlideTimeout(void)
    12161412{
    12171413    bool wasMovie = false, isMovie = false;
    void GLSingleView::createTexInfo(void) 
    13181514    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    13191515    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    13201516}
     1517
     1518void GLSingleView::LoadImage(QImage image, QSize origSize, Face *face)
     1519{
     1520    m_effect_kenBurns_image = image;
     1521    m_effect_kenBurns_orig_image_size = origSize;
     1522    if (face)
     1523    {
     1524        VERBOSE(VB_IMPORTANT, QString("Found face, set location x '%1' y '%2'").arg(face->getX()).arg(face->getY()));
     1525        m_effect_kenBurns_face_x = face->getX();
     1526        m_effect_kenBurns_face_y = face->getY();
     1527    }
     1528}
     1529
     1530float GLSingleView::FindMaxScale(float x_loc, float y_loc)
     1531{
     1532    // Zoom big enough to keep the entire image on screen when we pan
     1533    if (abs(x_loc) > abs(y_loc))
     1534        return abs(x_loc) * 2;
     1535    else
     1536        return abs(y_loc) * 2;
     1537}
     1538
     1539void GLSingleView::FindRandXY(float &x_loc, float &y_loc)
     1540{
     1541    x_loc = (0.5 * rand() / (RAND_MAX + 1.0f)) + 0.25;  //Random number between .25 and .75
     1542    if ((int)(2.0 * rand() / (RAND_MAX + 1.0f)) == 0)
     1543        x_loc = -1 * x_loc;
     1544    y_loc = (0.5 * rand() / (RAND_MAX + 1.0f)) + 0.25;  //Random number between .25 and .75
     1545    if ((int)(2.0 * rand() / (RAND_MAX + 1.0f)) == 0)
     1546        y_loc = -1 * y_loc;   
     1547}
     1548
     1549KenBurnsImageLoader::KenBurnsImageLoader(GLSingleView *singleView, ThumbList &itemList, QSize texSize, QSize screenSize)
     1550{
     1551    m_singleView = singleView;
     1552    m_itemList = itemList;
     1553    m_texSize = texSize;
     1554    m_screenSize = screenSize;
     1555}
     1556
     1557void KenBurnsImageLoader::Initialize(int pos)
     1558{
     1559    m_pos = pos;
     1560}
     1561
     1562void KenBurnsImageLoader::run()
     1563{
     1564    ThumbItem *item = m_itemList.at(m_pos);
     1565    if (!item)
     1566    {
     1567        VERBOSE(VB_IMPORTANT, LOC_ERR + "No item at "<<m_pos);
     1568        return;
     1569    }
     1570    QImage image(item->GetPath());
     1571    if (image.isNull())
     1572        return;
     1573   
     1574#ifdef FDLIB_SUPPORT
     1575   
     1576    int i, n, x[256], y[256], size[256], w, h, threshold;
     1577    float loc_x, loc_y;
     1578    unsigned char *bgrdata, *graydata;
     1579   
     1580    w = image.width();
     1581    h = image.height();
     1582    bgrdata = image.bits();
     1583 
     1584    graydata = new unsigned char[w*h];
     1585    for (i=0; i<w*h; i++)
     1586        graydata[i] = (unsigned char) ((.11*bgrdata[4*i] + .59*bgrdata[4*i+1] + .3*bgrdata[4*i+2]));
     1587   
     1588   
     1589    threshold = 0;
     1590    fdlib_detectfaces(graydata, w, h, threshold);   
     1591    delete[] graydata;       
     1592    n = fdlib_getndetections();
     1593    if (n==0)
     1594    {
     1595        VERBOSE(VB_IMPORTANT, QString("%1 face found.").arg(n));
     1596        m_singleView->LoadImage(QGLWidget::convertToGLFormat(image.scaled(m_texSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), image.size());
     1597    }
     1598    else if (n==1)
     1599    {
     1600        VERBOSE(VB_IMPORTANT, QString("%1 faces found.").arg(n));
     1601
     1602        fdlib_getdetection(0, x, y, size);
     1603        loc_x = (x[0]-(float)w/2)/((float)w/2)*(-1);
     1604        loc_y = (y[0]-(float)h/2)/((float)h/2)*(-1);
     1605        VERBOSE(VB_IMPORTANT, QString("x:%1 y:%2 size:%3").arg(x[0]).arg(y[0]).arg(size[0]));
     1606        m_singleView->LoadImage(QGLWidget::convertToGLFormat(image.scaled(m_texSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), image.size(), new Face(loc_x, loc_y));
     1607    }
     1608    else
     1609    {
     1610        VERBOSE(VB_IMPORTANT, QString("%1 faces found.").arg(n));
     1611        QList<Face*> faces;
     1612        int faceIndex;
     1613   
     1614        for (i=0; i<n; i++)
     1615        {
     1616            fdlib_getdetection(i, x+i, y+i, size+i);
     1617            loc_x = (x[i]-(float)w/2)/((float)w/2)*(-1);
     1618            loc_y = (y[i]-(float)h/2)/((float)h/2)*(-1);
     1619            VERBOSE(VB_IMPORTANT, QString("x:%1 y:%2 size:%3").arg(x[i]).arg(y[i]).arg(size[i]));
     1620            faces.append(new Face(loc_x, loc_y));
     1621        }
     1622        if (faces.count() > 1)
     1623            faceIndex = (int) ((faces.count()+1) * rand() / (RAND_MAX + 1.0f)); //
     1624        else
     1625            faceIndex = 0;
     1626           
     1627        m_singleView->LoadImage(QGLWidget::convertToGLFormat(image.scaled(m_texSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), image.size(), faces.at(faceIndex));
     1628    }
     1629   
     1630#else  //END FDLIB_SUPPORT
     1631    m_singleView->LoadImage(QGLWidget::convertToGLFormat(image.scaled(m_texSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)), image.size());   
     1632#endif
     1633    m_singleView->Ready();
     1634
     1635}
     1636
     1637Face::Face(float x, float y)
     1638{
     1639    m_x = x;
     1640    m_y = y;
     1641}
  • mythplugins/mythgallery/mythgallery/glsingleview.h

    diff --git a/mythplugins/mythgallery/mythgallery/glsingleview.h b/mythplugins/mythgallery/mythgallery/glsingleview.h
    index c8c6fe6..54acdd3 100644
    a b  
    2323#define GLSINGLEVIEW_H
    2424#ifdef USING_OPENGL
    2525
     26
    2627// MythTV plugin headers
    2728#include <util.h>
    2829#include <mythdialogs.h>
    class QImage; 
    3738class QTimer;
    3839
    3940class GLSingleView;
     41class KenBurnsImageLoader;
     42class Face;
    4043
    4144class GLSDialog : public MythDialog
    4245{
    class GLSingleView : public QGLWidget, public ImageView 
    6265    ~GLSingleView();
    6366
    6467    void CleanUp(void);
     68    void Ready(){m_effect_kenBurns_image_ready = true;}
     69    void LoadImage(QImage image, QSize origSize, Face *face = NULL);
     70   
    6571
    6672  protected:
    6773    void initializeGL(void);
    class GLSingleView : public QGLWidget, public ImageView 
    99105    void EffectSlide(void);
    100106    void EffectFlutter(void);
    101107    void EffectCube(void);
    102 
     108    void EffectKenBurns(void);
     109 
     110  private:
     111        float FindMaxScale(float x_loc, float y_loc);
     112        void FindRandXY(float &x_loc, float &y_loc);
     113   
    103114  private slots:
    104115    void SlideTimeout(void);
    105116
    class GLSingleView : public QGLWidget, public ImageView 
    130141    float         m_effect_cube_xrot;
    131142    float         m_effect_cube_yrot;
    132143    float         m_effect_cube_zrot;
     144    float         m_effect_kenBurns_location_x[2];
     145    float         m_effect_kenBurns_location_y[2];
     146    int           m_effect_kenBurns_projection[2];
     147    MythTimer     m_effect_kenBurns_image_time[2];
     148    float         m_effect_kenBurns_image_timeout;
     149    KenBurnsImageLoader *m_effect_kenBurns_imageLoadThread;
     150    bool          m_effect_kenBurns_image_ready;
     151    QImage        m_effect_kenBurns_image;
     152    QSize         m_effect_kenBurns_orig_image_size;
     153    float         m_effect_kenBurns_face_x;
     154    float         m_effect_kenBurns_face_y;
     155    ThumbItem     *m_effect_kenBurns_item;
     156    bool          m_effect_kenBurns_initialized;
     157    bool          m_effect_kenBurns_new_image_started;
     158   
     159};
     160
     161class KenBurnsImageLoader : public QThread
     162{
     163public:
     164    KenBurnsImageLoader(GLSingleView *singleView, ThumbList &itemList, QSize m_texSize, QSize m_screenSize);
     165    void Initialize(int pos);
     166    void run();
     167private:
     168        GLSingleView *m_singleView;
     169    ThumbList     m_itemList;
     170    int           m_pos;
     171    bool          m_tex1First;
     172    QSize         m_screenSize;
     173    QSize         m_texSize;
     174
     175};
     176
     177class Face
     178{
     179  public:
     180    Face(float x, float y);
     181    float getX() { return m_x; }
     182    float getY() { return m_y; }
     183  private:
     184      float m_x;
     185      float m_y;
    133186};
    134187
    135188#endif // USING_OPENGL
  • mythplugins/mythgallery/mythgallery/imageview.cpp

    diff --git a/mythplugins/mythgallery/mythgallery/imageview.cpp b/mythplugins/mythgallery/mythgallery/imageview.cpp
    index fa847ea..b9d17f3 100644
    a b QString ImageView::GetRandomEffect(void) const 
    139139{
    140140    QMap<QString,QString> tmpMap = m_effect_map;
    141141    tmpMap.remove("none");
     142    tmpMap.remove("Ken Burns (gl)");
    142143    QStringList t = tmpMap.keys();
    143144    int i = (int) ( (float)(t.count()) * rand() / (RAND_MAX + 1.0f) );
    144145    return tmpMap[t[i]];