diff options
author | mrwastl <mrwastl@users.sourceforge.net> | 2011-10-15 18:41:49 +0200 |
---|---|---|
committer | mrwastl <mrwastl@users.sourceforge.net> | 2011-10-15 18:41:49 +0200 |
commit | cb4534730274a32e7c4e64c7f282bd258375b1f9 (patch) | |
tree | e14bfcce71b13d802a31cdae9ed7b43cff9dc1b1 | |
parent | ab3acde2326a9d8f942995325b71b3aeaf24b918 (diff) | |
download | graphlcd-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.c | 31 | ||||
-rw-r--r-- | glcdgraphics/extformats.h | 3 | ||||
-rw-r--r-- | glcdgraphics/imagefile.h | 7 | ||||
-rw-r--r-- | glcdskin/cache.c | 48 | ||||
-rw-r--r-- | glcdskin/cache.h | 15 | ||||
-rw-r--r-- | glcdskin/object.c | 38 | ||||
-rw-r--r-- | glcdskin/object.h | 10 | ||||
-rw-r--r-- | glcdskin/parser.c | 1 |
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") |