summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrwastl <mrwastl@users.sourceforge.net>2011-10-15 18:41:49 +0200
committermrwastl <mrwastl@users.sourceforge.net>2011-10-15 18:41:49 +0200
commitcb4534730274a32e7c4e64c7f282bd258375b1f9 (patch)
treee14bfcce71b13d802a31cdae9ed7b43cff9dc1b1
parentab3acde2326a9d8f942995325b71b3aeaf24b918 (diff)
downloadgraphlcd-base-cb4534730274a32e7c4e64c7f282bd258375b1f9.tar.gz
graphlcd-base-cb4534730274a32e7c4e64c7f282bd258375b1f9.tar.bz2
support for scaling of images (image/graphicsmagick supported images only at the moment); skins: additional paraemter 'scale' for <image/>; added method for emptying of image cache (cImageCache::Clear())
-rw-r--r--glcdgraphics/extformats.c31
-rw-r--r--glcdgraphics/extformats.h3
-rw-r--r--glcdgraphics/imagefile.h7
-rw-r--r--glcdskin/cache.c48
-rw-r--r--glcdskin/cache.h15
-rw-r--r--glcdskin/object.c38
-rw-r--r--glcdskin/object.h10
-rw-r--r--glcdskin/parser.c1
8 files changed, 141 insertions, 12 deletions
diff --git a/glcdgraphics/extformats.c b/glcdgraphics/extformats.c
index ee87a32..764f85c 100644
--- a/glcdgraphics/extformats.c
+++ b/glcdgraphics/extformats.c
@@ -49,6 +49,13 @@ cExtFormatFile::~cExtFormatFile()
bool cExtFormatFile::Load(cImage & image, const string & fileName)
{
+ uint16_t scalew = 0;
+ uint16_t scaleh = 0;
+ return LoadScaled(image, fileName, scalew, scaleh);
+}
+
+bool cExtFormatFile::LoadScaled(cImage & image, const string & fileName, uint16_t & scalew, uint16_t & scaleh)
+{
#ifdef HAVE_IMAGEMAGICK
std::vector<Image> extimages;
try {
@@ -81,10 +88,32 @@ bool cExtFormatFile::Load(cImage & image, const string & fileName)
if (firstImage) {
width = (uint16_t)((*it).columns());
height = (uint16_t)((*it).rows());
+ firstImage = false;
+
+ // one out of scalew/h == 0 ? -> auto aspect ratio
+ if (scalew && ! scaleh) {
+ scaleh = (uint16_t)( ((uint32_t)scalew * (uint32_t)height) / (uint32_t)width );
+ } else if (!scalew && scaleh) {
+ scalew = (uint16_t)( ((uint32_t)scaleh * (uint32_t)width) / (uint32_t)height );
+ }
+
+ // scale image
+ if (scalew && ! (scalew == width && scaleh == height)) {
+ (*it).scale(Geometry(scalew, scaleh));
+ width = scalew;
+ height = scaleh;
+ } else {
+ // not scaled => reset to 0
+ scalew = 0;
+ scaleh = 0;
+ }
+
image.SetWidth(width);
image.SetHeight(height);
- firstImage = false;
} else {
+ if (scalew && scaleh) {
+ (*it).scale(Geometry(scalew, scaleh));
+ } else
if ( (width != (uint16_t)((*it).columns())) || (height != (uint16_t)((*it).rows())) ) {
ignoreImage = true;
}
diff --git a/glcdgraphics/extformats.h b/glcdgraphics/extformats.h
index 8a8223c..2f6b2bc 100644
--- a/glcdgraphics/extformats.h
+++ b/glcdgraphics/extformats.h
@@ -28,6 +28,9 @@ public:
virtual ~cExtFormatFile();
virtual bool Load(cImage & image, const std::string & fileName);
virtual bool Save(cImage & image, const std::string & fileName);
+
+ virtual bool SupportsScaling(void) { return true; }
+ virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh);
};
} // end of namespace
diff --git a/glcdgraphics/imagefile.h b/glcdgraphics/imagefile.h
index bf5ff5e..bc7e835 100644
--- a/glcdgraphics/imagefile.h
+++ b/glcdgraphics/imagefile.h
@@ -26,6 +26,13 @@ public:
virtual ~cImageFile();
virtual bool Load(cImage & image, const std::string & fileName);
virtual bool Save(cImage & image, const std::string & fileName);
+
+ virtual bool SupportsScaling(void) { return false; }
+ virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh) {
+ scalew = 0;
+ scaleh = 0;
+ return Load(image, fileName);
+ }
};
} // end of namespace
diff --git a/glcdskin/cache.c b/glcdskin/cache.c
index 4129eb9..59a5f26 100644
--- a/glcdskin/cache.c
+++ b/glcdskin/cache.c
@@ -23,10 +23,12 @@
namespace GLCD
{
-cImageItem::cImageItem(const std::string & path, cImage * image)
+cImageItem::cImageItem(const std::string & path, cImage * image, uint16_t scalew, uint16_t scaleh)
: path(path),
counter(0),
- image(image)
+ image(image),
+ scale_width(scalew),
+ scale_height(scaleh)
{
}
@@ -44,6 +46,11 @@ cImageCache::cImageCache(cSkin * Parent, int Size)
cImageCache::~cImageCache()
{
+ Clear();
+}
+
+void cImageCache::Clear(void)
+{
for (unsigned int i = 0; i < images.size(); i++)
{
delete images[i];
@@ -52,7 +59,7 @@ cImageCache::~cImageCache()
failedpaths.clear();
}
-cImage * cImageCache::Get(const std::string & path)
+cImage * cImageCache::Get(const std::string & path, uint16_t & scalew, uint16_t & scaleh)
{
std::vector <cImageItem *>::iterator it;
cImageItem * item;
@@ -71,7 +78,9 @@ cImage * cImageCache::Get(const std::string & path)
item = NULL;
for (it = images.begin(); it != images.end(); it++)
{
- if (item == NULL && path == (*it)->Path())
+ uint16_t scw = 0, sch = 0;
+ (*it)->ScalingGeometry(scw, sch);
+ if (item == NULL && path == (*it)->Path() && ( (scw == 0 && sch == 0) || (scw == scalew && sch == scaleh)))
{
(*it)->ResetCounter();
item = (*it);
@@ -91,7 +100,7 @@ cImage * cImageCache::Get(const std::string & path)
return item->Image();
}
- item = LoadImage(path);
+ item = LoadImage(path, scalew, scaleh);
if (item)
{
if (images.size() == size)
@@ -99,6 +108,8 @@ cImage * cImageCache::Get(const std::string & path)
images.erase(oldest);
}
images.push_back(item);
+ scalew = item->Image()->Width();
+ scaleh = item->Image()->Height();
return item->Image();
} else {
failedpaths.push_back(path);
@@ -106,7 +117,7 @@ cImage * cImageCache::Get(const std::string & path)
return NULL;
}
-cImageItem * cImageCache::LoadImage(const std::string & path)
+cImageItem * cImageCache::LoadImage(const std::string & path, uint16_t scalew, uint16_t scaleh)
{
cImageItem * item;
cImage * image;
@@ -150,6 +161,28 @@ cImageItem * cImageCache::LoadImage(const std::string & path)
}
file += path;
}
+
+ cImageFile* imgFile = NULL;
+
+ if (strcmp(str, "PBM") == 0) {
+ imgFile = new cPBMFile();
+ } else if (strcmp(str, "GLCD") == 0) {
+ imgFile = new cGLCDFile();
+ } else {
+ imgFile = new cExtFormatFile();
+ }
+
+ uint16_t scale_width = scalew;
+ uint16_t scale_height = scaleh;
+ // scale_width and scale_height are set to 0 if image was NOT scaled
+ if (!imgFile || (imgFile->LoadScaled(*image, file, scale_width, scale_height) == false) ) {
+ delete image;
+ if (imgFile) delete imgFile;
+ return NULL;
+ }
+ delete imgFile;
+
+#if 0
if (strcmp(str, "PBM") == 0)
{
cPBMFile pbm;
@@ -180,8 +213,9 @@ cImageItem * cImageCache::LoadImage(const std::string & path)
return NULL;
}
}
+#endif
- item = new cImageItem(path, image);
+ item = new cImageItem(path, image, scale_width, scale_height);
if (!item)
{
delete image;
diff --git a/glcdskin/cache.h b/glcdskin/cache.h
index 3862b51..533f009 100644
--- a/glcdskin/cache.h
+++ b/glcdskin/cache.h
@@ -29,11 +29,13 @@ private:
std::string path;
uint64_t counter;
cImage * image;
+ uint16_t scale_width, scale_height;
public:
- cImageItem(const std::string & path, cImage * image);
+ cImageItem(const std::string & path, cImage * image, uint16_t scalew, uint16_t scaleh);
~cImageItem();
const std::string & Path() const { return path; }
+ void ScalingGeometry(uint16_t & scalew, uint16_t & scaleh) { scalew = scale_width; scaleh = scale_height; }
uint64_t Counter() const { return counter; }
cImage * Image() { return image; }
void ResetCounter() { counter = 0; }
@@ -48,12 +50,19 @@ private:
std::vector <cImageItem *> images;
std::vector <std::string> failedpaths;
- cImageItem * LoadImage(const std::string & path);
+ cImageItem * LoadImage(const std::string & path, uint16_t scalew, uint16_t scaleh);
public:
cImageCache(cSkin * Parent, int Size);
~cImageCache();
- cImage * Get(const std::string & path);
+ cImage * Get(const std::string & path, uint16_t & scalew, uint16_t & scaleh);
+ cImage * Get(const std::string & path) {
+ uint16_t scalew = 0;
+ uint16_t scaleh = 0;
+ return Get(path, scalew, scaleh) ;
+ }
+
+ void Clear(void);
};
} // end of namespace
diff --git a/glcdskin/object.c b/glcdskin/object.c
index b2dffe7..7c6b75d 100644
--- a/glcdskin/object.c
+++ b/glcdskin/object.c
@@ -64,6 +64,7 @@ cSkinObject::cSkinObject(cSkinDisplay * Parent)
mStoredImagePath(""),
mImageFrameId(0), // start with 1st frame
mOpacity(255), // default: full opacity
+ mScale(tscNone), // scale image: default: don't scale
mScrollLoopMode(-1), // scroll (text) or loop (image) mode: default (-1)
mScrollLoopReached(false), // if scroll/loop == once: already looped once?
mScrollSpeed(0), // scroll speed: default (0)
@@ -117,6 +118,7 @@ cSkinObject::cSkinObject(const cSkinObject & Src)
mStoredImagePath(Src.mStoredImagePath),
mImageFrameId(0),
mOpacity(Src.mOpacity),
+ mScale(Src.mScale),
mScrollLoopMode(Src.mScrollLoopMode),
mScrollLoopReached(Src.mScrollLoopReached),
mScrollSpeed(Src.mScrollSpeed),
@@ -227,6 +229,21 @@ bool cSkinObject::ParseEffect(const std::string & Text)
return true;
}
+bool cSkinObject::ParseScale(const std::string & Text)
+{
+ if (Text == "none")
+ mScale = tscNone;
+ else if (Text == "autox")
+ mScale = tscAutoX;
+ else if (Text == "autoy")
+ mScale = tscAutoY;
+ else if (Text == "fill")
+ mScale = tscFill;
+ else
+ return false;
+ return true;
+}
+
bool cSkinObject::ParseIntParam(const std::string &Text, int & Param)
{
if (isalpha(Text[0]) || Text[0] == '#')
@@ -413,7 +430,26 @@ void cSkinObject::Render(GLCD::cBitmap * screen)
mChangeDelay = -1;
}
- GLCD::cImage * image = cache->Get(evalPath);
+ uint16_t scalew = 0;
+ uint16_t scaleh = 0;
+
+ switch (mScale) {
+ case tscAutoX:
+ scalew = Size().w;
+ break;
+ case tscAutoY:
+ scaleh = Size().h;
+ break;
+ case tscFill:
+ scalew = Size().w;
+ scaleh = Size().h;
+ break;
+ default:
+ scalew = 0;
+ scaleh = 0;
+ }
+
+ GLCD::cImage * image = cache->Get(evalPath, scalew, scaleh);
if (image)
{
int framecount = image->Count();
diff --git a/glcdskin/object.h b/glcdskin/object.h
index ec8027b..a82bedb 100644
--- a/glcdskin/object.h
+++ b/glcdskin/object.h
@@ -67,6 +67,14 @@ enum eEffect
tfxOutline
};
+enum eScale
+{
+ tscNone,
+ tscAutoX,
+ tscAutoY,
+ tscFill
+};
+
class cSkinColor
@@ -157,6 +165,7 @@ private:
std::string mStoredImagePath; // stored image path
int mImageFrameId; // frame ID of image
int mOpacity; // opacity of an image ([0, 255], default 255)
+ eScale mScale; // image scaling (['none', 'autox', 'autoy', 'fill'], default: none)
int mScrollLoopMode; // scroll (text) or loop (image) mode: -1: default, 0: never, 1: once, 2: always
bool mScrollLoopReached; // if scroll/loop == once: already looped once?
@@ -185,6 +194,7 @@ public:
bool ParseAlignment(const std::string &Text);
bool ParseVerticalAlignment(const std::string &Text);
bool ParseEffect(const std::string &Text);
+ bool ParseScale(const std::string &Text);
bool ParseFontFace(const std::string &Text);
bool ParseIntParam(const std::string &Text, int & Param);
//bool ParseWidth(const std::string &Text);
diff --git a/glcdskin/parser.c b/glcdskin/parser.c
index 8445449..ca90829 100644
--- a/glcdskin/parser.c
+++ b/glcdskin/parser.c
@@ -332,6 +332,7 @@ bool StartElem(const std::string & name, std::map<std::string,std::string> & att
ATTRIB_MAN_FUNC("path", object->mPath.Parse);
ATTRIB_OPT_FUNC("loop", object->ParseScrollLoopMode);
ATTRIB_OPT_FUNC_PARAM("opacity", object->ParseIntParam, object->mOpacity);
+ ATTRIB_OPT_FUNC("scale", object->ParseScale);
}
else if (name == "text"
|| name == "scrolltext")