diff --git a/es-app/src/guis/GuiLaunchScreen.cpp b/es-app/src/guis/GuiLaunchScreen.cpp
index a9e2c08bc..2ea9aa3c5 100644
--- a/es-app/src/guis/GuiLaunchScreen.cpp
+++ b/es-app/src/guis/GuiLaunchScreen.cpp
@@ -160,7 +160,8 @@ void GuiLaunchScreen::displayLaunchScreen(FileData* game)
     // width so that the sizes look somewhat consistent regardless of the aspect ratio
     // of the images.
     if (mImagePath != "") {
-        mMarquee->setImage(game->getMarqueePath(), false, true);
+        mMarquee->setLinearInterpolation(true);
+        mMarquee->setImage(game->getMarqueePath(), false);
         mMarquee->cropTransparentPadding(Renderer::getScreenWidth() *
                                              (0.25f * (1.778f / Renderer::getScreenAspectRatio())),
                                          mGrid->getRowHeight(3));
diff --git a/es-app/src/views/GamelistLegacy.h b/es-app/src/views/GamelistLegacy.h
index 2d13ef8c7..9b5deedd4 100644
--- a/es-app/src/views/GamelistLegacy.h
+++ b/es-app/src/views/GamelistLegacy.h
@@ -45,16 +45,16 @@ void GamelistView::legacyPopulateFields()
 
     // Thumbnails.
     mImageComponents.push_back(std::make_unique<ImageComponent>());
-    mImageComponents.back()->setMetadataField("image_md_thumbnail");
+    mImageComponents.back()->setThemeMetadata("image_md_thumbnail");
     mImageComponents.back()->setOrigin(0.5f, 0.5f);
-    mImageComponents.back()->setVisible(false);
     mImageComponents.back()->setMaxSize(mSize.x * (0.25f - 2.0f * padding), mSize.y * 0.10f);
     mImageComponents.back()->setDefaultZIndex(25.0f);
     addChild(mImageComponents.back().get());
 
     // Marquee.
     mImageComponents.push_back(std::make_unique<ImageComponent>());
-    mImageComponents.back()->setMetadataField("image_md_marquee");
+    mImageComponents.back()->setThemeMetadata("image_md_marquee");
+    mImageComponents.back()->setLinearInterpolation(true);
     mImageComponents.back()->setOrigin(0.5f, 0.5f);
     mImageComponents.back()->setVisible(false);
     mImageComponents.back()->setMaxSize(mSize.x * (0.5f - 2.0f * padding), mSize.y * 0.18f);
@@ -63,7 +63,7 @@ void GamelistView::legacyPopulateFields()
 
     // Image.
     mImageComponents.push_back(std::make_unique<ImageComponent>());
-    mImageComponents.back()->setMetadataField("image_md_image");
+    mImageComponents.back()->setThemeMetadata("image_md_image");
     mImageComponents.back()->setOrigin(0.5f, 0.5f);
     mImageComponents.back()->setPosition(mSize.x * 0.25f,
                                          mList.getPosition().y + mSize.y * 0.2125f);
@@ -74,7 +74,7 @@ void GamelistView::legacyPopulateFields()
     if (mViewStyle == ViewController::VIDEO) {
         // Video.
         mVideoComponents.push_back(std::make_unique<VideoFFmpegComponent>());
-        mVideoComponents.back()->setMetadataField("video_md_video");
+        mVideoComponents.back()->setThemeMetadata("video_md_video");
         mVideoComponents.back()->setOrigin(0.5f, 0.5f);
         mVideoComponents.back()->setPosition(mSize.x * 0.25f,
                                              mList.getPosition().y + mSize.y * 0.2125f);
@@ -91,80 +91,80 @@ void GamelistView::legacyPopulateFields()
     // Metadata labels + values.
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Rating: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_rating");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_rating");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Released: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_releasedate");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_releasedate");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Developer: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_developer");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_developer");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Publisher: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_publisher");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_publisher");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Genre: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_genre");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_genre");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Players: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_players");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_players");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Last played: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_lastplayed");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_lastplayed");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
     mTextComponents.back()->setText("Times played: ", false);
-    mTextComponents.back()->setMetadataField("text_md_lbl_playcount");
+    mTextComponents.back()->setThemeMetadata("text_md_lbl_playcount");
     addChild(mTextComponents.back().get());
 
     mRatingComponents.push_back(std::make_unique<RatingComponent>());
-    mRatingComponents.back()->setMetadataField("rating_md_rating");
+    mRatingComponents.back()->setThemeMetadata("rating_md_rating");
     mRatingComponents.back()->setDefaultZIndex(40.0f);
     addChild(mRatingComponents.back().get());
 
     mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
