Ticket #5176: kenburns2.patch
| File kenburns2.patch, 12.6 KB (added by , 18 years ago) |
|---|
-
mythgallery/glsingleview.cpp
93 93 // Unshared effect state variables 94 94 m_effect_cube_xrot(0.0f), 95 95 m_effect_cube_yrot(0.0f), 96 m_effect_cube_zrot(0.0f) 96 m_effect_cube_zrot(0.0f), 97 m_effect_kenBurns_image_ready(true), 98 m_effect_kenBurns_initialized(false), 99 m_effect_kenBurns_new_image_started(true) 97 100 { 98 101 m_scaleMax = (gContext->GetNumSetting("GalleryScaleMax", 0) > 0); 99 102 … … 673 676 m_effect_map.insert("slide (gl)", "EffectSlide"); 674 677 m_effect_map.insert("flutter (gl)", "EffectFlutter"); 675 678 m_effect_map.insert("cube (gl)", "EffectCube"); 679 m_effect_map.insert("Ken Burns (gl)", "EffectKenBurns"); 676 680 } 677 681 678 682 void GLSingleView::RunEffect(const QString &effect) … … 695 699 EffectFlutter(); 696 700 else if (effect == "EffectCube") 697 701 EffectCube(); 702 else if (effect == "EffectKenBurns") 703 EffectKenBurns(); 698 704 else //if (effect == "EffectNone") 699 705 EffectNone(); 700 706 } … … 1178 1184 m_effect_current_frame++; 1179 1185 } 1180 1186 1187 void GLSingleView::EffectKenBurns(void) 1188 { 1189 1190 float single_image_pct = 0.75; 1191 float trans_pct = 1.0 - single_image_pct; 1192 float scale_max, x_loc, y_loc; 1193 float scale_factor = 0; 1194 1195 //initialize effect 1196 if (!m_effect_kenBurns_initialized) 1197 { 1198 m_effect_kenBurns_initialized = !m_effect_kenBurns_initialized; 1199 m_effect_kenBurns_item = NULL; 1200 // Need to load images in the background to keep effect smooth 1201 m_effect_kenBurns_imageLoadThread = new KenBurnsImageLoader(this, m_itemList, m_texSize, m_screenSize); 1202 //Since total image time is longer/different than effect time, create image timers 1203 m_effect_kenBurns_image_time[m_texCur ? 0 : 1].restart(); 1204 // Pan image to a random location 1205 m_effect_kenBurns_location_x[0] = (2.0 * rand() / (RAND_MAX + 1.0f)) - 1; 1206 m_effect_kenBurns_location_y[0] = (2.0 * rand() / (RAND_MAX + 1.0f)) - 1; 1207 // Since first two images are preloaded, harcode them to zoom in 1208 m_effect_kenBurns_projection[0] = 1; 1209 m_effect_kenBurns_projection[1] = 1; 1210 m_effect_kenBurns_image_timeout_inv = 1 / (m_effect_transition_timeout + 1211 (m_effect_transition_timeout * trans_pct)); 1212 } 1213 1214 if (m_effect_frame_time.elapsed() >= m_effect_transition_timeout) 1215 { 1216 // Effect timed out, move new image to old image but don't load new image yet... 1217 m_tex1First = !m_tex1First; 1218 m_texCur = (m_texCur) ? 0 : 1; 1219 m_effect_current_frame = 0; 1220 m_effect_frame_time.restart(); 1221 1222 if (m_effect_kenBurns_item) // Since first two images are preloaded dont randomly select sizefactor 1223 // Randomly determine whether to zoom in or zoom out 1224 m_effect_kenBurns_projection[m_texCur] = 1 + (int)((2.0f * rand() / (RAND_MAX + 1.0f))); 1225 1226 m_effect_kenBurns_image_ready = false; 1227 1228 // Find next image to be loaded 1229 int oldpos = m_pos; 1230 1231 while (true) 1232 { 1233 m_pos = m_slideshow_sequence->next(); 1234 m_effect_kenBurns_item = m_itemList.at(m_pos); 1235 if (m_effect_kenBurns_item) 1236 { 1237 // Skip movies 1238 if (QFile::exists(m_effect_kenBurns_item->GetPath()) && !GalleryUtil::isMovie(m_effect_kenBurns_item->GetPath())) 1239 { 1240 break; 1241 } 1242 } 1243 if (m_pos == oldpos) 1244 { 1245 // No valid items!!! 1246 close(); 1247 } 1248 } 1249 m_effect_kenBurns_imageLoadThread->Initialize(m_pos); 1250 m_effect_kenBurns_imageLoadThread->start(); 1251 } 1252 1253 float t[2]; 1254 t[m_texCur] = m_effect_kenBurns_image_time[m_texCur].elapsed() * m_effect_kenBurns_image_timeout_inv; 1255 t[m_texCur ? 0 : 1] = m_effect_kenBurns_image_time[m_texCur ? 0 : 1].elapsed() * 1256 m_effect_kenBurns_image_timeout_inv; 1257 float effect_pct = m_effect_frame_time.elapsed() * m_effect_transition_timeout_inv; 1258 1259 // Load new image if its ready 1260 if (effect_pct > single_image_pct && m_effect_kenBurns_image_ready) 1261 { 1262 if (!m_effect_kenBurns_new_image_started) 1263 { 1264 if (m_effect_kenBurns_item) //Do not create textures for first two images, since they are preloaded 1265 { 1266 m_texItem[!m_tex1First].SetItem(m_effect_kenBurns_item, m_effect_kenBurns_orig_image_size); 1267 m_texItem[!m_tex1First].ScaleTo(m_screenSize, false); 1268 m_texItem[!m_tex1First].Init(m_effect_kenBurns_image); 1269 UpdateLCD(m_effect_kenBurns_item); 1270 } 1271 1272 m_effect_kenBurns_location_x[m_texCur] = (2.0 * rand() / (RAND_MAX + 1.0f)) - 1; 1273 m_effect_kenBurns_location_y[m_texCur] = (2.0 * rand() / (RAND_MAX + 1.0f)) - 1; 1274 m_effect_kenBurns_image_time[m_texCur].restart(); 1275 m_effect_kenBurns_new_image_started = true; 1276 } 1277 if (m_effect_kenBurns_projection[m_texCur] == 1) // Zoom in image 1278 { 1279 // Start in center and pan out 1280 x_loc = m_effect_kenBurns_location_x[m_texCur] * t[m_texCur]; 1281 y_loc = m_effect_kenBurns_location_y[m_texCur] * t[m_texCur]; 1282 scale_max = FindMaxScale(x_loc,y_loc); 1283 scale_factor = 1.0f + (scale_max * t[m_texCur]); 1284 } 1285 else // Zoom out image 1286 { 1287 // Start at random location and pan to center 1288 x_loc = m_effect_kenBurns_location_x[m_texCur] - m_effect_kenBurns_location_x[m_texCur] * t[m_texCur]; 1289 y_loc = m_effect_kenBurns_location_y[m_texCur] - m_effect_kenBurns_location_y[m_texCur] * t[m_texCur]; 1290 scale_max = FindMaxScale(x_loc,y_loc); 1291 scale_factor = 1.0f + scale_max - (scale_max * t[m_texCur]); 1292 } 1293 1294 glMatrixMode(GL_MODELVIEW); 1295 glLoadIdentity(); 1296 glTranslatef(x_loc, y_loc, 0.0f); 1297 1298 m_texItem[m_texCur].MakeQuad((effect_pct-single_image_pct)*4, scale_factor); 1299 } 1300 1301 //Load old picture 1302 if (m_effect_kenBurns_projection[m_texCur ? 0 : 1] == 1) 1303 { 1304 x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1]; 1305 y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1]; 1306 scale_max = FindMaxScale(x_loc,y_loc); 1307 scale_factor = 1.0f + (scale_max * t[m_texCur ? 0 : 1]); 1308 } 1309 else 1310 { 1311 x_loc = m_effect_kenBurns_location_x[m_texCur ? 0 : 1] - m_effect_kenBurns_location_x[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1]; 1312 y_loc = m_effect_kenBurns_location_y[m_texCur ? 0 : 1] - m_effect_kenBurns_location_y[m_texCur ? 0 : 1] * t[m_texCur ? 0 : 1]; 1313 scale_max = FindMaxScale(x_loc,y_loc); 1314 scale_factor = 1.0f + scale_max - (scale_max * t[m_texCur ? 0 : 1]); 1315 } 1316 1317 glMatrixMode(GL_MODELVIEW); 1318 glLoadIdentity(); 1319 glTranslatef(x_loc, y_loc, 0.0f); 1320 1321 if (effect_pct<= single_image_pct) 1322 { 1323 m_effect_kenBurns_new_image_started=false; 1324 m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f, scale_factor); // 1325 } 1326 else // Fade out image 1327 { 1328 m_texItem[m_texCur ? 0 : 1].MakeQuad(1.0f - ((effect_pct-single_image_pct)*4), scale_factor); 1329 1330 } 1331 1332 m_effect_current_frame++; 1333 } 1334 1181 1335 void GLSingleView::SlideTimeout(void) 1182 1336 { 1183 1337 bool wasMovie = false, isMovie = false; … … 1282 1436 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1283 1437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1284 1438 } 1439 1440 void GLSingleView::LoadImage(QImage image, QSize origSize) 1441 { 1442 m_effect_kenBurns_image = image; 1443 m_effect_kenBurns_orig_image_size = origSize; 1444 } 1445 1446 float GLSingleView::FindMaxScale(float x_loc, float y_loc) 1447 { 1448 // Zoom big enough to keep the entire image on screen when we pan 1449 if (abs(x_loc) > abs(y_loc)) 1450 return abs(x_loc) * 2; 1451 else 1452 return abs(y_loc) * 2; 1453 } 1454 1455 KenBurnsImageLoader::KenBurnsImageLoader(GLSingleView *singleView, ThumbList &itemList, QSize texSize, QSize screenSize) 1456 { 1457 m_singleView = singleView; 1458 m_itemList = itemList; 1459 m_texSize = texSize; 1460 m_screenSize = screenSize; 1461 } 1462 1463 void KenBurnsImageLoader::Initialize(int pos) 1464 { 1465 m_pos = pos; 1466 } 1467 1468 void KenBurnsImageLoader::run() 1469 { 1470 ThumbItem *item = m_itemList.at(m_pos); 1471 if (!item) 1472 { 1473 VERBOSE(VB_IMPORTANT, LOC_ERR + "No item at "<<m_pos); 1474 return; 1475 } 1476 QImage image(item->GetPath()); 1477 if (image.isNull()) 1478 return; 1479 1480 m_singleView->LoadImage(QGLWidget::convertToGLFormat(image.smoothScale(m_texSize)), image.size()); 1481 m_singleView->Ready(); 1482 1483 } -
mythgallery/glsingleview.h
27 27 #include <qgl.h> 28 28 #include <qmap.h> 29 29 #include <qsize.h> 30 #include <QThread> 30 31 31 32 // MythTV plugin headers 32 33 #include <mythtv/util.h> … … 42 43 class QTimer; 43 44 44 45 class GLSingleView; 46 class KenBurnsImageLoader; 45 47 46 48 class GLSDialog : public MythDialog 47 49 { … … 67 69 ~GLSingleView(); 68 70 69 71 void CleanUp(void); 72 void Ready(){m_effect_kenBurns_image_ready = true;} 73 void LoadImage(QImage image, QSize origSize); 74 70 75 71 76 protected: 72 77 void initializeGL(void); … … 104 109 void EffectSlide(void); 105 110 void EffectFlutter(void); 106 111 void EffectCube(void); 107 112 void EffectKenBurns(void); 113 114 private: 115 float FindMaxScale(float x_loc, float y_loc); 116 108 117 private slots: 109 118 void SlideTimeout(void); 110 119 … … 135 144 float m_effect_cube_xrot; 136 145 float m_effect_cube_yrot; 137 146 float m_effect_cube_zrot; 147 float m_effect_kenBurns_location_x[2]; 148 float m_effect_kenBurns_location_y[2]; 149 int m_effect_kenBurns_projection[2]; 150 MythTimer m_effect_kenBurns_image_time[2]; 151 float m_effect_kenBurns_image_timeout_inv; 152 KenBurnsImageLoader *m_effect_kenBurns_imageLoadThread; 153 bool m_effect_kenBurns_image_ready; 154 QImage m_effect_kenBurns_image; 155 QSize m_effect_kenBurns_orig_image_size; 156 ThumbItem *m_effect_kenBurns_item; 157 bool m_effect_kenBurns_initialized; 158 bool m_effect_kenBurns_new_image_started; 159 138 160 }; 139 161 162 class KenBurnsImageLoader : public QThread 163 { 164 public: 165 KenBurnsImageLoader(GLSingleView *singleView, ThumbList &itemList, QSize m_texSize, QSize m_screenSize); 166 void Initialize(int pos); 167 void run(); 168 private: 169 GLSingleView *m_singleView; 170 ThumbList m_itemList; 171 int m_pos; 172 bool m_tex1First; 173 QSize m_screenSize; 174 QSize m_texSize; 175 176 }; 177 140 178 #endif // USING_OPENGL 141 179 #endif // GLSINGLEVIEW_H -
mythgallery/imageview.cpp
136 136 { 137 137 QMap<QString,QString> tmpMap = m_effect_map; 138 138 tmpMap.remove("none"); 139 tmpMap.remove("Ken Burns (gl)"); 139 140 QStringList t = tmpMap.keys(); 140 141 int i = (int) ( (float)(t.count()) * rand() / (RAND_MAX + 1.0f) ); 141 142 return tmpMap[t[i]]; -
mythgallery/gallerysettings.cpp
105 105 gc->addSelection("flutter (gl)"); 106 106 gc->addSelection("cube (gl)"); 107 107 gc->addSelection("random (gl)"); 108 gc->addSelection("Ken Burns (gl)"); 108 109 gc->setHelpText(QObject::tr("This is the type of OpenGL transition used " 109 110 "between pictures in slideshow mode.")); 110 111 return gc; … … 113 114 static HostSpinBox *SlideshowOpenGLTransitionLength() 114 115 { 115 116 HostSpinBox *gc = new HostSpinBox( 116 "SlideshowOpenGLTransitionLength", 500, 10000, 500);117 "SlideshowOpenGLTransitionLength", 500, 30000, 500); 117 118 gc->setLabel(QObject::tr("Duration of OpenGL Transition (milliseconds)")); 118 119 gc->setValue(2000); 119 120 return gc; … … 159 160 160 161 static HostSpinBox *SlideshowDelay() 161 162 { 162 HostSpinBox *gc = new HostSpinBox("SlideshowDelay", 1, 600, 1);163 HostSpinBox *gc = new HostSpinBox("SlideshowDelay", 0, 600, 1); 163 164 gc->setLabel(QObject::tr("Slideshow Delay")); 164 165 gc->setValue(5); 165 166 gc->setHelpText(QObject::tr("This is the number of seconds to display each "
