summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY6
-rw-r--r--Makefile2
-rw-r--r--baserender.c17
-rw-r--r--displaychannel.c59
-rw-r--r--displaymenu.c73
-rw-r--r--displayreplay.c51
-rw-r--r--displayvolume.c5
-rw-r--r--flat.c1
-rw-r--r--flat.h3
-rw-r--r--imagecache.c52
-rw-r--r--imagecache.h25
-rw-r--r--imageloader.c114
-rw-r--r--imageloader.h25
-rw-r--r--imagemagickwrapper.c87
-rw-r--r--imagemagickwrapper.h23
-rw-r--r--imagescaler.c149
-rw-r--r--imagescaler.h97
-rw-r--r--po/de_DE.po2
-rw-r--r--skinflatplus.c5
19 files changed, 635 insertions, 161 deletions
diff --git a/HISTORY b/HISTORY
index d7ac5290..cdc42df6 100644
--- a/HISTORY
+++ b/HISTORY
@@ -9,11 +9,13 @@ VDR Plugin 'skinflatplus' Revision History
- [fix] remove button border if button is not shown
- [fix] menuitem progressbar overlay itemtext
- [fix] fixes in TopBar while icon set
-- [add] add support for menu SetItemChannel
-- [add] add support for menu SetItemTimer
- [update] add Patch from MegaV0lt, support for simple aspect & format, new icons
- [update] only log not loaded images
- [update] imageloader logging
+- [add] add support for menu SetItemChannel
+- [add] add support for menu SetItemTimer
+- [add] imagescaler from skin nopacity (thank you!)
+- [add] imagecache for faster image loading
2013-11-24: Version 0.1.0 - MegaV0lt Version
Special thanks to MegaV0lt@VDR-Portal for
diff --git a/Makefile b/Makefile
index 687bc748..72c18fdf 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@ LIBS += $(shell pkg-config --libs Magick++)
### The object files (add further files here):
-OBJS = config.o setup.o imageloader.o baserender.o displaychannel.o displaymenu.o displaymessage.o \
+OBJS = config.o setup.o imagecache.o imagescaler.o imagemagickwrapper.o imageloader.o baserender.o displaychannel.o displaymenu.o displaymessage.o \
displayreplay.o displaytracks.o displayvolume.o flat.o $(PLUGIN).o
### The main target:
diff --git a/baserender.c b/baserender.c
index 2d9cbcfd..0ab832a4 100644
--- a/baserender.c
+++ b/baserender.c
@@ -170,9 +170,11 @@ void cFlatBaseRender::TopBarUpdate(void) {
topBarIconPixmap->Fill(clrTransparent);
if( topBarExtraIconSet ) {
int extraIconLeft = extraLeft + extraMaxWidth + marginItem;
- if (imgLoader.LoadIcon(*topBarExtraIcon, 999, topBarHeight)) {
- int iconTop = topBarHeight / 2 - imgLoader.Height()/2;
- topBarIconPixmap->DrawImage(cPoint(extraIconLeft, iconTop), imgLoader.GetImage());
+// if (imgLoader.LoadIcon(*topBarExtraIcon, 999, topBarHeight)) {
+ cImage *img = imgLoader.LoadIcon(*topBarExtraIcon, 999, topBarHeight);
+ if( img ) {
+ int iconTop = 0;
+ topBarIconPixmap->DrawImage(cPoint(extraIconLeft, iconTop), *img);
RecLeft += topBarHeight + marginItem;
}
@@ -180,10 +182,11 @@ void cFlatBaseRender::TopBarUpdate(void) {
if( topBarMenuIconSet && Config.TopBarMenuIconShow ) {
int IconLeft = marginItem;
- if (imgLoader.LoadIcon(*topBarMenuIcon, 999, topBarHeight - marginItem*2)) {
- int iconTop = (topBarHeight / 2 - imgLoader.Height()/2);
- topBarIconPixmap->DrawImage(cPoint(IconLeft, iconTop), imgLoader.GetImage());
- MenuIconWidth = imgLoader.Width()+marginItem*2;
+ cImage *img = imgLoader.LoadIcon(*topBarMenuIcon, 999, topBarHeight - marginItem*2);
+ if( img ) {
+ int iconTop = (topBarHeight / 2 - img->Height()/2);
+ topBarIconPixmap->DrawImage(cPoint(IconLeft, iconTop), *img);
+ MenuIconWidth = img->Width()+marginItem*2;
TitleWidthLeft -= MenuIconWidth + marginItem*3;
}
}
diff --git a/displaychannel.c b/displaychannel.c
index af6567d8..5bf02c55 100644
--- a/displaychannel.c
+++ b/displaychannel.c
@@ -112,20 +112,23 @@ void cFlatDisplayChannel::SetChannel(const cChannel *Channel, int Number) {
chanInfoTopPixmap->Fill(Theme.Color(clrChannelBg));
chanInfoTopPixmap->DrawText(cPoint(50, 0), channelString, Theme.Color(clrChannelFontTitle), Theme.Color(clrChannelBg), font);
+ chanLogoPixmap->Fill(clrTransparent);
int imageHeight = heightImageLogo - marginItem*2;
int imageLeft = marginItem*2;
int imageTop = marginItem;
- if( imgLoader.LoadLogo(*channelName, imageHeight, imageHeight) ) {
-
- chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ cImage *img = imgLoader.LoadLogo(*channelName, imageHeight, imageHeight);
+ if( img ) {
+ chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
} else if( !isGroup ) { // draw default logo
if( isRadioChannel ) {
- if( imgLoader.LoadIcon("radio", imageHeight, imageHeight) ) {
- chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("radio", imageHeight, imageHeight);
+ if( img ) {
+ chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
}
} else {
- if( imgLoader.LoadIcon("tv", imageHeight, imageHeight) ) {
- chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("tv", imageHeight, imageHeight);
+ if( img ) {
+ chanLogoPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
}
}
}
@@ -140,6 +143,7 @@ void cFlatDisplayChannel::ChannelIconsDraw(const cChannel *Channel, bool Resolut
int top = fontHeight*2 + fontSmlHeight*2 + marginItem;
int height = fontSmlHeight;
int imageTop = 0;
+ cImage *img = NULL;
if( Config.SignalQualityShow ) {
top += max(fontSmlHeight, Config.decorProgressSignalSize) / 2 - fontSmlHeight / 2;
@@ -151,15 +155,17 @@ void cFlatDisplayChannel::ChannelIconsDraw(const cChannel *Channel, bool Resolut
if( Channel ) {
if (Channel->Ca()) {
- if (imgLoader.LoadIcon("crypted", 999, height)) {
- imageTop = top + (height - imgLoader.Height())/2;
- chanIconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon("crypted", 999, height);
+ if( img ) {
+ imageTop = top + (height - img->Height())/2;
+ chanIconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
} else {
- if (imgLoader.LoadIcon("uncrypted", 999, height)) {
- imageTop = top + (height - imgLoader.Height())/2;
- chanIconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon("uncrypted", 999, height);
+ if( img ) {
+ imageTop = top + (height - img->Height())/2;
+ chanIconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
@@ -178,10 +184,11 @@ void cFlatDisplayChannel::ChannelIconsDraw(const cChannel *Channel, bool Resolut
else if( screenAspect == 2.21 )
asp = "221";
}
- if (imgLoader.LoadIcon(*asp, 999, height)) {
- imageTop = top + (height - imgLoader.Height())/2;
- left -= imgLoader.Width();
- chanIconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*asp, 999, height);
+ if( img ) {
+ imageTop = top + (height - img->Height())/2;
+ left -= img->Width();
+ chanIconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
@@ -223,10 +230,11 @@ void cFlatDisplayChannel::ChannelIconsDraw(const cChannel *Channel, bool Resolut
break;
}
- if (imgLoader.LoadIcon(*res, 999, height)) {
- imageTop = top + (height - imgLoader.Height())/2;
- left -= imgLoader.Width();
- chanIconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*res, 999, height);
+ if( img ) {
+ imageTop = top + (height - img->Height())/2;
+ left -= img->Width();
+ chanIconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
@@ -246,10 +254,11 @@ void cFlatDisplayChannel::ChannelIconsDraw(const cChannel *Channel, bool Resolut
break;
}
- if (imgLoader.LoadIcon(*iconName, 999, height)) {
- imageTop = top + (height - imgLoader.Height())/2;
- left -= imgLoader.Width();
- chanIconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*iconName, 999, height);
+ if( img ) {
+ imageTop = top + (height - img->Height())/2;
+ left -= img->Width();
+ chanIconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
diff --git a/displaymenu.c b/displaymenu.c
index 840851f5..a2358515 100644
--- a/displaymenu.c
+++ b/displaymenu.c
@@ -396,11 +396,13 @@ void cFlatDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool S
if( (menuCategory == mcMain || menuCategory == mcSetup) && Config.MenuItemIconsShow) {
cString cIcon = GetIconName( MainMenuText(s) );
cImageLoader imgLoader;
- if (imgLoader.LoadIcon(*cIcon, fontHeight - marginItem*2)) {
- menuIconsPixmap->DrawImage(cPoint(xt + Config.decorBorderMenuItemSize + marginItem, y + marginItem), imgLoader.GetImage());
+ cImage *img = imgLoader.LoadIcon(*cIcon, fontHeight - marginItem*2, fontHeight - marginItem*2);
+ if( img ) {
+ menuIconsPixmap->DrawImage(cPoint(xt + Config.decorBorderMenuItemSize + marginItem, y + marginItem), *img);
} else {
- if (imgLoader.LoadIcon("menuIcons/blank", fontHeight)) {
- menuIconsPixmap->DrawImage(cPoint(xt + Config.decorBorderMenuItemSize + marginItem, y + marginItem), imgLoader.GetImage());
+ img = imgLoader.LoadIcon("menuIcons/blank", fontHeight - marginItem*2, fontHeight - marginItem*2);
+ if( img ) {
+ menuIconsPixmap->DrawImage(cPoint(xt + Config.decorBorderMenuItemSize + marginItem, y + marginItem), *img);
}
}
menuPixmap->DrawText(cPoint(fontHeight + marginItem*2 + xt + Config.decorBorderMenuItemSize, y), s, ColorFg, ColorBg, font,
@@ -627,29 +629,33 @@ bool cFlatDisplayMenu::SetItemChannel(const cChannel *Channel, int Index, bool C
int imageHeight = fontHeight;
int imageLeft = Left;
int imageTop = Top;
- if( imgLoader.LoadLogo(Channel->Name(), imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ cImage *img = imgLoader.LoadLogo(Channel->Name(), imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
} else {
bool isRadioChannel = ((!Channel->Vpid())&&(Channel->Apid(0))) ? true : false;
if( isRadioChannel ) {
- if( imgLoader.LoadIcon("radio", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("radio", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
} else if( Channel->GroupSep() ) {
- if( imgLoader.LoadIcon("changroup", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("changroup", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
} else {
- if( imgLoader.LoadIcon("tv", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("tv", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
}
@@ -926,9 +932,10 @@ bool cFlatDisplayMenu::SetItemTimer(const cTimer *Timer, int Index, bool Current
} else
TimerIconName = "timerActive";
- if( imgLoader.LoadIcon(TimerIconName, imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ cImage *img = imgLoader.LoadIcon(TimerIconName, imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
@@ -943,29 +950,33 @@ bool cFlatDisplayMenu::SetItemTimer(const cTimer *Timer, int Index, bool Current
imageLeft = Left;
- if( imgLoader.LoadLogo(Channel->Name(), imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadLogo(Channel->Name(), imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
} else {
bool isRadioChannel = ((!Channel->Vpid())&&(Channel->Apid(0))) ? true : false;
if( isRadioChannel ) {
- if( imgLoader.LoadIcon("radio", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("radio", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
} else if( Channel->GroupSep() ) {
- if( imgLoader.LoadIcon("changroup", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("changroup", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
} else {
- if( imgLoader.LoadIcon("tv", imageHeight, imageHeight) ) {
- imageTop = Top + (fontHeight - imgLoader.Height()) / 2;
- menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon("tv", imageHeight, imageHeight);
+ if( img ) {
+ imageTop = Top + (fontHeight - img->Height()) / 2;
+ menuIconsPixmap->DrawImage( cPoint(imageLeft, imageTop), *img );
Left += imageHeight + marginItem * 2;
}
}
diff --git a/displayreplay.c b/displayreplay.c
index 6d9a8b0b..c6ec4225 100644
--- a/displayreplay.c
+++ b/displayreplay.c
@@ -93,15 +93,21 @@ void cFlatDisplayReplay::SetMode(bool Play, bool Forward, int Speed) {
labelPixmap->DrawText(cPoint(left - font->Width(speed) - marginItem, 0), speed, Theme.Color(clrReplayFontSpeed), Theme.Color(clrReplayBg), font);
}
}
+ cImage *img = imgLoader.LoadIcon(*rewind, fontHeight, fontHeight);
+ if( img )
+ iconsPixmap->DrawImage( cPoint(left, 0), *img );
- if( imgLoader.LoadIcon(*rewind, fontHeight, fontHeight) )
- iconsPixmap->DrawImage( cPoint(left, 0), imgLoader.GetImage() );
- if( imgLoader.LoadIcon(*pause, fontHeight, fontHeight) )
- iconsPixmap->DrawImage( cPoint(left + fontHeight + marginItem, 0), imgLoader.GetImage() );
- if( imgLoader.LoadIcon(*play, fontHeight, fontHeight) )
- iconsPixmap->DrawImage( cPoint(left + fontHeight*2 + marginItem*2, 0), imgLoader.GetImage() );
- if( imgLoader.LoadIcon(*forward, fontHeight, fontHeight) )
- iconsPixmap->DrawImage( cPoint(left + fontHeight*3 + marginItem*3, 0), imgLoader.GetImage() );
+ img = imgLoader.LoadIcon(*pause, fontHeight, fontHeight);
+ if( img )
+ iconsPixmap->DrawImage( cPoint(left + fontHeight + marginItem, 0), *img );
+
+ img = imgLoader.LoadIcon(*play, fontHeight, fontHeight);
+ if( img )
+ iconsPixmap->DrawImage( cPoint(left + fontHeight*2 + marginItem*2, 0), *img );
+
+ img = imgLoader.LoadIcon(*forward, fontHeight, fontHeight);
+ if( img )
+ iconsPixmap->DrawImage( cPoint(left + fontHeight*3 + marginItem*3, 0), *img );
}
@@ -160,6 +166,8 @@ void cFlatDisplayReplay::SetJump(const char *Jump) {
void cFlatDisplayReplay::ResolutionAspectDraw(void) {
int left = osdWidth - Config.decorBorderReplaySize*2;
int imageTop = 0;
+ cImage *img = NULL;
+
if( screenWidth > 0 ) {
if( Config.RecordingResolutionAspectShow ) { // Show Aspect
cString asp = "unknown_asp"; // ???
@@ -173,10 +181,11 @@ void cFlatDisplayReplay::ResolutionAspectDraw(void) {
else if( screenAspect == 2.21 )
asp = "221";
}
- if (imgLoader.LoadIcon(*asp, 999, fontSmlHeight)) {
- imageTop = fontHeight + (fontSmlHeight - imgLoader.Height())/2;
- left -= imgLoader.Width();
- iconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*asp, 999, fontSmlHeight);
+ if( img ) {
+ imageTop = fontHeight + (fontSmlHeight - img->Height())/2;
+ left -= img->Width();
+ iconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
@@ -219,10 +228,11 @@ void cFlatDisplayReplay::ResolutionAspectDraw(void) {
//printf("Width: %d Height: %d Aspect: %.2f\n", screenWidth, screenHeight, screenAspect);
- if (imgLoader.LoadIcon(*res, 999, fontSmlHeight)) {
- imageTop = fontHeight + (fontSmlHeight - imgLoader.Height())/2;
- left -= imgLoader.Width();
- iconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*res, 999, fontSmlHeight);
+ if (img) {
+ imageTop = fontHeight + (fontSmlHeight - img->Height())/2;
+ left -= img->Width();
+ iconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2;
}
}
@@ -242,10 +252,11 @@ void cFlatDisplayReplay::ResolutionAspectDraw(void) {
break;
}
- if (imgLoader.LoadIcon(*iconName, 999, fontSmlHeight)) {
- imageTop = fontHeight + (fontSmlHeight - imgLoader.Height())/2;
- left -= imgLoader.Width();
- iconsPixmap->DrawImage(cPoint(left, imageTop), imgLoader.GetImage());
+ img = imgLoader.LoadIcon(*iconName, 999, fontSmlHeight);
+ if( img ) {
+ imageTop = fontHeight + (fontSmlHeight - img->Height())/2;
+ left -= img->Width();
+ iconsPixmap->DrawImage(cPoint(left, imageTop), *img);
left -= marginItem*2 ;
}
}
diff --git a/displayvolume.c b/displayvolume.c
index cc2aee73..f9daaf1d 100644
--- a/displayvolume.c
+++ b/displayvolume.c
@@ -44,8 +44,9 @@ void cFlatDisplayVolume::SetVolume(int Current, int Total, bool Mute) {
if (Mute) {
labelPixmap->DrawText(cPoint(left, marginItem), *label, Theme.Color(clrVolumeFont), Theme.Color(clrVolumeBg),
font, maxlabelWidth + marginItem + labelHeight, fontHeight, taLeft);
- if( imgLoader.LoadIcon("mute", fontHeight, fontHeight) ) {
- muteLogoPixmap->DrawImage( cPoint(left + maxlabelWidth + marginItem, marginItem), imgLoader.GetImage() );
+ cImage *img = imgLoader.LoadIcon("mute", fontHeight, fontHeight);
+ if( img ) {
+ muteLogoPixmap->DrawImage( cPoint(left + maxlabelWidth + marginItem, marginItem), *img );
}
DecorBorderDraw(left - marginItem, DecorTop, maxlabelWidth + marginItem*4 + fontHeight, fontHeight,
Config.decorBorderVolumeSize, Config.decorBorderVolumeType, Config.decorBorderVolumeFg, Config.decorBorderVolumeBg);
diff --git a/flat.c b/flat.c
index c29127cc..29c82303 100644
--- a/flat.c
+++ b/flat.c
@@ -11,6 +11,7 @@
#include "displayvolume.h"
class cFlatConfig Config;
+class cImageCache imgCache;
cTheme Theme;
static bool menuActive = false;
diff --git a/flat.h b/flat.h
index 83a4d1d0..34246f8d 100644
--- a/flat.h
+++ b/flat.h
@@ -4,7 +4,10 @@
#include <vdr/videodir.h>
#include "config.h"
+#include "imagecache.h"
+
extern class cFlatConfig Config;
+extern class cImageCache imgCache;
extern bool firstDisplay;
class cFlatDisplayMenu;
diff --git a/imagecache.c b/imagecache.c
new file mode 100644
index 00000000..b220f6e2
--- /dev/null
+++ b/imagecache.c
@@ -0,0 +1,52 @@
+#include "imagecache.h"
+
+cImageCache::cImageCache() {
+
+}
+
+cImageCache::~cImageCache() {
+
+}
+
+void cImageCache::Create(void) {
+ for(int i = 0; i < MAX_IMAGE_CACHE; i++) {
+ CacheImage[i] = NULL;
+ CacheName[i] = "";
+ CacheWidth[i] = -1;
+ CacheHeight[i] = -1;
+ }
+
+ InsertIndex = 0;
+}
+
+void cImageCache::Clear(void) {
+ for(int i = 0; i < MAX_IMAGE_CACHE; i++) {
+ if( CacheImage[i] != NULL )
+ delete CacheImage[i];
+ }
+
+ InsertIndex = 0;
+}
+
+cImage* cImageCache::GetImage(std::string Name, int Width, int Height) {
+ for(int index = 0; index < MAX_IMAGE_CACHE; index++ ) {
+ if( CacheName[index] == Name && CacheWidth[index] == Width && CacheHeight[index] == Height )
+ return CacheImage[index];
+ }
+ return NULL;
+}
+
+void cImageCache::InsertImage(cImage *Image, std::string Name, int Width, int Height) {
+ CacheImage[InsertIndex] = Image;
+ CacheName[InsertIndex] = Name;
+ CacheWidth[InsertIndex] = Width;
+ CacheHeight[InsertIndex] = Height;
+
+ dsyslog("imagecache InsertImage");
+
+ InsertIndex++;
+ if( InsertIndex >= MAX_IMAGE_CACHE ) {
+ InsertIndex = 0;
+ dsyslog("imagecache overflow");
+ }
+}
diff --git a/imagecache.h b/imagecache.h
new file mode 100644
index 00000000..edeb8f41
--- /dev/null
+++ b/imagecache.h
@@ -0,0 +1,25 @@
+#pragma once
+#include <vdr/osd.h>
+#include <vdr/skins.h>
+#include <string>
+
+#define MAX_IMAGE_CACHE 999
+
+class cImageCache {
+private:
+ cImage *CacheImage[MAX_IMAGE_CACHE];
+ std::string CacheName[MAX_IMAGE_CACHE];
+ int CacheWidth[MAX_IMAGE_CACHE];
+ int CacheHeight[MAX_IMAGE_CACHE];
+
+ int InsertIndex;
+public:
+ cImageCache();
+ ~cImageCache();
+
+ void Create(void);
+ void Clear(void);
+
+ cImage *GetImage(std::string Name, int Width, int Height);
+ void InsertImage(cImage *Image, std::string Name, int Width, int Height);
+};
diff --git a/imageloader.c b/imageloader.c
index fd8e6a35..e989b84d 100644
--- a/imageloader.c
+++ b/imageloader.c
@@ -6,6 +6,7 @@
using namespace Magick;
+
cImageLoader::cImageLoader() {
InitializeMagick(NULL);
logoExtension = "png";
@@ -14,39 +15,64 @@ cImageLoader::cImageLoader() {
cImageLoader::~cImageLoader() {
}
-bool cImageLoader::LoadLogo(const char *logo, int width = -1, int height = -1) {
- if( width == -1 )
- width = logoWidth;
- if( height == -1 )
- height = logoHeight;
-
+cImage* cImageLoader::LoadLogo(const char *logo, int width, int height) {
if( (width == 0) || (height==0) )
- return false;
+ return NULL;
+ dsyslog("imageloader LoadLogo: %s", logo);
std::string logoLower = logo;
toLowerCase(logoLower);
cString File = cString::sprintf("%s/%s.%s", *Config.logoPath, logoLower.c_str(), *logoExtension);
+
+ cImage *img;
+ img = imgCache.GetImage( *File, width, height );
+ if( img != NULL )
+ return img;
+
bool success = LoadImage(File);
if( !success ) {
dsyslog("imageloader LoadLogo: %s could not be loaded", *File);
- return false;
+ return NULL;
}
- if( height != 0 || width != 0 ) {
- buffer.sample( Geometry(width, height) );
- }
- return true;
+ img = CreateImage(width, height);
+ if( img == NULL )
+ return NULL;
+ imgCache.InsertImage(img, logoLower, width, height);
+ return img;
}
-int cImageLoader::Height(void) {
- Geometry geo = buffer.size();
- return geo.height();
-}
+cImage* cImageLoader::LoadIcon(const char *cIcon, int width, int height, bool preserveAspect) {
+ if ((width == 0)||(height==0))
+ return NULL;
+
+ cString File = cString::sprintf("%s%s/%s.%s", *Config.iconPath, Setup.OSDTheme, cIcon, *logoExtension);
+
+ cImage *img;
+ img = imgCache.GetImage( *File, width, height );
+ if( img != NULL )
+ return img;
+
+ bool success = LoadImage(File);
+ if( !success ) {
+ File = cString::sprintf("%s%s/%s.%s", *Config.iconPath, "default", cIcon, *logoExtension);
+ img = imgCache.GetImage( *File, width, height );
+ if( img != NULL )
+ return img;
-int cImageLoader::Width(void) {
- Geometry geo = buffer.size();
- return geo.width();
+ success = LoadImage(File);
+ if( !success ) {
+ dsyslog("imageloader LoadIcon: %s could not be loaded", *File);
+ return NULL;
+ }
+ }
+ img = CreateImage(width, height);
+ if( img == NULL )
+ return NULL;
+ imgCache.InsertImage(img, cIcon, width, height);
+ return img;
}
+/*
bool cImageLoader::LoadIcon(const char *cIcon, int size) {
if (size==0)
return false;
@@ -64,11 +90,11 @@ bool cImageLoader::LoadIcon(const char *cIcon, int size) {
buffer.sample(Geometry(size, size));
return true;
}
+*/
-bool cImageLoader::LoadIcon(const char *cIcon, int width, int height, bool preserveAspect) {
+/*
+bool cImageLoader::LoadIcon2(const char *cIcon) {
try {
- if ((width == 0)||(height==0))
- return false;
cString File = cString::sprintf("%s%s/%s.%s", *Config.iconPath, Setup.OSDTheme, cIcon, *logoExtension);
bool success = LoadImage(File);
@@ -80,12 +106,6 @@ bool cImageLoader::LoadIcon(const char *cIcon, int width, int height, bool prese
return false;
}
}
- if (preserveAspect) {
- buffer.sample(Geometry(width, height));
- } else {
- cString geometry = cString::sprintf("%dx%d!", width, height);
- buffer.scale(Geometry(*geometry));
- }
return true;
}
catch (...) {
@@ -94,32 +114,15 @@ bool cImageLoader::LoadIcon(const char *cIcon, int width, int height, bool prese
}
cImage cImageLoader::GetImage() {
- int w, h;
- w = buffer.columns();
- h = buffer.rows();
- cImage image (cSize(w, h));
- const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
- for (int iy = 0; iy < h; ++iy) {
- for (int ix = 0; ix < w; ++ix) {
- tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
- | (int(pixels->green * 255 / MaxRGB) << 8)
- | (int(pixels->red * 255 / MaxRGB) << 16)
- | (int(pixels->blue * 255 / MaxRGB) );
- image.SetPixel(cPoint(ix, iy), col);
- ++pixels;
- }
- }
- return image;
+ return CreateImageCopy();
}
-Color cImageLoader::Argb2Color(tColor col) {
- tIndex alpha = (col & 0xFF000000) >> 24;
- tIndex red = (col & 0x00FF0000) >> 16;
- tIndex green = (col & 0x0000FF00) >> 8;
- tIndex blue = (col & 0x000000FF);
- Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
- return color;
+cImage cImageLoader::GetImage(int width, int height, bool preserveAspect) {
+ cImage *img;
+ img = CreateImage(width, height, preserveAspect);
+ return *img;
}
+*/
void cImageLoader::toLowerCase(std::string &str) {
const int length = str.length();
@@ -127,12 +130,3 @@ void cImageLoader::toLowerCase(std::string &str) {
str[i] = std::tolower(str[i]);
}
}
-
-bool cImageLoader::LoadImage(cString File) {
- try {
- buffer.read(*File);
- } catch (...) {
- return false;
- }
- return true;
-}
diff --git a/imageloader.h b/imageloader.h
index fc9a3186..b7ffb243 100644
--- a/imageloader.h
+++ b/imageloader.h
@@ -2,34 +2,35 @@
#define X_DISPLAY_MISSING
+
#include <vdr/osd.h>
#include <vdr/skins.h>
#include <Magick++.h>
+#include "imagemagickwrapper.h"
#include "flat.h"
using namespace Magick;
-
-class cImageLoader {
+
+class cImageLoader : public cImageMagickWrapper {
public:
cImageLoader();
~cImageLoader();
- cImage GetImage();
- bool LoadLogo(const char *logo, int width, int height);
- bool LoadIcon(const char *cIcon, int size = -1);
- bool LoadIcon(const char *cIcon, int width, int height, bool preserveAspect = true);
+
+ cImage* LoadLogo(const char *logo, int width, int height);
+ cImage* LoadIcon(const char *cIcon, int width, int height, bool preserveAspect = true);
+
+ //cImage GetImage();
+ //cImage GetImage(int width, int height, bool preserveAspect = true);
+
+ //bool LoadIcon(const char *cIcon, int size = -1);
+ //bool LoadIcon2(const char *cIcon);
- int Height(void);
- int Width(void);
private:
int epgImageWidthLarge, epgImageHeightLarge;
int epgImageWidth, epgImageHeight;
- int logoWidth, logoHeight;
cString logoExtension;
- Image buffer;
- Color Argb2Color(tColor col);
void toLowerCase(std::string &str);
- bool LoadImage(cString File);
};
diff --git a/imagemagickwrapper.c b/imagemagickwrapper.c
new file mode 100644
index 00000000..22532b3b
--- /dev/null
+++ b/imagemagickwrapper.c
@@ -0,0 +1,87 @@
+#include <string>
+#include <sstream>
+#include "imagemagickwrapper.h"
+#include "imagescaler.h"
+
+cImageMagickWrapper::cImageMagickWrapper() {
+ InitializeMagick(NULL);
+}
+
+cImageMagickWrapper::~cImageMagickWrapper() {
+}
+
+cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) {
+ int w, h;
+ w = buffer.columns();
+ h = buffer.rows();
+ if (width == 0)
+ width = w;
+ if (height == 0)
+ height = h;
+ if (preserveAspect) {
+ unsigned scale_w = 1000 * width / w;
+ unsigned scale_h = 1000 * height / h;
+ if (scale_w > scale_h)
+ width = w * height / h;
+ else
+ height = h * width / w;
+ }
+ const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+ cImage *image = new cImage(cSize(width, height));
+ tColor *imgData = (tColor *)image->Data();
+ if (w != width || h != height) {
+ ImageScaler scaler;
+ scaler.SetImageParameters(imgData, width, width, height, w, h);
+ for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
+ scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
+ pixels->green / ((MaxRGB + 1) / 256),
+ pixels->red / ((MaxRGB + 1) / 256),
+ ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
+ return image;
+ }
+ for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
+ *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
+ (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
+ (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
+ (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
+ return image;
+}
+
+cImage cImageMagickWrapper::CreateImageCopy() {
+ int w, h;
+ w = buffer.columns();
+ h = buffer.rows();
+ cImage image (cSize(w, h));
+ const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+ for (int iy = 0; iy < h; ++iy) {
+ for (int ix = 0; ix < w; ++ix) {
+ tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
+ | (int(pixels->green * 255 / MaxRGB) << 8)
+ | (int(pixels->red * 255 / MaxRGB) << 16)
+ | (int(pixels->blue * 255 / MaxRGB) );
+ image.SetPixel(cPoint(ix, iy), col);
+ ++pixels;
+ }
+ }
+ return image;
+}
+
+bool cImageMagickWrapper::LoadImage(const char *fullpath) {
+ if ((fullpath == NULL) || (strlen(fullpath) < 5))
+ return false;
+ try {
+ buffer.read(fullpath);
+ } catch(...) {
+ return false;
+ }
+ return true;
+}
+
+Color cImageMagickWrapper::Argb2Color(tColor col) {
+ tIndex alpha = (col & 0xFF000000) >> 24;
+ tIndex red = (col & 0x00FF0000) >> 16;
+ tIndex green = (col & 0x0000FF00) >> 8;
+ tIndex blue = (col & 0x000000FF);
+ Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
+ return color;
+}
diff --git a/imagemagickwrapper.h b/imagemagickwrapper.h
new file mode 100644
index 00000000..9750a888
--- /dev/null
+++ b/imagemagickwrapper.h
@@ -0,0 +1,23 @@
+#ifndef __NOPACITY_IMAGEMAGICKWRAPPER_H
+#define __NOPACITY_IMAGEMAGICKWRAPPER_H
+
+#define X_DISPLAY_MISSING
+
+#include <Magick++.h>
+#include <vdr/osd.h>
+
+using namespace Magick;
+
+class cImageMagickWrapper {
+public:
+ cImageMagickWrapper();
+ ~cImageMagickWrapper();
+protected:
+ Image buffer;
+ Color Argb2Color(tColor col);
+ cImage *CreateImage(int width, int height, bool preserveAspect = true);
+ cImage CreateImageCopy(void);
+ bool LoadImage(const char *fullpath);
+};
+
+#endif
diff --git a/imagescaler.c b/imagescaler.c
new file mode 100644
index 00000000..cebe9129
--- /dev/null
+++ b/imagescaler.c
@@ -0,0 +1,149 @@
+
+#include "imagescaler.h"
+
+#include <cstdlib>
+#include <cmath>
+
+ImageScaler::ImageScaler() :
+ m_memory(NULL),
+ m_hor_filters(NULL),
+ m_ver_filters(NULL),
+ m_buffer(NULL),
+ m_dst_image(NULL),
+ m_dst_stride(0),
+ m_dst_width(0),
+ m_dst_height(0),
+ m_src_width(0),
+ m_src_height(0),
+ m_src_x(0),
+ m_src_y(0),
+ m_dst_x(0),
+ m_dst_y(0) {
+}
+
+ImageScaler::~ImageScaler() {
+ if ( m_memory ) free( m_memory );
+}
+
+// sin(x)/(x)
+static float sincf( float x ) {
+ if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x; // taylor series approximation to avoid 0/0
+ return sin(x)/x;
+}
+
+static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) {
+ const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size);
+
+ for (int i = 0; i < dst_size; i++) {
+ const int d = 2*dst_size; // sample position denominator
+ const int e = (2*i+1) * src_size - dst_size; // sample position enumerator
+ int offset = e / d; // truncated sample position
+ const float sub_offset = ((float) (e - offset*d)) / ((float) d); // exact sample position is (float) e/d = offset + sub_offset
+
+ // calculate filter coefficients
+ float h[4];
+ for (int j=0; j<4; j++) {
+ const float t = 3.14159265359f * (sub_offset+(1-j));
+ h[j] = sincf( fc * t ) * cosf( 0.25f * t ); // sinc-lowpass and cos-window
+ }
+
+ // ensure that filter does not reach out off image bounds:
+ while ( offset < 1 ) {
+ h[0] += h[1];
+ h[1] = h[2];
+ h[2] = h[3];
+ h[3] = 0.0f;
+ offset++;
+ }
+
+ while ( offset+3 > src_size ) {
+ h[3] += h[2];
+ h[2] = h[1];
+ h[1] = h[0];
+ h[0] = 0.0f;
+ offset--;
+ }
+
+ // coefficients are normalized to sum up to 2048
+ const float norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] );
+
+ offset--; // offset of fist used pixel
+
+ filters[i].m_offset = offset + 4; // store offset of first unused pixel
+
+ for (int j=0; j<4; j++) {
+ const float t = norm * h[j];
+ filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ? (t+0.5f) : (t-0.5f)); // consider ring buffer index permutations
+ }
+ }
+
+ // set end marker
+ filters[dst_size].m_offset = (unsigned) -1;
+
+}
+
+void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) {
+ m_src_x = 0;
+ m_src_y = 0;
+ m_dst_x = 0;
+ m_dst_y = 0;
+
+ m_dst_image = dst_image;
+ m_dst_stride = dst_stride;
+
+ // if image dimensions do not change we can keep the old filter coefficients
+ if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return;
+
+ m_dst_width = dst_width;
+ m_dst_height = dst_height;
+ m_src_width = src_width;
+ m_src_height = src_height;
+
+ if ( m_memory ) free( m_memory );
+
+ const unsigned hor_filters_size = (m_dst_width + 1) * sizeof(Filter); // reserve one extra position for end marker
+ const unsigned ver_filters_size = (m_dst_height + 1) * sizeof(Filter);
+ const unsigned buffer_size = 4 * m_dst_width * sizeof(TmpPixel);
+
+ char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size );
+
+ m_memory = p;
+
+ m_hor_filters = (Filter *) p; p += hor_filters_size;
+ m_ver_filters = (Filter *) p; p += ver_filters_size;
+ m_buffer = (TmpPixel *) p;
+
+ CalculateFilters( m_hor_filters, m_dst_width , m_src_width );
+ CalculateFilters( m_ver_filters, m_dst_height, m_src_height );
+}
+
+// shift range to 0..255 and clamp overflows
+static unsigned shift_clamp( int x ) {
+ x = ( x + (1<<21) ) >> 22;
+ if ( x < 0 ) return 0;
+ if ( x > 255 ) return 255;
+ return x;
+}
+
+void ImageScaler::NextSourceLine() {
+ m_dst_x = 0;
+ m_src_x = 0;
+ m_src_y++;
+
+ while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) {
+ const int h0 = m_ver_filters[m_dst_y].m_coeff[0];
+ const int h1 = m_ver_filters[m_dst_y].m_coeff[1];
+ const int h2 = m_ver_filters[m_dst_y].m_coeff[2];
+ const int h3 = m_ver_filters[m_dst_y].m_coeff[3];
+ const TmpPixel *src = m_buffer;
+ unsigned *dst = m_dst_image + m_dst_stride * m_dst_y;
+
+ for (unsigned i=0; i<m_dst_width; i++) {
+ const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 );
+ src += 4;
+ dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24);
+ }
+
+ m_dst_y++;
+ }
+}
diff --git a/imagescaler.h b/imagescaler.h
new file mode 100644
index 00000000..f2de6ba4
--- /dev/null
+++ b/imagescaler.h
@@ -0,0 +1,97 @@
+#ifndef _ImageScaler_h
+#define _ImageScaler_h
+
+/*!
+ * this class scales images consisting of 4 components (RGBA)
+ * to an arbitrary size using a 4-tap filter
+ */
+class ImageScaler {
+public:
+
+ struct Filter {
+ unsigned m_offset;
+ short m_coeff[4];
+ };
+
+ ImageScaler();
+ ~ImageScaler();
+
+ //! set destination image and source image size
+ void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );
+
+ /*! process one pixel of source image; destination image is written while input is processed
+ * SetImageParameters() must be called first
+ */
+ void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
+ m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );
+
+ TmpPixel *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
+ const Filter *fh;
+
+ while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
+ *bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
+ m_dst_x++;
+ bp += 4;
+ }
+
+ if ( m_src_x == m_src_width ) NextSourceLine();
+ }
+
+private:
+
+ //! temporary image pixel class - a 4-element integer vector
+ class TmpPixel {
+ public:
+ TmpPixel() {
+ }
+
+ TmpPixel( int c0, int c1, int c2, int c3 ) {
+ Set(c0,c1,c2,c3);
+ }
+
+ void Set( int c0, int c1, int c2, int c3 ) {
+ m_comp[0] = c0;
+ m_comp[1] = c1;
+ m_comp[2] = c2;
+ m_comp[3] = c3;
+ }
+
+ TmpPixel operator*( int s ) const {
+ return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
+ }
+
+ TmpPixel operator+( const TmpPixel &x ) const {
+ return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
+ }
+
+ // return component i=[0..3] - No range check!
+ int operator[](unsigned i) const {
+ return m_comp[i];
+ }
+
+ private:
+ int m_comp[4];
+ };
+
+ //! this is called whenever one input line is processed completely
+ void NextSourceLine();
+
+ TmpPixel m_hbuf[4]; //! ring buffer for 4 input pixels
+ char *m_memory; //! buffer container
+ Filter *m_hor_filters; //! buffer for horizontal filters (one for each output image column)
+ Filter *m_ver_filters; //! buffer for vertical filters (one for each output image row)
+ TmpPixel *m_buffer; //! buffer contains 4 horizontally filtered input lines, multiplexed
+ unsigned *m_dst_image; //! pointer to destination image
+ unsigned m_dst_stride; //! destination image stride
+ unsigned m_dst_width; //! destination image width
+ unsigned m_dst_height; //! destination image height
+ unsigned m_src_width; //! source image width
+ unsigned m_src_height; //! source image height
+ unsigned m_src_x; //! x position of next source image pixel
+ unsigned m_src_y; //! y position of source image line currently beeing processed
+ unsigned m_dst_x; //! x position of next destination image pixel
+ unsigned m_dst_y; //! x position of next destination image line
+};
+
+#endif // _ImageScaler_h
+
diff --git a/po/de_DE.po b/po/de_DE.po
index eb4b0b56..b584980e 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -34,7 +34,7 @@ msgid "Subtitle"
msgstr "Untertitel"
msgid "timer not enabled"
-msgstr ""
+msgstr "Timer nicht aktiv"
msgid "Length"
msgstr "Länge"
diff --git a/skinflatplus.c b/skinflatplus.c
index 33c26262..fb6dbc63 100644
--- a/skinflatplus.c
+++ b/skinflatplus.c
@@ -14,6 +14,7 @@
#include "flat.h"
#include "setup.h"
+#include "imageloader.h"
static const char *VERSION = "0.1.0";
static const char *DESCRIPTION = "skin flatplus";
@@ -86,11 +87,15 @@ bool cPluginFlat::Start(void) {
return false;
} else
dsyslog("skinflatplus: TrueColor OSD found");
+
+ imgCache.Create();
+
flat = new cFlat;
return flat;
}
void cPluginFlat::Stop(void) {
+ imgCache.Clear();
}
void cPluginFlat::Housekeeping(void) {