-    mDateTimeComponents.back()->setMetadataField("datetime_md_releasedate");
+    mDateTimeComponents.back()->setThemeMetadata("datetime_md_releasedate");
     addChild(mDateTimeComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_developer");
+    mTextComponents.back()->setThemeMetadata("text_md_developer");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_publisher");
+    mTextComponents.back()->setThemeMetadata("text_md_publisher");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_genre");
+    mTextComponents.back()->setThemeMetadata("text_md_genre");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_players");
+    mTextComponents.back()->setThemeMetadata("text_md_players");
     addChild(mTextComponents.back().get());
 
     mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
-    mDateTimeComponents.back()->setMetadataField("datetime_md_lastplayed");
+    mDateTimeComponents.back()->setThemeMetadata("datetime_md_lastplayed");
     mDateTimeComponents.back()->setDisplayRelative(true);
     addChild(mDateTimeComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_playcount");
+    mTextComponents.back()->setThemeMetadata("text_md_playcount");
     addChild(mTextComponents.back().get());
 
     mTextComponents.push_back(std::make_unique<TextComponent>());
-    mTextComponents.back()->setMetadataField("text_md_name");
+    mTextComponents.back()->setThemeMetadata("text_md_name");
     mTextComponents.back()->setPosition(mSize.x, mSize.y);
     mTextComponents.back()->setFont(Font::get(FONT_SIZE_MEDIUM));
     mTextComponents.back()->setHorizontalAlignment(ALIGN_CENTER);
@@ -174,7 +174,7 @@ void GamelistView::legacyPopulateFields()
 
     // Badges.
     mBadgeComponents.push_back(std::make_unique<BadgeComponent>());
-    mBadgeComponents.back()->setMetadataField("badges_md_badges");
+    mBadgeComponents.back()->setThemeMetadata("badges_md_badges");
     mBadgeComponents.back()->setOrigin(0.5f, 0.5f);
     mBadgeComponents.back()->setPosition(mSize.x * 0.8f, mSize.y * 0.7f);
     mBadgeComponents.back()->setSize(mSize.x * 0.15f, mSize.y * 0.2f);
@@ -183,7 +183,7 @@ void GamelistView::legacyPopulateFields()
 
     // Scrollable container (game description).
     mContainerComponents.push_back(std::make_unique<ScrollableContainer>());
-    mContainerComponents.back()->setMetadataField("text_md_description");
+    mContainerComponents.back()->setThemeMetadata("text_md_description");
     mContainerComponents.back()->setSize(mSize.x * (0.50f - 2.0f * padding),
                                          mSize.y - mContainerComponents.back()->getPosition().y);
     mContainerComponents.back()->setAutoScroll(true);
@@ -196,7 +196,7 @@ void GamelistView::legacyPopulateFields()
     mContainerComponents.back()->addChild(mTextComponents.back().get());
 
     mGamelistInfoComponents.push_back(std::make_unique<TextComponent>());
-    mGamelistInfoComponents.back()->setMetadataField("text_gamelistInfo");
+    mGamelistInfoComponents.back()->setThemeMetadata("text_gamelistInfo");
     mGamelistInfoComponents.back()->setOrigin(0.5f, 0.5f);
     mGamelistInfoComponents.back()->setFont(Font::get(FONT_SIZE_SMALL));
     mGamelistInfoComponents.back()->setDefaultZIndex(50.0f);
@@ -229,19 +229,19 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
     mList.applyTheme(theme, getName(), "textlist_gamelist", ALL);
 
     mImageComponents[LegacyImage::MD_THUMBNAIL]->applyTheme(
-        theme, getName(), mImageComponents[LegacyImage::MD_THUMBNAIL]->getMetadataField(), ALL);
+        theme, getName(), mImageComponents[LegacyImage::MD_THUMBNAIL]->getThemeMetadata(), ALL);
     mImageComponents[LegacyImage::MD_MARQUEE]->applyTheme(theme, getName(), "image_md_marquee",
                                                           POSITION | ThemeFlags::SIZE | Z_INDEX |
                                                               ROTATION | VISIBLE);
 
     if (mViewStyle == ViewController::DETAILED) {
         mImageComponents[LegacyImage::MD_IMAGE]->applyTheme(
-            theme, getName(), mImageComponents[LegacyImage::MD_IMAGE]->getMetadataField(),
+            theme, getName(), mImageComponents[LegacyImage::MD_IMAGE]->getThemeMetadata(),
             POSITION | ThemeFlags::SIZE | Z_INDEX | ROTATION | VISIBLE);
     }
     else if (mViewStyle == ViewController::VIDEO) {
         mVideoComponents.front()->applyTheme(
-            theme, getName(), mVideoComponents.front()->getMetadataField(),
+            theme, getName(), mVideoComponents.front()->getThemeMetadata(),
             POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX | ROTATION | VISIBLE);
     }
 
@@ -249,31 +249,31 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
     legacyInitMDValues();
 
     mTextComponents[LegacyText::MD_NAME]->applyTheme(
-        theme, getName(), mTextComponents[LegacyText::MD_NAME]->getMetadataField(), ALL);
+        theme, getName(), mTextComponents[LegacyText::MD_NAME]->getThemeMetadata(), ALL);
 
     for (size_t i = 0; i < mBadgeComponents.size(); ++i)
-        mBadgeComponents[i]->applyTheme(theme, getName(), mBadgeComponents[i]->getMetadataField(),
+        mBadgeComponents[i]->applyTheme(theme, getName(), mBadgeComponents[i]->getThemeMetadata(),
                                         ALL);
 
     for (size_t i = 0; i < mRatingComponents.size(); ++i)
-        mRatingComponents[i]->applyTheme(theme, getName(), mRatingComponents[i]->getMetadataField(),
+        mRatingComponents[i]->applyTheme(theme, getName(), mRatingComponents[i]->getThemeMetadata(),
                                          ALL);
 
     mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->applyTheme(
-        theme, getName(), mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->getMetadataField(),
+        theme, getName(), mDateTimeComponents[LegacyDateTime::MD_RELEASEDATE]->getThemeMetadata(),
         ALL);
 
     mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->applyTheme(
-        theme, getName(), mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->getMetadataField(),
+        theme, getName(), mDateTimeComponents[LegacyDateTime::MD_LASTPLAYED]->getThemeMetadata(),
         ALL);
 
     for (size_t i = LegacyText::MD_LBL_RATING; i < LegacyText::MD_NAME; ++i) {
-        mTextComponents[i]->applyTheme(theme, getName(), mTextComponents[i]->getMetadataField(),
+        mTextComponents[i]->applyTheme(theme, getName(), mTextComponents[i]->getThemeMetadata(),
                                        ALL ^ ThemeFlags::TEXT);
     }
 
     for (auto& container : mContainerComponents) {
-        container->applyTheme(theme, getName(), container->getMetadataField(),
+        container->applyTheme(theme, getName(), container->getThemeMetadata(),
                               POSITION | ThemeFlags::SIZE | Z_INDEX | VISIBLE);
     }
 
@@ -284,7 +284,7 @@ void GamelistView::legacyOnThemeChanged(const std::shared_ptr<ThemeData>& theme)
         ALL ^ (POSITION | ThemeFlags::SIZE | ThemeFlags::ORIGIN | TEXT | ROTATION));
 
     for (auto& gamelistInfo : mGamelistInfoComponents)
-        gamelistInfo->applyTheme(theme, getName(), gamelistInfo->getMetadataField(),
+        gamelistInfo->applyTheme(theme, getName(), gamelistInfo->getThemeMetadata(),
                                  ALL ^ ThemeFlags::TEXT);
 
     // If there is no position defined in the theme for gamelistInfo, then hide it.
@@ -379,8 +379,7 @@ void GamelistView::legacyUpdateInfoPanel()
             if (mRandomGame) {
                 mImageComponents[LegacyImage::MD_THUMBNAIL]->setImage(
                     mRandomGame->getThumbnailPath());
-                mImageComponents[LegacyImage::MD_MARQUEE]->setImage(mRandomGame->getMarqueePath(),
-                                                                    false, true);
+                mImageComponents[LegacyImage::MD_MARQUEE]->setImage(mRandomGame->getMarqueePath());
                 if (mViewStyle == ViewController::VIDEO) {
                     mVideoComponents.front()->setImage(mRandomGame->getImagePath());
                     // Always stop the video before setting a new video as it will otherwise
@@ -410,8 +409,7 @@ void GamelistView::legacyUpdateInfoPanel()
         }
         else {
             mImageComponents[LegacyImage::MD_THUMBNAIL]->setImage(file->getThumbnailPath());
-            mImageComponents[LegacyImage::MD_MARQUEE]->setImage(file->getMarqueePath(), false,
-                                                                true);
+            mImageComponents[LegacyImage::MD_MARQUEE]->setImage(file->getMarqueePath());
             if (mViewStyle == ViewController::VIDEO) {
                 mVideoComponents.front()->setImage(file->getImagePath());
                 mVideoComponents.front()->onHide();
diff --git a/es-app/src/views/GamelistView.cpp b/es-app/src/views/GamelistView.cpp
index 5d00fb1e6..c52a34655 100644
--- a/es-app/src/views/GamelistView.cpp
+++ b/es-app/src/views/GamelistView.cpp
@@ -107,7 +107,7 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
                 mImageComponents.push_back(std::make_unique<ImageComponent>());
                 mImageComponents.back()->setDefaultZIndex(30.0f);
                 mImageComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
-                if (mImageComponents.back()->getMetadataField() != "")
+                if (mImageComponents.back()->getThemeImageType() != "")
                     mImageComponents.back()->setScrollHide(true);
                 addChild(mImageComponents.back().get());
             }
@@ -116,7 +116,7 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
                 mVideoComponents.back()->setDefaultZIndex(30.0f);
                 addChild(mVideoComponents.back().get());
                 mVideoComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
-                if (mVideoComponents.back()->getMetadataField() != "")
+                if (mVideoComponents.back()->getThemeImageType() != "")
                     mVideoComponents.back()->setScrollHide(true);
             }
             else if (element.second.type == "animation") {
@@ -155,7 +155,7 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
                     mTextComponents.push_back(std::make_unique<TextComponent>());
                     mTextComponents.back()->setDefaultZIndex(40.0f);
                     mTextComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
-                    if (mTextComponents.back()->getMetadataField() != "")
+                    if (mTextComponents.back()->getThemeMetadata() != "")
                         mTextComponents.back()->setScrollHide(true);
                     addChild(mTextComponents.back().get());
                 }
@@ -164,7 +164,7 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
                 mDateTimeComponents.push_back(std::make_unique<DateTimeComponent>());
                 mDateTimeComponents.back()->setDefaultZIndex(40.0f);
                 mDateTimeComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
-                if (mDateTimeComponents.back()->getMetadataField() != "")
+                if (mDateTimeComponents.back()->getThemeMetadata() != "")
                     mDateTimeComponents.back()->setScrollHide(true);
                 addChild(mDateTimeComponents.back().get());
             }
@@ -342,7 +342,7 @@ void GamelistView::updateInfoPanel()
 
     if (hideMetaDataFields) {
         for (auto& text : mTextComponents) {
-            if (text->getMetadataField() != "")
+            if (text->getThemeMetadata() != "")
                 text->setVisible(false);
         }
         for (auto& date : mDateTimeComponents)
@@ -352,13 +352,13 @@ void GamelistView::updateInfoPanel()
         for (auto& rating : mRatingComponents)
             rating->setVisible(false);
         for (auto& cText : mContainerTextComponents) {
-            if (cText->getMetadataField() != "md_description")
+            if (cText->getThemeMetadata() != "description")
                 cText->setVisible(false);
         }
     }
     else {
         for (auto& text : mTextComponents) {
-            if (text->getMetadataField() != "")
+            if (text->getThemeMetadata() != "")
                 text->setVisible(true);
         }
         for (auto& date : mDateTimeComponents)
@@ -368,7 +368,7 @@ void GamelistView::updateInfoPanel()
         for (auto& rating : mRatingComponents)
             rating->setVisible(true);
         for (auto& cText : mContainerTextComponents) {
-            if (cText->getMetadataField() != "md_description")
+            if (cText->getThemeMetadata() != "description")
                 cText->setVisible(true);
         }
     }
@@ -388,48 +388,48 @@ void GamelistView::updateInfoPanel()
                 file->getSystem());
             if (mRandomGame) {
                 for (auto& image : mImageComponents) {
-                    if (image->getMetadataField() == "md_image")
+                    if (image->getThemeImageType() == "image")
                         image->setImage(mRandomGame->getImagePath());
-                    else if (image->getMetadataField() == "md_miximage")
+                    else if (image->getThemeImageType() == "miximage")
                         image->setImage(mRandomGame->getMiximagePath());
-                    else if (image->getMetadataField() == "md_marquee")
-                        image->setImage(mRandomGame->getMarqueePath(), false, true);
-                    else if (image->getMetadataField() == "md_screenshot")
+                    else if (image->getThemeImageType() == "marquee")
+                        image->setImage(mRandomGame->getMarqueePath());
+                    else if (image->getThemeImageType() == "screenshot")
                         image->setImage(mRandomGame->getScreenshotPath());
-                    else if (image->getMetadataField() == "md_titlescreen")
+                    else if (image->getThemeImageType() == "titlescreen")
                         image->setImage(mRandomGame->getTitleScreenPath());
-                    else if (image->getMetadataField() == "md_cover")
+                    else if (image->getThemeImageType() == "cover")
                         image->setImage(mRandomGame->getCoverPath());
-                    else if (image->getMetadataField() == "md_backcover")
+                    else if (image->getThemeImageType() == "backcover")
                         image->setImage(mRandomGame->getBackCoverPath());
-                    else if (image->getMetadataField() == "md_3dbox")
+                    else if (image->getThemeImageType() == "3dbox")
                         image->setImage(mRandomGame->get3DBoxPath());
-                    else if (image->getMetadataField() == "md_fanart")
+                    else if (image->getThemeImageType() == "fanart")
                         image->setImage(mRandomGame->getFanArtPath());
-                    else if (image->getMetadataField() == "md_thumbnail")
+                    else if (image->getThemeImageType() == "thumbnail")
                         image->setImage(mRandomGame->getThumbnailPath());
                 }
 
                 for (auto& video : mVideoComponents) {
-                    if (video->getMetadataField() == "md_image")
+                    if (video->getThemeImageType() == "image")
                         video->setImage(mRandomGame->getImagePath());
-                    else if (video->getMetadataField() == "md_miximage")
+                    else if (video->getThemeImageType() == "miximage")
                         video->setImage(mRandomGame->getMiximagePath());
-                    else if (video->getMetadataField() == "md_marquee")
-                        video->setImage(mRandomGame->getMarqueePath(), false, true);
-                    else if (video->getMetadataField() == "md_screenshot")
+                    else if (video->getThemeImageType() == "marquee")
+                        video->setImage(mRandomGame->getMarqueePath());
+                    else if (video->getThemeImageType() == "screenshot")
                         video->setImage(mRandomGame->getScreenshotPath());
-                    else if (video->getMetadataField() == "md_titlescreen")
+                    else if (video->getThemeImageType() == "titlescreen")
                         video->setImage(mRandomGame->getTitleScreenPath());
-                    else if (video->getMetadataField() == "md_cover")
+                    else if (video->getThemeImageType() == "cover")
                         video->setImage(mRandomGame->getCoverPath());
-                    else if (video->getMetadataField() == "md_backcover")
+                    else if (video->getThemeImageType() == "backcover")
                         video->setImage(mRandomGame->getBackCoverPath());
-                    else if (video->getMetadataField() == "md_3dbox")
+                    else if (video->getThemeImageType() == "3dbox")
                         video->setImage(mRandomGame->get3DBoxPath());
-                    else if (video->getMetadataField() == "md_fanart")
+                    else if (video->getThemeImageType() == "fanart")
                         video->setImage(mRandomGame->getFanArtPath());
-                    else if (video->getMetadataField() == "md_thumbnail")
+                    else if (video->getThemeImageType() == "thumbnail")
                         video->setImage(mRandomGame->getThumbnailPath());
 
                     // Always stop the video before setting a new video as it will otherwise
@@ -447,7 +447,7 @@ void GamelistView::updateInfoPanel()
             }
             else {
                 for (auto& image : mImageComponents) {
-                    if (image->getMetadataField() != "")
+                    if (image->getThemeImageType() != "")
                         image->setImage("");
                 }
 
@@ -466,48 +466,48 @@ void GamelistView::updateInfoPanel()
         }
         else {
             for (auto& image : mImageComponents) {
-                if (image->getMetadataField() == "md_image")
+                if (image->getThemeImageType() == "image")
                     image->setImage(file->getImagePath());
-                else if (image->getMetadataField() == "md_miximage")
+                else if (image->getThemeImageType() == "miximage")
                     image->setImage(file->getMiximagePath());
-                else if (image->getMetadataField() == "md_marquee")
-                    image->setImage(file->getMarqueePath(), false, true);
-                else if (image->getMetadataField() == "md_screenshot")
+                else if (image->getThemeImageType() == "marquee")
+                    image->setImage(file->getMarqueePath());
+                else if (image->getThemeImageType() == "screenshot")
                     image->setImage(file->getScreenshotPath());
-                else if (image->getMetadataField() == "md_titlescreen")
+                else if (image->getThemeImageType() == "titlescreen")
                     image->setImage(file->getTitleScreenPath());
-                else if (image->getMetadataField() == "md_cover")
+                else if (image->getThemeImageType() == "cover")
                     image->setImage(file->getCoverPath());
-                else if (image->getMetadataField() == "md_backcover")
+                else if (image->getThemeImageType() == "backcover")
                     image->setImage(file->getBackCoverPath());
-                else if (image->getMetadataField() == "md_3dbox")
+                else if (image->getThemeImageType() == "3dbox")
                     image->setImage(file->get3DBoxPath());
-                else if (image->getMetadataField() == "md_fanart")
+                else if (image->getThemeImageType() == "fanart")
                     image->setImage(file->getFanArtPath());
-                else if (image->getMetadataField() == "md_thumbnail")
+                else if (image->getThemeImageType() == "thumbnail")
                     image->setImage(file->getThumbnailPath());
             }
 
             for (auto& video : mVideoComponents) {
-                if (video->getMetadataField() == "md_image")
+                if (video->getThemeImageType() == "image")
                     video->setImage(file->getImagePath());
-                else if (video->getMetadataField() == "md_miximage")
+                else if (video->getThemeImageType() == "miximage")
                     video->setImage(file->getMiximagePath());
-                else if (video->getMetadataField() == "md_marquee")
-                    video->setImage(file->getMarqueePath(), false, true);
-                else if (video->getMetadataField() == "md_screenshot")
+                else if (video->getThemeImageType() == "marquee")
+                    video->setImage(file->getMarqueePath());
+                else if (video->getThemeImageType() == "screenshot")
                     video->setImage(file->getScreenshotPath());
-                else if (video->getMetadataField() == "md_titlescreen")
+                else if (video->getThemeImageType() == "titlescreen")
                     video->setImage(file->getTitleScreenPath());
-                else if (video->getMetadataField() == "md_cover")
+                else if (video->getThemeImageType() == "cover")
                     video->setImage(file->getCoverPath());
-                else if (video->getMetadataField() == "md_backcover")
+                else if (video->getThemeImageType() == "backcover")
                     video->setImage(file->getBackCoverPath());
-                else if (video->getMetadataField() == "md_3dbox")
+                else if (video->getThemeImageType() == "3dbox")
                     video->setImage(file->get3DBoxPath());
-                else if (video->getMetadataField() == "md_fanart")
+                else if (video->getThemeImageType() == "fanart")
                     video->setImage(file->getFanArtPath());
-                else if (video->getMetadataField() == "md_thumbnail")
+                else if (video->getThemeImageType() == "thumbnail")
                     video->setImage(file->getThumbnailPath());
 
                 video->onHide();
@@ -609,23 +609,23 @@ void GamelistView::updateInfoPanel()
         }
 
         for (auto& text : mTextComponents) {
-            if (text->getMetadataField() == "md_name")
+            if (text->getThemeMetadata() == "name")
                 text->setText(file->metadata.get("name"));
         }
 
         if (file->getType() == GAME) {
             if (!hideMetaDataFields) {
                 for (auto& date : mDateTimeComponents) {
-                    if (date->getMetadataField() == "md_lastplayed")
+                    if (date->getThemeMetadata() == "lastplayed")
                         date->setValue(file->metadata.get("lastplayed"));
-                    else if (date->getMetadataField() == "md_playcount")
+                    else if (date->getThemeMetadata() == "playcount")
                         date->setValue(file->metadata.get("playcount"));
                 }
             }
             else if (file->getType() == FOLDER) {
                 if (!hideMetaDataFields) {
                     for (auto& date : mDateTimeComponents) {
-                        if (date->getMetadataField() == "md_lastplayed") {
+                        if (date->getThemeMetadata() == "lastplayed") {
                             date->setValue(file->metadata.get("lastplayed"));
                             date->setVisible(false);
                             date->setVisible(false);
@@ -638,46 +638,46 @@ void GamelistView::updateInfoPanel()
         std::string metadata;
 
         auto getMetadataValue = [&file, &metadata]() -> std::string {
-            if (metadata == "md_name")
+            if (metadata == "name")
                 return file->metadata.get("name");
-            else if (metadata == "md_description")
+            else if (metadata == "description")
                 return file->metadata.get("desc");
-            else if (metadata == "md_developer")
+            else if (metadata == "developer")
                 return file->metadata.get("developer");
-            else if (metadata == "md_publisher")
+            else if (metadata == "publisher")
                 return file->metadata.get("publisher");
-            else if (metadata == "md_genre")
+            else if (metadata == "genre")
                 return file->metadata.get("genre");
-            else if (metadata == "md_players")
+            else if (metadata == "players")
                 return file->metadata.get("players");
-            else if (metadata == "md_favorite")
-                return file->metadata.get("favorite") == "true" ? "Yes" : "No";
-            else if (metadata == "md_completed")
-                return file->metadata.get("completed") == "true" ? "Yes" : "No";
-            else if (metadata == "md_kidgame")
-                return file->metadata.get("kidgame") == "true" ? "Yes" : "No";
-            else if (metadata == "md_broken")
-                return file->metadata.get("broken") == "true" ? "Yes" : "No";
-            else if (metadata == "md_playcount")
+            else if (metadata == "favorite")
+                return file->metadata.get("favorite") == "true" ? "yes" : "no";
+            else if (metadata == "completed")
+                return file->metadata.get("completed") == "true" ? "yes" : "no";
+            else if (metadata == "kidgame")
+                return file->metadata.get("kidgame") == "true" ? "yes" : "no";
+            else if (metadata == "broken")
+                return file->metadata.get("broken") == "true" ? "yes" : "no";
+            else if (metadata == "playcount")
                 return file->metadata.get("playcount");
-            else if (metadata == "md_altemulator")
+            else if (metadata == "altemulator")
                 return file->metadata.get("altemulator");
             else
                 return metadata;
         };
 
         for (auto& text : mContainerTextComponents) {
-            metadata = text->getMetadataField();
+            metadata = text->getThemeMetadata();
             if (metadata == "")
                 continue;
 
-            if (metadata == "md_rating") {
+            if (metadata == "rating") {
                 text->setValue(mRatingComponents.front()->getRatingValue());
                 continue;
             }
-            else if (metadata == "md_controller") {
-                std::string controller =
-                    BadgeComponent::getDisplayName(file->metadata.get("controller"));
+            else if (metadata == "controller") {
+                std::string controller {
+                    BadgeComponent::getDisplayName(file->metadata.get("controller"))};
                 text->setValue(controller == "unknown" ? "" : controller);
                 continue;
             }
@@ -686,15 +686,15 @@ void GamelistView::updateInfoPanel()
         }
 
         for (auto& text : mTextComponents) {
-            metadata = text->getMetadataField();
+            metadata = text->getThemeMetadata();
             if (metadata == "")
                 continue;
 
-            if (metadata == "md_rating") {
+            if (metadata == "rating") {
                 text->setValue(mRatingComponents.front()->getRatingValue());
                 continue;
             }
-            else if (metadata == "md_controller") {
+            else if (metadata == "controller") {
                 std::string controller =
                     BadgeComponent::getDisplayName(file->metadata.get("controller"));
                 text->setValue(controller == "unknown" ? "" : controller);
@@ -705,14 +705,14 @@ void GamelistView::updateInfoPanel()
         }
 
         for (auto& date : mDateTimeComponents) {
-            std::string metadata = date->getMetadataField();
+            std::string metadata = date->getThemeMetadata();
             if (metadata == "")
                 continue;
 
-            if (metadata == "md_releasedate") {
+            if (metadata == "releasedate") {
                 date->setValue(file->metadata.get("releasedate"));
             }
-            else if (metadata == "md_lastplayed") {
+            else if (metadata == "lastplayed") {
                 date->setValue(file->metadata.get("lastplayed"));
             }
             else {
diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp
index 12e2b7b54..46e51e2de 100644
--- a/es-app/src/views/SystemView.cpp
+++ b/es-app/src/views/SystemView.cpp
@@ -348,15 +348,15 @@ void SystemView::populate()
                         elements.imageComponents.back()->setDefaultZIndex(30.0f);
                         elements.imageComponents.back()->applyTheme(theme, "system", element.first,
                                                                     ThemeFlags::ALL);
-                        if (elements.imageComponents.back()->getMetadataField() != "")
+                        if (elements.imageComponents.back()->getThemeImageType() != "")
                             elements.imageComponents.back()->setScrollHide(true);
                         elements.children.emplace_back(elements.imageComponents.back().get());
                     }
                     else if (element.second.type == "text") {
-                        if (element.second.has("metadata") &&
-                            element.second.get<std::string>("metadata").substr(0, 12) ==
-                                "sy_gamecount") {
-                            if (element.second.has("metadata")) {
+                        if (element.second.has("systemdata") &&
+                            element.second.get<std::string>("systemdata").substr(0, 9) ==
+                                "gamecount") {
+                            if (element.second.has("systemdata")) {
                                 elements.gameCountComponents.emplace_back(
                                     std::make_unique<TextComponent>());
                                 elements.gameCountComponents.back()->setDefaultZIndex(40.0f);
@@ -409,13 +409,13 @@ void SystemView::populate()
 
     for (auto& elements : mSystemElements) {
         for (auto& text : elements.textComponents) {
-            if (text->getMetadataField() != "") {
-                if (text->getMetadataField() == "sy_name")
+            if (text->getThemeSystemdata() != "") {
+                if (text->getThemeSystemdata() == "name")
                     text->setValue(elements.name);
-                else if (text->getMetadataField() == "sy_fullname")
+                else if (text->getThemeSystemdata() == "fullname")
                     text->setValue(elements.fullName);
                 else
-                    text->setValue(text->getMetadataField());
+                    text->setValue(text->getThemeSystemdata());
             }
         }
     }
@@ -470,20 +470,20 @@ void SystemView::updateGameCount()
     }
     else {
         for (auto& gameCount : mSystemElements[mCarousel->getCursor()].gameCountComponents) {
-            if (gameCount->getMetadataField() == "sy_gamecount") {
+            if (gameCount->getThemeSystemdata() == "gamecount") {
                 gameCount->setValue(ss.str());
             }
-            else if (gameCount->getMetadataField() == "sy_gamecount_games") {
+            else if (gameCount->getThemeSystemdata() == "gamecount_games") {
                 if (games)
                     gameCount->setValue(ssGames.str());
                 else
                     gameCount->setValue(ss.str());
             }
-            else if (gameCount->getMetadataField() == "sy_gamecount_favorites") {
+            else if (gameCount->getThemeSystemdata() == "gamecount_favorites") {
                 gameCount->setValue(ssFavorites.str());
             }
             else {
-                gameCount->setValue(gameCount->getMetadataField());
+                gameCount->setValue(gameCount->getThemeSystemdata());
             }
         }
     }
diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h
index fb690b8e6..544c5d2d5 100644
--- a/es-core/src/GuiComponent.h
+++ b/es-core/src/GuiComponent.h
@@ -211,8 +211,12 @@ public:
     virtual bool getEnabled() { return mEnabled; }
     virtual void setEnabled(bool state) { mEnabled = state; }
 
-    std::string getMetadataField() { return mMetadataField; }
-    void setMetadataField(const std::string& text) { mMetadataField = text; }
+    const std::string getThemeSystemdata() { return mThemeSystemdata; }
+    void setThemeSystemdata(const std::string& text) { mThemeSystemdata = text; }
+    const std::string getThemeMetadata() { return mThemeMetadata; }
+    void setThemeMetadata(const std::string& text) { mThemeMetadata = text; }
+    const std::string getThemeImageType() { return mThemeImageType; }
+    void setThemeImageType(const std::string& text) { mThemeImageType = text; }
 
     virtual std::shared_ptr<Font> getFont() const { return nullptr; }
 
@@ -275,7 +279,9 @@ protected:
     GuiComponent* mParent;
     std::vector<GuiComponent*> mChildren;
 
-    std::string mMetadataField;
+    std::string mThemeSystemdata;
+    std::string mThemeMetadata;
+    std::string mThemeImageType;
 
     unsigned int mColor;
     float mSaturation;
diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp
index 88397bfdc..2b4c83109 100644
--- a/es-core/src/ThemeData.cpp
+++ b/es-core/src/ThemeData.cpp
@@ -89,7 +89,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
        {"path", PATH},
        {"default", PATH},
        {"tile", BOOLEAN},
-       {"metadata", STRING},
+       {"imageType", STRING},
+       {"interpolation", STRING},
        {"color", COLOR},
        {"colorEnd", COLOR},
        {"gradientType", STRING},
@@ -107,7 +108,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
        {"path", PATH},
        {"default", PATH},
        {"defaultImage", PATH},
-       {"imageMetadata", STRING},
+       {"imageType", STRING},
+       {"interpolation", STRING},
        {"pillarboxes", BOOLEAN},
        {"scanlines", BOOLEAN},
        {"delay", FLOAT},
@@ -157,6 +159,7 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
        {"rotation", FLOAT},
        {"rotationOrigin", NORMALIZED_PAIR},
        {"text", STRING},
+       {"systemdata", STRING},
        {"metadata", STRING},
        {"container", BOOLEAN},
        {"containerScrollSpeed", FLOAT},
diff --git a/es-core/src/components/CarouselComponent.cpp b/es-core/src/components/CarouselComponent.cpp
index e8a208a0e..c651799fb 100644
--- a/es-core/src/components/CarouselComponent.cpp
+++ b/es-core/src/components/CarouselComponent.cpp
@@ -71,7 +71,7 @@ void CarouselComponent::addEntry(const std::shared_ptr<ThemeData>& theme,
         if (entry.data.logoPath != "" &&
             ResourceManager::getInstance().fileExists(entry.data.logoPath)) {
             auto logo = std::make_shared<ImageComponent>(false, false);
-            logo->setImage(entry.data.logoPath, false, false);
+            logo->setImage(entry.data.logoPath);
             logo->setMaxSize(glm::round(mLogoSize * mLogoScale));
             logo->applyTheme(theme, "system", "", ThemeFlags::ALL);
             logo->setRotateByTargetSize(true);
@@ -80,7 +80,7 @@ void CarouselComponent::addEntry(const std::shared_ptr<ThemeData>& theme,
         else if (entry.data.defaultLogoPath != "" &&
                  ResourceManager::getInstance().fileExists(entry.data.defaultLogoPath)) {
             auto defaultLogo = std::make_shared<ImageComponent>(false, false);
-            defaultLogo->setImage(entry.data.defaultLogoPath, false, false);
+            defaultLogo->setImage(entry.data.defaultLogoPath);
             defaultLogo->setMaxSize(glm::round(mLogoSize * mLogoScale));
             defaultLogo->applyTheme(theme, "system", "", ThemeFlags::ALL);
             defaultLogo->setRotateByTargetSize(true);
diff --git a/es-core/src/components/DateTimeComponent.cpp b/es-core/src/components/DateTimeComponent.cpp
index 87e78d0f1..b86d7e601 100644
--- a/es-core/src/components/DateTimeComponent.cpp
+++ b/es-core/src/components/DateTimeComponent.cpp
@@ -173,9 +173,9 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
     }
 
     if (properties & METADATA && elem->has("metadata"))
-        setMetadataField(elem->get<std::string>("metadata"));
+        mThemeMetadata = elem->get<std::string>("metadata");
 
-    if (mMetadataField == "md_lastplayed")
+    if (mThemeMetadata == "lastplayed")
         setDisplayRelative(true);
 
     if (elem->has("displayRelative"))
@@ -204,7 +204,7 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
         setUppercase(elem->get<bool>("forceUppercase"));
 
     if (properties & LINE_SPACING && elem->has("lineSpacing"))
-        setLineSpacing(elem->get<float>("lineSpacing"));
+        setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
 
     setFont(Font::getFromTheme(elem, properties, mFont));
 }
diff --git a/es-core/src/components/ImageComponent.cpp b/es-core/src/components/ImageComponent.cpp
index 50d6ab2dd..cc2ced6c7 100644
--- a/es-core/src/components/ImageComponent.cpp
+++ b/es-core/src/components/ImageComponent.cpp
@@ -42,6 +42,7 @@ ImageComponent::ImageComponent(bool forceLoad, bool dynamic)
     , mForceLoad {forceLoad}
     , mDynamic {dynamic}
     , mRotateByTargetSize {false}
+    , mLinearInterpolation {false}
     , mTopLeftCrop {0.0f, 0.0f}
     , mBottomRightCrop {1.0f, 1.0f}
 {
@@ -132,7 +133,7 @@ void ImageComponent::resize()
     onSizeChanged();
 }
 
-void ImageComponent::setImage(const std::string& path, bool tile, bool linearMagnify)
+void ImageComponent::setImage(const std::string& path, bool tile)
 {
     // Always load bundled graphic resources statically, unless mForceLoad has been set.
     // This eliminates annoying texture pop-in problems that would otherwise occur.
@@ -144,11 +145,11 @@ void ImageComponent::setImage(const std::string& path, bool tile, bool linearMag
         if (mDefaultPath.empty() || !ResourceManager::getInstance().fileExists(mDefaultPath))
             mTexture.reset();
         else
-            mTexture =
-                TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic, linearMagnify);
+            mTexture = TextureResource::get(mDefaultPath, tile, mForceLoad, mDynamic,
+                                            mLinearInterpolation);
     }
     else {
-        mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, linearMagnify);
+        mTexture = TextureResource::get(path, tile, mForceLoad, mDynamic, mLinearInterpolation);
     }
 
     resize();
@@ -497,6 +498,22 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
             setMinSize(elem->get<glm::vec2>("minSize") * scale);
     }
 
+    if (elem->has("interpolation")) {
+        const std::string interpolation {elem->get<std::string>("interpolation")};
+        if (interpolation == "linear") {
+            mLinearInterpolation = true;
+        }
+        else if (interpolation == "nearest") {
+            mLinearInterpolation = false;
+        }
+        else {
+            mLinearInterpolation = false;
+            LOG(LogWarning) << "ImageComponent: Invalid theme configuration, property "
+                               "<interpolation> set to \""
+                            << interpolation << "\"";
+        }
+    }
+
     if (elem->has("default"))
         setDefaultImage(elem->get<std::string>("default"));
 
@@ -505,8 +522,8 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
         setImage(elem->get<std::string>("path"), tile);
     }
 
-    if (properties & METADATA && elem->has("metadata"))
-        setMetadataField(elem->get<std::string>("metadata"));
+    if (properties & METADATA && elem->has("imageType"))
+        mThemeImageType = elem->get<std::string>("imageType");
 
     if (properties & COLOR) {
         if (elem->has("color"))
diff --git a/es-core/src/components/ImageComponent.h b/es-core/src/components/ImageComponent.h
index 9faabfac0..0a8c5c242 100644
--- a/es-core/src/components/ImageComponent.h
+++ b/es-core/src/components/ImageComponent.h
@@ -24,7 +24,7 @@ public:
 
     // Loads the image at the given filepath. Will tile if tile is true (retrieves texture
     // as tiling, creates vertices accordingly).
-    void setImage(const std::string& path, bool tile = false, bool linearMagnify = false);
+    void setImage(const std::string& path, bool tile = false);
     // Loads an image from memory.
     void setImage(const char* data, size_t length, bool tile = false);
     // Use an already existing texture.
@@ -79,6 +79,8 @@ public:
 
     // Flag indicating if rotation should be based on target size vs. actual size.
     void setRotateByTargetSize(bool rotate) { mRotateByTargetSize = rotate; }
+    // Whether to use smooth texture magnification by utilizing linear interpolation.
+    void setLinearInterpolation(bool state) { mLinearInterpolation = state; }
 
     // Returns the size of the current texture, or (0, 0) if none is loaded.
     // May be different than drawn size (use getSize() for that).
@@ -129,6 +131,7 @@ private:
     bool mForceLoad;
     bool mDynamic;
     bool mRotateByTargetSize;
+    bool mLinearInterpolation;
 
     glm::vec2 mTopLeftCrop;
     glm::vec2 mBottomRightCrop;
diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp
index 77cc15679..eb2578172 100644
--- a/es-core/src/components/TextComponent.cpp
+++ b/es-core/src/components/TextComponent.cpp
@@ -427,8 +427,11 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
     if (properties & TEXT && elem->has("text"))
         setText(elem->get<std::string>("text"));
 
+    if (properties & METADATA && elem->has("systemdata"))
+        mThemeSystemdata = elem->get<std::string>("systemdata");
+
     if (properties & METADATA && elem->has("metadata"))
-        setMetadataField(elem->get<std::string>("metadata"));
+        mThemeMetadata = elem->get<std::string>("metadata");
 
     if (properties & LETTER_CASE && elem->has("letterCase")) {
         std::string letterCase {elem->get<std::string>("letterCase")};
@@ -453,7 +456,7 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
         setUppercase(elem->get<bool>("forceUppercase"));
 
     if (properties & LINE_SPACING && elem->has("lineSpacing"))
-        setLineSpacing(elem->get<float>("lineSpacing"));
+        setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
 
     setFont(Font::getFromTheme(elem, properties, mFont));
 }
diff --git a/es-core/src/components/TextListComponent.h b/es-core/src/components/TextListComponent.h
index c4052de83..74b4d6636 100644
--- a/es-core/src/components/TextListComponent.h
+++ b/es-core/src/components/TextListComponent.h
@@ -561,7 +561,7 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
 
     if (properties & LINE_SPACING) {
         if (elem->has("lineSpacing"))
-            setLineSpacing(elem->get<float>("lineSpacing"));
+            setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
         if (elem->has("selectorHeight"))
             setSelectorHeight(elem->get<float>("selectorHeight") * Renderer::getScreenHeight());
         if (elem->has("selectorOffsetY")) {
diff --git a/es-core/src/components/VideoComponent.cpp b/es-core/src/components/VideoComponent.cpp
index 6f5769f57..29c7d6768 100644
--- a/es-core/src/components/VideoComponent.cpp
+++ b/es-core/src/components/VideoComponent.cpp
@@ -44,7 +44,7 @@ VideoComponent::VideoComponent()
     // Setup the default configuration.
     mConfig.showSnapshotDelay = false;
     mConfig.showSnapshotNoVideo = false;
-    mConfig.startDelay = 0;
+    mConfig.startDelay = 1500;
 
     if (mWindow->getGuiStackSize() > 1)
         topWindow(false);
@@ -78,13 +78,13 @@ bool VideoComponent::setVideo(std::string path)
     return false;
 }
 
-void VideoComponent::setImage(const std::string& path, bool tile, bool linearMagnify)
+void VideoComponent::setImage(const std::string& path, bool tile)
 {
     // Check that the image has changed.
     if (path == mStaticImagePath)
         return;
 
-    mStaticImage.setImage(path, tile, linearMagnify);
+    mStaticImage.setImage(path, tile);
     mStaticImagePath = path;
 }
 
@@ -246,6 +246,22 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
             mVideoAreaPos = elem->get<glm::vec2>("pos") * scale;
     }
 
+    if (elem->has("interpolation")) {
+        const std::string interpolation {elem->get<std::string>("interpolation")};
+        if (interpolation == "linear") {
+            mStaticImage.setLinearInterpolation(true);
+        }
+        else if (interpolation == "nearest") {
+            mStaticImage.setLinearInterpolation(false);
+        }
+        else {
+            mStaticImage.setLinearInterpolation(false);
+            LOG(LogWarning) << "ImageComponent: Invalid theme configuration, property "
+                               "<interpolation> set to \""
+                            << interpolation << "\"";
+        }
+    }
+
     if (elem->has("default"))
         mConfig.defaultVideoPath = elem->get<std::string>("default");
 
@@ -258,7 +274,8 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
         mConfig.staticVideoPath = elem->get<std::string>("path");
 
     if ((properties & ThemeFlags::DELAY) && elem->has("delay"))
-        mConfig.startDelay = static_cast<unsigned>((elem->get<float>("delay") * 1000.0f));
+        mConfig.startDelay =
+            static_cast<unsigned int>(glm::clamp(elem->get<float>("delay"), 0.0f, 15.0f) * 1000.0f);
 
     if (!theme->isLegacyTheme())
         mConfig.showSnapshotNoVideo = true;
@@ -270,8 +287,8 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
     else if (elem->has("showSnapshotDelay"))
         mConfig.showSnapshotDelay = elem->get<bool>("showSnapshotDelay");
 
-    if (properties & METADATA && elem->has("imageMetadata"))
-        setMetadataField(elem->get<std::string>("imageMetadata"));
+    if (properties & METADATA && elem->has("imageType"))
+        mThemeImageType = elem->get<std::string>("imageType");
 
     if (elem->has("pillarboxes"))
         mDrawPillarboxes = elem->get<bool>("pillarboxes");
diff --git a/es-core/src/components/VideoComponent.h b/es-core/src/components/VideoComponent.h
index 4cde87992..89ad4b94f 100644
--- a/es-core/src/components/VideoComponent.h
+++ b/es-core/src/components/VideoComponent.h
@@ -40,7 +40,7 @@ public:
     // Configures the component to show the static video.
     void setStaticVideo() { setVideo(mConfig.staticVideoPath); }
     // Loads a static image that is displayed if the video cannot be played.
-    void setImage(const std::string& path, bool tile = false, bool linearMagnify = false);
+    void setImage(const std::string& path, bool tile = false);
     // Sets whether we're in media viewer mode.
     void setMediaViewerMode(bool isMediaViewer) { mMediaViewerMode = isMediaViewer; }
     // Sets whether we're in screensaver mode.