diff options
author | mrwastl <mrwastl@users.sourceforge.net> | 2013-03-21 20:29:45 +0100 |
---|---|---|
committer | mrwastl <mrwastl@users.sourceforge.net> | 2013-03-21 20:29:45 +0100 |
commit | 60bdec72ecd6bb236f2f1153398c9996fb95730f (patch) | |
tree | 7b6a7667f41002b54dcc78360cef71256b811c94 | |
parent | cf926629084ab015873859e759155f9bfe813e6b (diff) | |
download | graphlcd-base-60bdec72ecd6bb236f2f1153398c9996fb95730f.tar.gz graphlcd-base-60bdec72ecd6bb236f2f1153398c9996fb95730f.tar.bz2 |
glcdgraphics: bug fix in glcd.c, moved methods Scale() and Blend() to image.c, added static methods for loading/saving image; showpic and convpic working again; convpic cleaned up; showpic: added parameters for scaling and centering image
-rw-r--r-- | glcdgraphics/extformats.c | 10 | ||||
-rw-r--r-- | glcdgraphics/glcd.c | 25 | ||||
-rw-r--r-- | glcdgraphics/image.c | 189 | ||||
-rw-r--r-- | glcdgraphics/image.h | 10 | ||||
-rw-r--r-- | glcdgraphics/imagefile.c | 122 | ||||
-rw-r--r-- | glcdgraphics/imagefile.h | 6 | ||||
-rw-r--r-- | glcdgraphics/pbm.c | 15 | ||||
-rw-r--r-- | graphlcd.conf | 2 | ||||
-rw-r--r-- | tools/convpic/Makefile | 2 | ||||
-rw-r--r-- | tools/convpic/bmp.c | 378 | ||||
-rw-r--r-- | tools/convpic/bmp.h | 45 | ||||
-rw-r--r-- | tools/convpic/convpic.c | 214 | ||||
-rw-r--r-- | tools/convpic/tiff.c | 203 | ||||
-rw-r--r-- | tools/convpic/tiff.h | 42 | ||||
-rw-r--r-- | tools/convpic/tuxbox.c | 287 | ||||
-rw-r--r-- | tools/convpic/tuxbox.h | 46 | ||||
-rw-r--r-- | tools/showpic/showpic.c | 474 |
17 files changed, 559 insertions, 1511 deletions
diff --git a/glcdgraphics/extformats.c b/glcdgraphics/extformats.c index 3a0ab36..5734fce 100644 --- a/glcdgraphics/extformats.c +++ b/glcdgraphics/extformats.c @@ -8,7 +8,7 @@ * This file is released under the GNU General Public License. Refer * to the COPYING file distributed with this package. * - * (c) 2011-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> */ #include <stdio.h> @@ -66,7 +66,7 @@ bool cExtFormatFile::LoadScaled(cImage & image, const string & fileName, uint16_ std::vector<Magick::Image>::iterator it; readImages(&extimages, fileName); if (extimages.size() == 0) { - syslog(LOG_ERR, "ERROR: graphlcd: Couldn't load %s", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s' (cExtFormatFile::LoadScaled)", fileName.c_str()); return false; } @@ -163,16 +163,16 @@ bool cExtFormatFile::LoadScaled(cImage & image, const string & fileName, uint16_ } } } catch (Magick::Exception &e) { - syslog(LOG_ERR, "ERROR: graphlcd: Couldn't load %s: %s", fileName.c_str(), e.what()); + syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s': %s (cExtFormatFile::LoadScaled)", fileName.c_str(), e.what()); return false; } catch (...) { - syslog(LOG_ERR, "ERROR: graphlcd: Couldn't load %s: Unknown exception caught", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s': Unknown exception caught (cExtFormatFile::LoadScaled)", fileName.c_str()); return false; } return true; #else return false; -#endif +#endif } // to be done ... diff --git a/glcdgraphics/glcd.c b/glcdgraphics/glcd.c index 3b2c3f3..6e97208 100644 --- a/glcdgraphics/glcd.c +++ b/glcdgraphics/glcd.c @@ -10,7 +10,7 @@ * to the COPYING file distributed with this package. * * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de> - * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> * Andreas 'randy' Weinberger */ @@ -69,7 +69,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) fp = fopen(fileName.c_str(), "rb"); if (!fp) { - syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: opening of '%s' failed (cGLCDFile::Load).", fileName.c_str()); return false; } @@ -98,7 +98,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) // check header sign if (strncmp(sign, kGLCDFileSign, 3) != 0) { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong header (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -114,7 +114,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) height = (buf[3] << 8) | buf[2]; if (width == 0 || height == 0) { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong header (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -126,7 +126,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) // check file length if (fileSize != (long) (height * ((width + 7) / 8) + 8)) { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong size (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -136,7 +136,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) // read count and delay if (fread(buf, 6, 1, fp) != 1) { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong header (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -146,7 +146,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) if (count == 0 || fileSize != (long) (count * (height * ((width + 7) / 8)) + 14)) { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong size (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -156,7 +156,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) } else { - syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: loading of '%s' failed, wrong header (cGLCDFile::Load).", fileName.c_str()); fclose(fp); return false; } @@ -213,7 +213,7 @@ bool cGLCDFile::Load(cImage & image, const string & fileName) if (bmpdata_raw) delete[] bmpdata_raw; - syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str()); + syslog(LOG_DEBUG, "glcdgraphics: image '%s' loaded.", fileName.c_str()); return true; } @@ -234,7 +234,7 @@ bool cGLCDFile::Save(cImage & image, const string & fileName) fp = fopen(fileName.c_str(), "wb"); if (!fp) { - syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Save).", fileName.c_str()); + syslog(LOG_ERR, "glcdgraphics: opening '%s' failed (cGLCDFile::Save).", fileName.c_str()); return false; } @@ -285,8 +285,7 @@ bool cGLCDFile::Save(cImage & image, const string & fileName) { if (bitmap->Width() == width && bitmap->Height() == height) { -// if (fwrite(bitmap->Data(), height * ((width + 7) / 8), 1, fp) != 1) - if (fwrite(bitmap->Data(), height * width, 1, fp) != 1) + if (fwrite( cBitmap::ConvertTo1BPP(*bitmap), height * ((width + 7) / 8), 1, fp) != 1) { fclose(fp); return false; @@ -296,7 +295,7 @@ bool cGLCDFile::Save(cImage & image, const string & fileName) } fclose(fp); - syslog(LOG_DEBUG, "glcdgraphics: image %s saved.", fileName.c_str()); + syslog(LOG_DEBUG, "glcdgraphics: image '%s' saved.", fileName.c_str()); return true; } diff --git a/glcdgraphics/image.c b/glcdgraphics/image.c index 72003b1..1240b80 100644 --- a/glcdgraphics/image.c +++ b/glcdgraphics/image.c @@ -10,11 +10,17 @@ * to the COPYING file distributed with this package. * * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> */ #include "bitmap.h" #include "image.h" +#include "imagefile.h" +#include "glcd.h" +#include "pbm.h" +#include "extformats.h" +#include <string.h> namespace GLCD { @@ -64,4 +70,187 @@ void cImage::Clear() lastChange = 0; } + +uint32_t cImage::Blend(uint32_t FgColour, uint32_t BgColour, uint8_t Level, double antiAliasGranularity) const +{ + if (antiAliasGranularity > 0.0) + Level = uint8_t(int(Level / antiAliasGranularity + 0.5) * antiAliasGranularity); + int Af = (FgColour & 0xFF000000) >> 24; + int Rf = (FgColour & 0x00FF0000) >> 16; + int Gf = (FgColour & 0x0000FF00) >> 8; + int Bf = (FgColour & 0x000000FF); + int Ab = (BgColour & 0xFF000000) >> 24; + int Rb = (BgColour & 0x00FF0000) >> 16; + int Gb = (BgColour & 0x0000FF00) >> 8; + int Bb = (BgColour & 0x000000FF); + int A = (Ab + (Af - Ab) * Level / 0xFF) & 0xFF; + int R = (Rb + (Rf - Rb) * Level / 0xFF) & 0xFF; + int G = (Gb + (Gf - Gb) * Level / 0xFF) & 0xFF; + int B = (Bb + (Bf - Bb) * Level / 0xFF) & 0xFF; + return (A << 24) | (R << 16) | (G << 8) | B; +} + +bool cImage::Scale(uint16_t scalew, uint16_t scaleh, bool AntiAlias) +{ + if (! (scalew || scaleh) ) + return false; + + unsigned int orig_w = Width(); + unsigned int orig_h = Height(); + + // one out of scalew/h == 0 ? -> auto aspect ratio + if (scalew && ! scaleh) { + scaleh = (uint16_t)( ((uint32_t)scalew * (uint32_t)orig_h) / (uint32_t)orig_w ); + } else if (!scalew && scaleh) { + scalew = (uint16_t)( ((uint32_t)scaleh * (uint32_t)orig_w) / (uint32_t)orig_h ); + } + + cImage tempImg = cImage(); + tempImg.SetWidth(scalew); + tempImg.SetHeight(scaleh); + + // Scaling/Blending based on VDR / osd.c + // Fixed point scaling code based on www.inversereality.org/files/bitmapscaling.pdf + // by deltener@mindtremors.com + // + // slightly improved by Wolfgang Astleitner (modify factors and ratios so that scaled image is centered when upscaling) + + double FactorX, FactorY; + int RatioX, RatioY; + + if (!AntiAlias) { + FactorX = (double)scalew / (double)orig_w; + FactorY = (double)scaleh / (double)orig_h; + RatioX = (orig_w << 16) / scalew; + RatioY = (orig_h << 16) / scaleh; + } else { + FactorX = (double)scalew / (double)(orig_w-1); + FactorY = (double)scaleh / (double)(orig_h-1); + RatioX = ((orig_w-1) << 16) / scalew; + RatioY = ((orig_h-1) << 16) / scaleh; + } + + bool downscale = (!AntiAlias || (FactorX <= 1.0 && FactorY <= 1.0)); + + for (unsigned int frame = 0; frame < Count() ; frame ++ ) { + cBitmap *b = new cBitmap(scalew, scaleh, GRAPHLCD_Transparent); + + cBitmap *currFrame = GetBitmap(frame); + + b->SetMonochrome(currFrame->IsMonochrome()); + + if (downscale) { + // Downscaling - no anti-aliasing: + const uint32_t *DestRow = b->Data(); + int SourceY = 0; + for (int y = 0; y < scaleh; y++) { + int SourceX = 0; + const uint32_t *SourceRow = currFrame->Data() + (SourceY >> 16) * orig_w; + uint32_t *Dest = (uint32_t*) DestRow; + for (int x = 0; x < scalew; x++) { + *Dest++ = SourceRow[SourceX >> 16]; + SourceX += RatioX; + } + SourceY += RatioY; + DestRow += scalew; + } + } else { + // Upscaling - anti-aliasing: + int SourceY = 0; + for (int y = 0; y < scaleh /*- 1*/; y++) { + int SourceX = 0; + int sy = SourceY >> 16; + uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF); + for (int x = 0; x < scalew /*- 1*/; x++) { + int sx = SourceX >> 16; + uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF); + // TODO: antiAliasGranularity + uint32_t c1 = Blend(currFrame->GetPixel(sx, sy), currFrame->GetPixel(sx + 1, sy), BlendX); + uint32_t c2 = Blend(currFrame->GetPixel(sx, sy + 1), currFrame->GetPixel(sx + 1, sy + 1), BlendX); + uint32_t c3 = Blend(c1, c2, BlendY); + b->DrawPixel(x, y, c3); + SourceX += RatioX; + } + SourceY += RatioY; + } + } + tempImg.AddBitmap(b); + } + // clear all bitmaps from this image + unsigned int temp_delay = Delay(); + Clear(); + // set new resolution + SetWidth(scalew); + SetHeight(scaleh); + SetDelay(temp_delay); + // re-add bitmaps from scaled image container + cBitmap * b; + cBitmap * tempb; + for (unsigned int frame = 0; frame < tempImg.Count(); frame ++) { + tempb = tempImg.GetBitmap(frame); + b = new cBitmap(scalew, scaleh, (uint32_t*)tempb->Data()); + b->SetMonochrome(tempb->IsMonochrome()); + AddBitmap(b); + } + return true; +} + + +/* static methods */ +bool cImage::LoadImage(cImage & image, const std::string & fileName) { + const std::string fext = GetFilenameExtension(fileName); + cImageFile* imgFile = NULL; + bool result = true; + + if (fext == "PBM") { + imgFile = new cPBMFile(); + } else if (fext == "GLCD") { + imgFile = new cGLCDFile(); + } else { + imgFile = new cExtFormatFile(); + } + + uint16_t scale_w = 0; + uint16_t scale_h = 0; + + if (!imgFile || (imgFile->LoadScaled(image, fileName, scale_w, scale_h) == false) ) + result = false; + + if (imgFile) delete imgFile; + return result; +} + + +bool cImage::SaveImage(cImage & image, const std::string & fileName) { + const std::string fext = GetFilenameExtension(fileName); + cImageFile* imgFile = NULL; + bool result = false; + + if (fext == "PBM") { + imgFile = new cPBMFile(); + } else if (fext == "GLCD") { + imgFile = new cGLCDFile(); + } else { + imgFile = new cExtFormatFile(); + } + if ( imgFile && imgFile->Save(image, fileName) ) + result = true; + + if (imgFile) delete imgFile; + return result; +} + + +const std::string cImage::GetFilenameExtension(const std::string & fileName) { + size_t pos = fileName.find_last_of('.'); + std::string ext = ""; + if (pos != std::string::npos) { + ext = fileName.substr(pos+1); + for (size_t i = 0; i < ext.size(); i++) + ext[i] = toupper(ext[i]); + } + return ext; +} + + } // end of namespace diff --git a/glcdgraphics/image.h b/glcdgraphics/image.h index 888d942..f594886 100644 --- a/glcdgraphics/image.h +++ b/glcdgraphics/image.h @@ -10,6 +10,7 @@ * to the COPYING file distributed with this package. * * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> + * (c) 2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> */ #ifndef _GLCDGRAPHICS_IMAGE_H_ @@ -18,6 +19,7 @@ #include <stdint.h> #include <vector> +#include <string> namespace GLCD { @@ -33,6 +35,8 @@ private: unsigned int curBitmap; uint64_t lastChange; std::vector <cBitmap *> bitmaps; + + uint32_t Blend(uint32_t fgcol, uint32_t bgcol, uint8_t level, double antiAliasGranularity = 0.0) const; public: cImage(); ~cImage(); @@ -51,6 +55,12 @@ public: cBitmap * GetBitmap() const; void AddBitmap(cBitmap * Bitmap) { bitmaps.push_back(Bitmap); } void Clear(); + + bool Scale(uint16_t scalew, uint16_t scaleh, bool AntiAlias = false); + + static bool LoadImage(cImage & image, const std::string & fileName); + static bool SaveImage(cImage & image, const std::string & fileName); + static const std::string GetFilenameExtension(const std::string & fileName); }; } // end of namespace diff --git a/glcdgraphics/imagefile.c b/glcdgraphics/imagefile.c index b8c6a42..0f9ec25 100644 --- a/glcdgraphics/imagefile.c +++ b/glcdgraphics/imagefile.c @@ -7,7 +7,7 @@ * to the COPYING file distributed with this package. * * (c) 2006 Andreas Regel <andreas.regel AT powarman.de> - * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> */ #include "image.h" @@ -35,130 +35,12 @@ bool cImageFile::Save(cImage & image, const std::string & fileName) } -uint32_t cImageFile::Blend(uint32_t FgColour, uint32_t BgColour, uint8_t Level, double antiAliasGranularity) const -{ - if (antiAliasGranularity > 0.0) - Level = uint8_t(int(Level / antiAliasGranularity + 0.5) * antiAliasGranularity); - int Af = (FgColour & 0xFF000000) >> 24; - int Rf = (FgColour & 0x00FF0000) >> 16; - int Gf = (FgColour & 0x0000FF00) >> 8; - int Bf = (FgColour & 0x000000FF); - int Ab = (BgColour & 0xFF000000) >> 24; - int Rb = (BgColour & 0x00FF0000) >> 16; - int Gb = (BgColour & 0x0000FF00) >> 8; - int Bb = (BgColour & 0x000000FF); - int A = (Ab + (Af - Ab) * Level / 0xFF) & 0xFF; - int R = (Rb + (Rf - Rb) * Level / 0xFF) & 0xFF; - int G = (Gb + (Gf - Gb) * Level / 0xFF) & 0xFF; - int B = (Bb + (Bf - Bb) * Level / 0xFF) & 0xFF; - return (A << 24) | (R << 16) | (G << 8) | B; -} - -bool cImageFile::Scale(cImage & image, uint16_t scalew, uint16_t scaleh, bool AntiAlias) -{ - if (! (scalew || scaleh) ) - return false; - - // one out of scalew/h == 0 ? -> auto aspect ratio - if (scalew && ! scaleh) { - scaleh = (uint16_t)( ((uint32_t)scalew * (uint32_t)image.Height()) / (uint32_t)image.Width() ); - } else if (!scalew && scaleh) { - scalew = (uint16_t)( ((uint32_t)scaleh * (uint32_t)image.Width()) / (uint32_t)image.Height() ); - } - - cImage tempImg = cImage(); - tempImg.SetWidth(scalew); - tempImg.SetHeight(scaleh); - - // Scaling/Blending based on VDR / osd.c - // Fixed point scaling code based on www.inversereality.org/files/bitmapscaling.pdf - // by deltener@mindtremors.com - // - // slightly improved by Wolfgang Astleitner (modify factors and ratios so that scaled image is centered when upscaling) - - double FactorX, FactorY; - int RatioX, RatioY; - - if (!AntiAlias) { - FactorX = (double)scalew / (double)image.Width(); - FactorY = (double)scaleh / (double)image.Height(); - RatioX = (image.Width() << 16) / scalew; - RatioY = (image.Height() << 16) / scaleh; - } else { - FactorX = (double)scalew / (double)(image.Width()-1); - FactorY = (double)scaleh / (double)(image.Height()-1); - RatioX = ((image.Width()-1) << 16) / scalew; - RatioY = ((image.Height()-1) << 16) / scaleh; - } - - bool downscale = (!AntiAlias || (FactorX <= 1.0 && FactorY <= 1.0)); - - for (unsigned int frame = 0; frame < image.Count() ; frame ++ ) { - cBitmap *b = new cBitmap(scalew, scaleh, GRAPHLCD_Transparent); - - cBitmap *currFrame = image.GetBitmap(frame); - - b->SetMonochrome(currFrame->IsMonochrome()); - - if (downscale) { - // Downscaling - no anti-aliasing: - const uint32_t *DestRow = b->Data(); - int SourceY = 0; - for (int y = 0; y < scaleh; y++) { - int SourceX = 0; - const uint32_t *SourceRow = currFrame->Data() + (SourceY >> 16) * image.Width(); - uint32_t *Dest = (uint32_t*) DestRow; - for (int x = 0; x < scalew; x++) { - *Dest++ = SourceRow[SourceX >> 16]; - SourceX += RatioX; - } - SourceY += RatioY; - DestRow += scalew; - } - } else { - // Upscaling - anti-aliasing: - int SourceY = 0; - for (int y = 0; y < scaleh /*- 1*/; y++) { - int SourceX = 0; - int sy = SourceY >> 16; - uint8_t BlendY = 0xFF - ((SourceY >> 8) & 0xFF); - for (int x = 0; x < scalew /*- 1*/; x++) { - int sx = SourceX >> 16; - uint8_t BlendX = 0xFF - ((SourceX >> 8) & 0xFF); - // TODO: antiAliasGranularity - uint32_t c1 = Blend(currFrame->GetPixel(sx, sy), currFrame->GetPixel(sx + 1, sy), BlendX); - uint32_t c2 = Blend(currFrame->GetPixel(sx, sy + 1), currFrame->GetPixel(sx + 1, sy + 1), BlendX); - uint32_t c3 = Blend(c1, c2, BlendY); - b->DrawPixel(x, y, c3); - SourceX += RatioX; - } - SourceY += RatioY; - } - } - tempImg.AddBitmap(b); - } - // clear all bitmaps from image - image.Clear(); - // set new resolution - image.SetWidth(scalew); - image.SetHeight(scaleh); - // re-add bitmaps from scaled image container - cBitmap * b; - cBitmap * tempb; - for (unsigned int frame = 0; frame < tempImg.Count(); frame ++) { - tempb = tempImg.GetBitmap(frame); - b = new cBitmap(scalew, scaleh, (uint32_t*)tempb->Data()); - b->SetMonochrome(tempb->IsMonochrome()); - image.AddBitmap(b); - } - return true; -} bool cImageFile::LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh) { if (Load(image, fileName)) { if (scalew || scaleh) { - return Scale(image, scalew, scaleh, true); + return image.Scale(scalew, scaleh, true); } else { return true; } diff --git a/glcdgraphics/imagefile.h b/glcdgraphics/imagefile.h index 60049ea..fd7dbcc 100644 --- a/glcdgraphics/imagefile.h +++ b/glcdgraphics/imagefile.h @@ -7,7 +7,7 @@ * to the COPYING file distributed with this package. * * (c) 2006 Andreas Regel <andreas.regel AT powarman.de> - * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> */ #ifndef _GLCDGRAPHICS_IMAGEFILE_H_ @@ -22,10 +22,6 @@ class cImage; class cImageFile { -private: - uint32_t Blend(uint32_t fgcol, uint32_t bgcol, uint8_t level, double antiAliasGranularity = 0.0) const; -protected: - bool Scale(cImage & image, uint16_t scalew, uint16_t scaleh, bool AntiAlias = false); public: cImageFile(); virtual ~cImageFile(); diff --git a/glcdgraphics/pbm.c b/glcdgraphics/pbm.c index d5c0576..3bf94c1 100644 --- a/glcdgraphics/pbm.c +++ b/glcdgraphics/pbm.c @@ -7,7 +7,7 @@ * to the COPYING file distributed with this package. * * (c) 2006-2010 Andreas Regel <andreas.regel AT powarman.de> - * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net> + * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> * Andreas 'randy' Weinberger */ @@ -152,7 +152,7 @@ bool cPBMFile::Load(cImage & image, const std::string & fileName) return false; } fclose(pbmFile); - syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str()); + syslog(LOG_DEBUG, "glcdgraphics: image '%s' loaded.", fileName.c_str()); return true; } @@ -189,7 +189,6 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName) } sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height()); fwrite(str, strlen(str), 1, fp); -// fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); fwrite(rawdata, rawdata_size, 1, fp); } fclose(fp); @@ -201,10 +200,17 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName) { uint16_t i; char tmpStr[256]; + size_t pos = fileName.find_last_of('.'); + std::string fileExt = ""; + std::string fileBase = fileName; + if (pos != std::string::npos) { + fileExt = fileName.substr(pos); + fileBase = fileName.substr(0, fileName.length() - fileExt.length()); + } for (i = 0; i < image.Count(); i++) { - sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i); + sprintf(tmpStr, "%.244s-%05d%s", fileBase.c_str(), i, fileExt.c_str()); fp = fopen(tmpStr, "wb"); if (fp) { @@ -226,7 +232,6 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName) } sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height()); fwrite(str, strlen(str), 1, fp); -// fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp); fwrite(rawdata, rawdata_size, 1, fp); } fclose(fp); diff --git a/graphlcd.conf b/graphlcd.conf index 3e28240..625ee12 100644 --- a/graphlcd.conf +++ b/graphlcd.conf @@ -22,7 +22,7 @@ # 1 - nanosleep # 2 - nanosleep (sched_rr) - This is recommended on kernel 2.4 systems # 3 - gettimeofday - This is recommended on kernel 2.6 systems -# Defaukt value: 3 +# Default value: 3 WaitMethod=3 # WaitPriority diff --git a/tools/convpic/Makefile b/tools/convpic/Makefile index a3a0f6e..6ed0d76 100644 --- a/tools/convpic/Makefile +++ b/tools/convpic/Makefile @@ -6,7 +6,7 @@ PRGNAME = convpic -OBJS = $(PRGNAME).o bmp.o tiff.o tuxbox.o +OBJS = $(PRGNAME).o INCLUDES += -I../../ LIBDIRS += -L../../glcdgraphics/ diff --git a/tools/convpic/bmp.c b/tools/convpic/bmp.c deleted file mode 100644 index 0357988..0000000 --- a/tools/convpic/bmp.c +++ /dev/null @@ -1,378 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * bmp.c - bmp logo class - * - * (C) 2004 Andreas Brachold <vdr04 AT deltab de> - * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ - -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <cstring> -#include <cstdlib> - -#include <glcdgraphics/bitmap.h> -#include <glcdgraphics/image.h> - -#include "bmp.h" - - -#pragma pack(1) -typedef struct BMPH { - uint16_t bmpIdentifier; - uint32_t bmpFileSize; - uint32_t bmpReserved; - uint32_t bmpBitmapDataOffset; - uint32_t bmpBitmapHeaderSize; - uint32_t bmpWidth; - uint32_t bmpHeight; - uint16_t bmpPlanes; - uint16_t bmpBitsPerPixel; - uint32_t bmpCompression; - uint32_t bmpBitmapDataSize; - uint32_t bmpHResolution; - uint32_t bmpVResolution; - uint32_t bmpColors; - uint32_t bmpImportantColors; -} BMPHEADER; // 54 bytes - -typedef struct RGBQ { - uint8_t rgbBlue; - uint8_t rgbGreen; - uint8_t rgbRed; - uint8_t rgbReserved; -} RGBQUAD; // 4 bytes -#pragma pack() - - -uint8_t bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; -uint8_t bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; -uint8_t bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; - -cBMPFile::cBMPFile() -{ -} - -cBMPFile::~cBMPFile() -{ -} - -bool cBMPFile::Load(GLCD::cImage & image, const std::string & fileName) -{ - FILE *fIN; - BMPHEADER bmpHeader; - RGBQUAD *pPalette; - char *pByte; - char Dummy; - long iNumColors; - long iSize; - uint32_t x, y; - uint16_t iRead; -// uint8_t * bitmap = NULL; - uint32_t *bitmap = NULL; - bool bInvert = false; - - if (fileName.length() > 0) - { - fIN = fopen(fileName.c_str(), "rb"); - if (fIN) - { - if (fread(&bmpHeader, sizeof(BMPHEADER), 1, fIN)!=1) - { - fclose(fIN); - return false; - } - - // check for Windows BMP - if (bmpHeader.bmpBitmapHeaderSize != 0x00000028 ) - { - fprintf(stderr, "ERROR: only Windows BMP images are allowed.\n"); - fclose(fIN); - return false; - } - - // check for 2 color - iNumColors = (1 << bmpHeader.bmpBitsPerPixel); - if (iNumColors != 2) - { - fprintf(stderr, "ERROR: the image has %ld colors, but only images with 2 colors are allowed.\n", iNumColors); - fclose(fIN); - return false; - } - - iSize = bmpHeader.bmpHeight * bmpHeader.bmpWidth; - - pPalette = (RGBQUAD *) malloc( iNumColors*sizeof(RGBQUAD)); - if (!pPalette) - { - fprintf(stderr, "ERROR: cannot allocate memory\n"); - fclose(fIN); - return false; - } - - if (fread( pPalette, iNumColors*sizeof(RGBQUAD), 1, fIN)!=1) - { - free(pPalette); - fclose(fIN); - return false; - } - - // check colors - if (pPalette->rgbBlue+pPalette->rgbGreen+pPalette->rgbRed < - (pPalette+1)->rgbBlue+(pPalette+1)->rgbGreen+(pPalette+1)->rgbRed) - { - // index 0 represents 'black', index 1 'white' - bInvert = !bInvert; - } - else - { - // index 0 represents 'white', index 1 'black' - } - - if (fseek(fIN, bmpHeader.bmpBitmapDataOffset, SEEK_SET)==EOF) - { - free(pPalette); - fclose(fIN); - return false; - } - - switch (bmpHeader.bmpCompression) - { - case 0: // BI_RGB no compression - image.Clear(); - image.SetWidth(bmpHeader.bmpWidth); - image.SetHeight(bmpHeader.bmpHeight); - image.SetDelay(100); -// bitmap = new unsigned char[bmpHeader.bmpHeight * ((bmpHeader.bmpWidth + 7) / 8)]; - bitmap = new uint32_t [bmpHeader.bmpHeight * bmpHeader.bmpWidth]; - if (!bitmap) - { - fprintf(stderr, "ERROR: cannot allocate memory\n"); - free(pPalette); - fclose(fIN); - image.Clear(); - return false; - } - - for (y = bmpHeader.bmpHeight; y > 0; y--) - { - pByte = (char*)bitmap + (y-1)*((bmpHeader.bmpWidth+7)/8); - iRead = 0; - for (x = 0; x < bmpHeader.bmpWidth / 8; x++) - { - if (fread(pByte, sizeof(char), 1, fIN) != 1) - { - delete[] bitmap; - free(pPalette); - fclose(fIN); - image.Clear(); - return false; - } - iRead++; - if (bInvert) - *pByte = *pByte ^ 0xff; - pByte++; - } - - if (bmpHeader.bmpWidth % 8) - { - if (fread(pByte, sizeof(char), 1, fIN) != 1) - { - delete [] bitmap; - free(pPalette); - fclose(fIN); - image.Clear(); - return false; - } - iRead++; - if (bInvert) - *pByte = *pByte^0xff; - *pByte = *pByte & bitmaskl[bmpHeader.bmpWidth%8]; - pByte++; - } - - // Scan line must be 4-byte-alligned - while (iRead % 4) - { - if (fread(&Dummy, sizeof(char), 1, fIN) != 1) - { - delete [] bitmap; - free(pPalette); - fclose(fIN); - image.Clear(); - return false; - } - iRead++; - } - } - image.AddBitmap(new GLCD::cBitmap(bmpHeader.bmpWidth, bmpHeader.bmpHeight, bitmap)); - break; - case 1: // BI_RLE4 RLE 4bit/pixel - case 2: // BI_RLE8 RLE 8bit/pixel - case 3: // BI_BITFIELDS - default: - fprintf(stderr, "ERROR: only uncompressed RGB images are allowed.\n"); - - free(pPalette); - fclose(fIN); - return false; - } - fclose(fIN); - } - else - { - fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str()); - } - } - else - { - fprintf(stderr, "ERROR: no FileName given!\n"); - } - return true; -} - -bool cBMPFile::Save(const GLCD::cBitmap * bitmap, const std::string & fileName) -{ - FILE *fOut; - BMPHEADER bmpHeader; - RGBQUAD bmpColor1, bmpColor2; - uint32_t dBDO, dBDSx, dBDS; - char *pByte; - char Dummy = 0x00; - uint32_t x, y; - uint16_t iWrote; -// const uint8_t * bmpdata = bitmap->Data(); - const uint32_t * bmpdata = bitmap->Data(); - - if (bitmap - && bitmap->Width() > 0 - && bitmap->Height() > 0) - { - memset(&bmpHeader, 0, sizeof(BMPHEADER)); - - dBDO = sizeof(BMPHEADER)+2*sizeof(RGBQUAD); - dBDSx = ((bitmap->Width() + 7) / 8 + 3) & 0xfffffffc; - dBDS = dBDSx * bitmap->Height(); - - bmpHeader.bmpIdentifier = 0x4d42; // "BM" - bmpHeader.bmpFileSize = dBDO + dBDS; - bmpHeader.bmpBitmapDataOffset = dBDO; - bmpHeader.bmpBitmapHeaderSize = 0x28; - bmpHeader.bmpWidth = bitmap->Width(); - bmpHeader.bmpHeight = bitmap->Height(); - bmpHeader.bmpPlanes = 0x01; - bmpHeader.bmpBitsPerPixel = 0x01; - bmpHeader.bmpCompression = 0x00; - bmpHeader.bmpBitmapDataSize = dBDS; - bmpHeader.bmpHResolution = 0xb13; // 72dpi - bmpHeader.bmpVResolution = 0xb13; // 72dpi - bmpHeader.bmpColors = 0x02; - bmpHeader.bmpImportantColors = 0x02; - - bmpColor1.rgbBlue = 0x00; - bmpColor1.rgbGreen = 0x00; - bmpColor1.rgbRed = 0x00; - bmpColor1.rgbReserved = 0x00; - bmpColor2.rgbBlue = 0xff; - bmpColor2.rgbGreen = 0xff; - bmpColor2.rgbRed = 0xff; - bmpColor2.rgbReserved = 0x00; - - - fOut = fopen(fileName.c_str(), "wb"); - if (!fOut) - { - fprintf(stderr,"Cannot create file: %s\n", fileName.c_str()); - return false; - } - fwrite(&bmpHeader, sizeof(BMPHEADER), 1, fOut); - fwrite(&bmpColor1, sizeof(RGBQUAD), 1, fOut); - fwrite(&bmpColor2, sizeof(RGBQUAD), 1, fOut); - - for (y=bitmap->Height(); y>0; y--) - { - pByte = (char*)bmpdata + (y-1)*((bitmap->Width()+7)/8); - iWrote = 0; - for (x=0; x<(uint32_t) bitmap->Width()/8; x++) - { - *pByte = *pByte^0xff; - if (fwrite(pByte, sizeof(char), 1, fOut)!=1) - { - fclose(fOut); - return false; - } - iWrote++; - pByte++; - } - // Scan line must be 4-byte-alligned - while (iWrote%4) - { - if (fwrite(&Dummy, sizeof(char), 1, fOut)!=1) - { - fclose(fOut); - return 3; - } - iWrote++; - } - } - fclose(fOut); - } - return true; -} - -bool cBMPFile::Save(GLCD::cImage & image, const std::string & fileName) -{ - const GLCD::cBitmap * bitmap; - - if (image.Count() == 1) - { - bitmap = image.GetBitmap(0); - if (bitmap) - { - if (!Save(bitmap, fileName)) - { - return false; - } - } - } - else - { - uint16_t i; - char tmpStr[256]; - - for (i = 0; i < image.Count(); i++) - { - sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i); - bitmap = image.GetBitmap(i); - if (bitmap) - { - if (!Save(bitmap, tmpStr)) - { - return false; - } - } - } - } - return true; -} diff --git a/tools/convpic/bmp.h b/tools/convpic/bmp.h deleted file mode 100644 index 8419838..0000000 --- a/tools/convpic/bmp.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * bmp.h - bmp logo class - * - * (C) 2004 Andreas Brachold <vdr04 AT deltab de> - * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ - -#ifndef _BMP_H_ -#define _BMP_H_ - -#include <glcdgraphics/imagefile.h> - -class cBMPFile : public GLCD::cImageFile -{ -private: - bool Save(const GLCD::cBitmap * bitmap, const std::string & fileName); -public: - cBMPFile(); - virtual ~cBMPFile(); - virtual bool Load(GLCD::cImage & image, const std::string & fileName); - virtual bool Save(GLCD::cImage & image, const std::string & fileName); -}; - -#endif diff --git a/tools/convpic/convpic.c b/tools/convpic/convpic.c index 732738c..252b6c8 100644 --- a/tools/convpic/convpic.c +++ b/tools/convpic/convpic.c @@ -5,6 +5,7 @@ * * (C) 2004 Andreas Brachold <vdr04 AT deltab de> * (C) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de> + * (C) 2013 Wolfgang Astleitner <mrwastl AT users sourceforge net> **/ /*************************************************************************** @@ -40,98 +41,41 @@ #include <glcdgraphics/glcd.h> #include <glcdgraphics/pbm.h> -#include "bmp.h" -#include "tiff.h" -#include "tuxbox.h" - static const char *prgname = "convpic"; -static const char *VERSION = "0.1.1"; +static const char *VERSION = "0.1.3"; unsigned int delay = 250; -enum ePicFormat -{ - pfUndefined, - pfTIFF, - pfBMP, - pfGLCD, - pfPBM, - pfTUXBOX -}; - -void usage(void); - -ePicFormat getFormat(const char* szFile) -{ - static const struct tagformats {const char* szExt; ePicFormat picformat;} formats[] = - { - {".tiff", pfTIFF }, - {".tif", pfTIFF }, - {".bmp", pfBMP }, - {".glcd", pfGLCD }, - {".pbm", pfPBM }, - {".ani", pfTUXBOX} - }; - ePicFormat pf = pfUndefined; - - if (szFile) - { - for (int i = strlen(szFile) - 1; i >= 0; i--) - { - if (*(szFile+i) == '.' && strlen(szFile + i + 1)) - { - for (unsigned int n = 0; n < sizeof(formats)/sizeof(*formats); n++) - { - if (!strcasecmp((szFile+i), formats[n].szExt)) - { - return formats[n].picformat; - } - } - } - } - } - return pf; +void usage(void) { + fprintf(stdout, "\n"); + fprintf(stdout, "%s v%s\n", prgname, VERSION); + fprintf(stdout, "%s is a tool to convert images to a simple format (*.glcd)\n", prgname); + fprintf(stdout, " that is used by the graphlcd plugin for VDR.\n\n"); + fprintf(stdout, " Usage: %s [-n] -i file[s...] -o outfile \n\n", prgname); + fprintf(stdout, " -n --invert inverts the output (default: none)\n"); + fprintf(stdout, " -i --infile specifies the name of the input file[s]\n"); + fprintf(stdout, " -o --outfile specifies the name of the output file\n"); + fprintf(stdout, " -d --delay specifies the delay between multiple images [Default: %d ms] \n",delay); + fprintf(stdout, "\n" ); + fprintf(stdout, " example: %s -i vdr-logo.bmp -o vdr-logo.glcd \n", prgname ); } -GLCD::cImageFile * GetFileTranslator(ePicFormat Format) -{ - switch (Format) - { - case pfGLCD: - return new GLCD::cGLCDFile(); - - case pfPBM: - return new GLCD::cPBMFile(); - - case pfBMP: - return new cBMPFile(); - - case pfTIFF: - return new cTIFFFile(); - - case pfTUXBOX: - return new cTuxBoxFile(); - - default: - return NULL; - } - -} int main(int argc, char *argv[]) { - ePicFormat inFormat = pfUndefined; - ePicFormat outFormat = pfUndefined; std::string inFile = ""; std::string outFile = ""; + std::string inExtension = ""; + std::string outExtension = ""; GLCD::cImage image; GLCD::cImage nextImage; - GLCD::cImageFile * pInBitmap = NULL; - GLCD::cImageFile * pOutBitmap = NULL; bool bError = false; bool bInvert = false; bool bDelay = false; + unsigned int image_w = 0; + unsigned int image_h = 0; + static struct option long_options[] = { @@ -162,97 +106,108 @@ int main(int argc, char *argv[]) { bDelay = true; if (delay < 10) { - fprintf(stderr, "Warning: You have specify a to short delay, minimum are 10 ms\n"); + fprintf(stderr, "WARNING: Delay is too short, minimum delay is 10 ms\n"); delay = 10; } break; default: + usage(); return 1; } } - if (inFile.length() == 0) - { + if (inFile.length() == 0) { fprintf(stderr, "ERROR: You have to specify the infile (-i filename)\n"); bError = true; } - if (pfUndefined == (inFormat = getFormat(inFile.c_str()))) - { - fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str()); + inExtension = GLCD::cImage::GetFilenameExtension(inFile); + + if (outFile.length() == 0) { + outFile = inFile.substr(0, inFile.length() - inExtension.length() - 1); + if (inExtension == "GLCD") { + outFile += ".pbm"; + outExtension = "PBM"; + } else { + outFile += ".glcd"; + outExtension = "GLCD"; + } + fprintf(stderr, "WARNING: No output filename given, will use '%s'\n", outFile.c_str()); + } + + if (outExtension.length() == 0) { + outExtension = GLCD::cImage::GetFilenameExtension(outFile); + } + + if ( !(outExtension == "GLCD" || outExtension == "PBM") ) { + fprintf(stderr, "ERROR: Unsupported format for outfile ('%s')\n", outExtension.c_str()); bError = true; } - if (outFile.length() == 0) - { - fprintf(stderr, "ERROR: You have to specify the outfile (-o filename)\n"); + if ( inExtension != "GLCD" && outExtension != "GLCD" ) { + fprintf(stderr, "ERROR: Either infile or outfile needs to be a GLCD file\n"); bError = true; } - if (pfUndefined == (outFormat = getFormat(outFile.c_str()))) - { - fprintf(stderr, "ERROR: You have to specify a correct extension for the %s \n", outFile.c_str()); + if ( outExtension != "GLCD" && outExtension != "PBM" ) { + fprintf(stderr, "ERROR: outfile needs to be either GLCD or PBM\n"); bError = true; } - if (bError) - { + if (bError) { usage(); return 1; } - - pInBitmap = GetFileTranslator(inFormat); - if (!pInBitmap) - return 2; - - pOutBitmap = GetFileTranslator(outFormat); - if (!pOutBitmap) - return 3; - // Load Picture fprintf(stdout, "loading %s\n", inFile.c_str()); - bError = !pInBitmap->Load(image, inFile); - if (!bError) - { + if (GLCD::cImage::LoadImage(image, inFile) == false) { + fprintf(stderr, "ERROR: Failed loading file %s\n", inFile.c_str()); + bError = true; + } + + /* if more than one input image: following images must match width and height of first image */ + image_w = image.GetBitmap(0)->Width(); + image_h = image.GetBitmap(0)->Height(); + + if (!bError) { + GLCD::cImageFile * outImage = NULL; // Load more in files - while (optind < argc && !bError) - { + while (optind < argc && !bError) { inFile = argv[optind++]; - inFormat = getFormat(inFile.c_str()); - if (inFormat == pfUndefined) - { - fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str()); - bError = true; - break; - } - pInBitmap = GetFileTranslator(inFormat); - if (!pInBitmap) - break; fprintf(stdout, "loading %s\n", inFile.c_str()); - if (pInBitmap->Load(nextImage, inFile)) - { + if (GLCD::cImage::LoadImage(nextImage, inFile) == false) { + fprintf(stderr, "ERROR: Failed loading file '%s', ignoring it ...\n", inFile.c_str()); + } else { + unsigned int nim_w = nextImage.GetBitmap(0)->Width(); + unsigned int nim_h = nextImage.GetBitmap(0)->Height(); + if ( nim_w != image_w || nim_h != image_h) { + fprintf(stderr, "ERROR: Image '%s' is not matching dimensions of first image, ignoring it ...\n", inFile.c_str()); + } else { uint16_t i; - for (i = 0; i < nextImage.Count(); i++) - { + for (i = 0; i < nextImage.Count(); i++) { image.AddBitmap(new GLCD::cBitmap(*nextImage.GetBitmap(i))); } + } } } if (bDelay) image.SetDelay(delay); - if (bInvert) - { + if (bInvert) { uint16_t i; - for (i = 0; i < image.Count(); i++) - { + for (i = 0; i < image.Count(); i++) { image.GetBitmap(i)->Invert(); } } + if (outExtension == "PBM") { + outImage = new GLCD::cPBMFile(); + } else { + outImage = new GLCD::cGLCDFile(); + } fprintf(stdout, "saving %s\n", outFile.c_str()); - bError = !pOutBitmap->Save(image, outFile); + bError = !outImage->Save(image, outFile); } if (bError) { return 4; @@ -262,18 +217,3 @@ int main(int argc, char *argv[]) { return 0; } - -void usage(void) -{ - fprintf(stdout, "\n"); - fprintf(stdout, "%s v%s\n", prgname, VERSION); - fprintf(stdout, "%s is a tool to convert images to a simple format (*.glcd)\n", prgname); - fprintf(stdout, " that is used by the graphlcd plugin for VDR.\n\n"); - fprintf(stdout, " Usage: %s [-n] -i file[s...] -o outfile \n\n", prgname); - fprintf(stdout, " -n --invert inverts the output (default: none)\n"); - fprintf(stdout, " -i --infile specifies the name of the input file[s]\n"); - fprintf(stdout, " -o --outfile specifies the name of the output file\n"); - fprintf(stdout, " -d --delay specifies the delay between multiple images [Default: %d ms] \n",delay); - fprintf(stdout, "\n" ); - fprintf(stdout, " example: %s -i vdr-logo.bmp -o vdr-logo.glcd \n", prgname ); -} diff --git a/tools/convpic/tiff.c b/tools/convpic/tiff.c deleted file mode 100644 index 3eb8cad..0000000 --- a/tools/convpic/tiff.c +++ /dev/null @@ -1,203 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * tiff.c - tiff logo class - * - * (c) 2004 Andreas Brachold <vdr04 AT deltab de> - * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ - -#include <stdio.h> -#include <string.h> - -#include <string> - -#include <glcdgraphics/bitmap.h> -#include <glcdgraphics/image.h> - -#include "tiff.h" - - -#pragma pack(1) -typedef struct TIFFT{ - unsigned short tag; - unsigned short type; - unsigned long length; - /* 1 = BYTE. 8-bit unsigned integer. */ - /* 2 = ASCII. 8-bit bytes that store ASCII codes; the last byte must be null. */ - /* 3 = SHORT. A 16-bit (2-byte) unsigned integer. */ - /* 4 = LONG. A 32-bit (4-byte) unsigned integer. */ - /* 5 = RATIONAL. Two LONGs: the first represents the numerator of a fraction, the second the denominator. */ - unsigned long off_val; -} TIFFTAG; -#pragma pack() - -#define GETANDCHECK { t=fgetc(fIN);if(t==EOF) {fclose(fIN);return false;};} - -cTIFFFile::cTIFFFile() -{ -} - -cTIFFFile::~cTIFFFile() -{ -} - -bool cTIFFFile::Load(GLCD::cImage & image, const std::string & fileName) -{ - FILE *fIN; - TIFFTAG tifftag; - unsigned int tiff_header, tiff_anztags, tiff_data; - unsigned char cl,ch,y,i; - unsigned char height, width, strip, invert; - unsigned char fLittleEndian=0; - int j; - int t; -// unsigned char *bitmap = NULL; - uint32_t *bitmap = NULL; - bool bInvert = false; - - if (fileName.length() > 0) - { - fIN = fopen(fileName.c_str(), "rb"); - if (fIN) - { - // isyslog("graphlcd plugin: try to load logo %s.", szFileName); - if (fseek(fIN, 0, SEEK_SET)==EOF) - { - fclose(fIN); - return false; - } - GETANDCHECK; cl=(unsigned char)t; - GETANDCHECK; ch=(unsigned char)t; - if ((cl==0x49) && (ch==0x49)) - { - fLittleEndian=1; - } - - if (fseek(fIN, 4, SEEK_SET)==EOF) - { - fclose(fIN); - return false; - } - GETANDCHECK; cl=(unsigned char)t; - GETANDCHECK; ch=(unsigned char)t; - tiff_header = cl+256*ch; - //printf("tiff_header:%d %x\n", tiff_header, tiff_header); - - if (fseek(fIN, tiff_header, SEEK_SET)==EOF) - { - fclose(fIN); - return false; - } - - GETANDCHECK; cl=(unsigned char)t; - GETANDCHECK; ch=(unsigned char)t; - tiff_anztags = cl+256*ch; - //printf("tiff_anztags:%d %x\n", tiff_anztags, tiff_anztags); - - height=0; - width=0; - strip=0; - invert=0; - for (i=0; (i<tiff_anztags)&&(!height||!width||!strip||!invert); i++) - { - if (fread(&tifftag, sizeof(tifftag), 1, fIN)!=1) - { - fclose(fIN); - return false; - } - if (tifftag.tag==0x0100) width=tifftag.off_val; - if (tifftag.tag==0x0101) height=tifftag.off_val; - if (tifftag.tag==0x0111) strip=tifftag.off_val; - if (tifftag.tag==0x0106) invert=tifftag.off_val+1; - //printf("tag%d: %d %d %ld %ld\n", i,tifftag.tag, tifftag.type, tifftag.length, tifftag.off_val ); - } - - if (fseek(fIN,strip, SEEK_SET)==EOF) - { - fclose(fIN); - return false; - } - GETANDCHECK; cl=(unsigned char)t; - GETANDCHECK; ch=(unsigned char)t; - tiff_data = cl+256*ch; - //printf("tiff_data:%d %x\n", tiff_data, tiff_data); - - if (fseek(fIN, tiff_data, SEEK_SET)==EOF) - { - fclose(fIN); - return false; - } - - - image.Clear(); - image.SetWidth(width); - image.SetHeight(height); - image.SetDelay(100); -// bitmap = new unsigned char[height * ((width + 7) / 8)]; - bitmap = new uint32_t[height * width]; - if (bitmap) - { - if (fread(bitmap, height*((width+7)/8), 1, fIN)!=1) - { - delete [] bitmap; - fclose(fIN); - image.Clear(); - return false; - } - - if (invert-1==1) bInvert = !bInvert; // 'Black is zero' - if (bInvert) - { - for (j=0; j < height * ((width+7)/8); j++) - { - (*(bitmap+j)) = (*(bitmap+j))^0xff; - } - } - - // cut the rest of the line - if (width%8) - { - for (y=1; y<=height; y++) { - j=y*((width+7)/8)-1; - (*(bitmap+j)) = ((*(bitmap+j))>>(8-width%8))<<(8-width%8); - } - } - image.AddBitmap(new GLCD::cBitmap(width, height, bitmap)); - } - else - { - fprintf(stderr, "ERROR: cannot allocate memory\n"); - } - fclose(fIN); - } - else - { - fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str()); - } - } - else - { - fprintf(stderr, "ERROR: no szFileName given!\n"); - } - return true; -} diff --git a/tools/convpic/tiff.h b/tools/convpic/tiff.h deleted file mode 100644 index f6e66c1..0000000 --- a/tools/convpic/tiff.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * tiff.h - tiff logo class - * - * (c) 2004 Andreas Brachold <vdr04 AT deltab de> - * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ - -#ifndef _TIFF_H_ -#define _TIFF_H_ - -#include <glcdgraphics/imagefile.h> - -class cTIFFFile : public GLCD::cImageFile -{ -public: - cTIFFFile(); - virtual ~cTIFFFile(); - virtual bool Load(GLCD::cImage & image, const std::string & fileName); -}; - -#endif diff --git a/tools/convpic/tuxbox.c b/tools/convpic/tuxbox.c deleted file mode 100644 index 9e3f558..0000000 --- a/tools/convpic/tuxbox.c +++ /dev/null @@ -1,287 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * tuxbox.c - tuxbox logo class - * - * (c) 2004 Andreas Brachold <vdr04 AT deltab de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <netinet/in.h> - -#include <string> - -#include <glcdgraphics/bitmap.h> -#include <glcdgraphics/image.h> - -#include "tuxbox.h" - -#pragma pack(1) -struct ani_header { - unsigned char magic[4]; // = "LCDA" - unsigned short format; // Format - unsigned short width; // Breite - unsigned short height; // Höhe - unsigned short count; // Anzahl Einzelbilder - unsigned long delay; // µs zwischen Einzelbildern -}; -#pragma pack() - -cTuxBoxFile::cTuxBoxFile() -{ -} - -cTuxBoxFile::~cTuxBoxFile() -{ -} - -bool cTuxBoxFile::Load(GLCD::cImage & image, const std::string & fileName) -{ - bool ret = false; - FILE * fIN; - long fileLen; - struct ani_header header; - bool bInvert = false; - - fIN = fopen(fileName.c_str(), "rb"); - if (fIN) - { - // get len of file - if (fseek(fIN, 0, SEEK_END)) - { - fclose(fIN); - return false; - } - fileLen = ftell(fIN); - - // rewind and get Header - if (fseek(fIN, 0, SEEK_SET)) - { - fclose(fIN); - return false; - } - - // Read header - if (fread(&header, sizeof(header), 1, fIN) != 1) - { - fclose(fIN); - return false; - } - - image.Clear(); - image.SetWidth(ntohs(header.width)); - image.SetHeight(ntohs(header.height)); - image.SetDelay(ntohl(header.delay) / 1000); - - // check Header - if (strncmp((const char*)header.magic, "LCDA", sizeof(header.magic)) || - !image.Width() || !image.Height() || ntohs(header.format) != 0) - { - fprintf(stderr, "ERROR: load %s failed, wrong header.\n", fileName.c_str()); - fclose(fIN); - return false; - } - - //fprintf(stderr,"%d %dx%d (%d %d) %d\n",ntohs(header.count),image.Width(),image.Height(),fileLen, ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header)),lhdr.delay); - - // check file length - if (!ntohs(header.count) - || (fileLen != (long) ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header)))) - { - fprintf(stderr, "ERROR: load %s failed, wrong size.\n", fileName.c_str()); - fclose(fIN); - return false; - } - // Set minimal limit for next image - if (image.Delay() < 10) - image.SetDelay(10); - for (unsigned int n=0;n<ntohs(header.count);++n) - { - ret = false; -// unsigned int nBmpSize = image.Height() * ((image.Width() + 7) / 8); - unsigned int nBmpSize = image.Height() * image.Width(); -// unsigned char *bitmap = new unsigned char[nBmpSize]; - uint32_t *bitmap = new uint32_t [nBmpSize]; - if (!bitmap) - { - fprintf(stderr, "ERROR: malloc failed."); - break; - } -// unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8); - unsigned int nAniSize = image.Width() * image.Height(); -// unsigned char *pAni = new unsigned char[nAniSize]; - uint32_t *pAni = new uint32_t [nAniSize]; - if (!pAni) - { - delete[] bitmap; - fprintf(stderr, "ERROR: malloc failed."); - break; - } - - if (1 != fread(pAni, nAniSize, 1, fIN)) - { - fprintf(stderr,"ERROR: Cannot read filedata: %s\n", fileName.c_str()); - delete[] bitmap; - delete[] pAni; - break; - } - - vert2horz(pAni,bitmap, image.Width(), image.Height()); - delete[] pAni; - - if (bInvert) - for (unsigned int i=0;i<nBmpSize;++i) - bitmap[i] ^= 0xFF; - - image.AddBitmap(new GLCD::cBitmap(image.Width(), image.Height(), bitmap)); - ret = true; - } - fclose(fIN); - if (!ret) - image.Clear(); - } - return ret; -} - - -bool cTuxBoxFile::Save(GLCD::cImage & image, const std::string & fileName) -{ - FILE * fOut; - struct ani_header header; - bool bRet = false; - - if (image.Count() > 0 - && image.Width() - && image.Height()) - { - memcpy(header.magic, "LCDA", 4); - header.format = htons(0); - header.width = htons(image.Width()); - header.height = htons(image.Height()); - header.count = htons(image.Count()); - header.delay = htonl(image.Delay() * 1000); - - - if (image.Width() != 120 || image.Height() != 64) - { - fprintf(stderr,"WARNING: Maybe wrong image dimension (for all I know is 120x64 wanted) %s\n", fileName.c_str()); - } - - fOut = fopen(fileName.c_str(), "wb"); - if (!fOut) { - fprintf(stderr,"ERROR: Cannot create file: %s\n", fileName.c_str()); - return false; - } - - if (1 != fwrite(&header, sizeof(header), 1, fOut)) - { - fprintf(stderr,"ERROR: Cannot write fileheader: %s\n", fileName.c_str()); - fclose(fOut); - return false; - } - - for (unsigned int n = 0; n < image.Count(); n++) - { - bRet = false; - unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8); -// unsigned char *pAni = new unsigned char[nAniSize]; - uint32_t *pAni = new uint32_t [nAniSize]; - if (!pAni) - { - fprintf(stderr, "ERROR: malloc failed."); - break; - } - horz2vert(image.GetBitmap(n)->Data(), pAni, image.Width(), image.Height()); - - if (1 != fwrite(pAni, nAniSize, 1, fOut)) - { - delete [] pAni; - fprintf(stderr,"ERROR: Cannot write filedata: %s\n", fileName.c_str()); - break; - } - delete [] pAni; - bRet = true; - } - - fclose(fOut); - } - return bRet; -} - -/** Translate memory alignment from vertical to horizontal -rotate from {Byte} to {Byte} -{o}[o][o][o][o][o][o][o] => { oooooooo } -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ] -{o}[o][o][o][o][o][o][o] => [ oooooooo ]*/ -//void cTuxBoxFile::vert2horz(const unsigned char* source, unsigned char* dest, int width, int height) { -void cTuxBoxFile::vert2horz(const uint32_t *source, uint32_t *dest, int width, int height) { - int x, y, off; - memset(dest,0,height*((width+7)/8)); - - for (y=0; y<height; ++y) - { - for (x=0; x<width; ++x) - { - off = x + ((y/8) * width); - if (source[off] & (0x1 << (y % 8))) - { - off = (x / 8) + (y * ((width+7)/8)); - dest[off] |= (unsigned char)(0x80 >> (x % 8)); - } - } - } -} - -/** Translate memory alignment from horizontal to vertical (rotate byte) -rotate from {Byte} to {Byte} -{ oooooooo } => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o] -[ oooooooo ] => {o}[o][o][o][o][o][o][o]*/ -//void cTuxBoxFile::horz2vert(const unsigned char* source, unsigned char* dest, int width, int height) { -void cTuxBoxFile::horz2vert(const uint32_t *source, uint32_t *dest, int width, int height) { - int x, y, off; - memset(dest,0,width*((height+7)/8)); - - for (y=0; y<height; ++y) - { - for (x=0; x<width; ++x) - { - off = (x / 8) + ((y) * ((width+7)/8)); - if (source[off] & (0x80 >> (x % 8))) - { - off = x + ((y/8) * width); - dest[off] |= (unsigned char)(0x1 << (y % 8)); - } - } - } -} diff --git a/tools/convpic/tuxbox.h b/tools/convpic/tuxbox.h deleted file mode 100644 index 8d19ebd..0000000 --- a/tools/convpic/tuxbox.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * GraphLCD plugin for the Video Disk Recorder - * - * tuxbox.h - tuxbox logo class - * - * (c) 2004 Andreas Brachold <vdr04 AT deltab de> - **/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; * - * if not, write to the Free Software Foundation, Inc., * - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * * - ***************************************************************************/ -#ifndef _TUXBOX_H_ -#define _TUXBOX_H_ - -#include <glcdgraphics/imagefile.h> - -class cTuxBoxFile : public GLCD::cImageFile -{ -private: -// void vert2horz(const unsigned char* source, unsigned char* dest, int width, int height); -// void horz2vert(const unsigned char* source, unsigned char* dest, int width, int height); - void vert2horz(const uint32_t *source, uint32_t *dest, int width, int height); - void horz2vert(const uint32_t *source, uint32_t *dest, int width, int height); -public: - cTuxBoxFile(); - virtual ~cTuxBoxFile(); - virtual bool Load(GLCD::cImage & image, const std::string & fileName); - virtual bool Save(GLCD::cImage & image, const std::string & fileName); -}; - -#endif diff --git a/tools/showpic/showpic.c b/tools/showpic/showpic.c index 1c6e213..7c05ca3 100644 --- a/tools/showpic/showpic.c +++ b/tools/showpic/showpic.c @@ -20,248 +20,276 @@ #include <getopt.h> #include <dlfcn.h> #include <unistd.h> -#include <syslog.h> #include <signal.h> #include <string> #include <glcdgraphics/bitmap.h> -#include <glcdgraphics/glcd.h> #include <glcdgraphics/image.h> + #include <glcddrivers/config.h> #include <glcddrivers/driver.h> #include <glcddrivers/drivers.h> -#include <glcdgraphics/extformats.h> static const char *prgname = "showpic"; -static const char *version = "0.1.2"; +static const char *version = "0.1.3"; static const int kDefaultSleepMs = 100; static const char * kDefaultConfigFile = "/etc/graphlcd.conf"; static volatile bool stopProgramm = false; -static void sighandler(int signal) -{ - switch (signal) - { - case SIGINT: - case SIGQUIT: - case SIGTERM: - stopProgramm = true; - } +static void sighandler(int signal) { + switch (signal) { + case SIGINT: + case SIGQUIT: + case SIGTERM: + stopProgramm = true; + } } -void usage() -{ - fprintf(stdout, "\n"); - fprintf(stdout, "%s v%s\n", prgname, version); - fprintf(stdout, "%s is a tool to show an image on an LCD.\n", prgname); - fprintf(stdout, "The image must be in a special format (*.glcd).\n"); - fprintf(stdout, "You can create such images with the convpic tool.\n\n"); - fprintf(stdout, " Usage: %s [-c CONFIGFILE] [-d DISPLAY] [-s SLEEP] [-uie] file [more files]\n\n", prgname); - fprintf(stdout, " -c --config specifies the location of the config file\n"); - fprintf(stdout, " (default: /etc/graphlcd.conf)\n"); - fprintf(stdout, " -d --display specifies the output display (default is the first one)\n"); - fprintf(stdout, " -u --upsidedown rotates the output by 180 degrees (default: no)\n"); - fprintf(stdout, " -i --invert inverts the output (default: no)\n"); - fprintf(stdout, " -e --endless show all images in endless loop (default: no)\n"); - fprintf(stdout, " -s --sleep set sleeptime between two images [ms] (default: %d ms)\n", kDefaultSleepMs); - fprintf(stdout, " -b --brightness set brightness for display (if supported by the driver) [%%]\n"); - fprintf(stdout, " (default: config file value)\n"); - fprintf(stdout, "\n" ); - fprintf(stdout, " examples: %s -c /etc/graphlcd.conf vdr-logo.glcd\n", prgname); - fprintf(stdout, " %s -c /etc/graphlcd.conf -d LCD_T6963 -u -i vdr-logo.glcd\n", prgname); - fprintf(stdout, "\n" ); +void usage() { + fprintf(stdout, "\n"); + fprintf(stdout, "%s v%s\n", prgname, version); + fprintf(stdout, "%s is a tool to show an image on an LCD.\n", prgname); + fprintf(stdout, "The image format must be supported by libglcdgraphics.\n\n"); + fprintf(stdout, " Usage: %s [-c CONFIGFILE] [-d DISPLAY] [-s SLEEP] [-uie] file [more files]\n\n", prgname); + fprintf(stdout, " -c --config specifies the location of the config file\n"); + fprintf(stdout, " (default: /etc/graphlcd.conf)\n"); + fprintf(stdout, " -d --display specifies the output display (default is the first one)\n"); + fprintf(stdout, " -u --upsidedown rotates the output by 180 degrees (default: no)\n"); + fprintf(stdout, " -i --invert inverts the output (default: no)\n"); + fprintf(stdout, " -e --endless show all images in endless loop (default: no)\n"); + fprintf(stdout, " -s --sleep set sleeptime between two images [ms] (default: %d ms)\n", kDefaultSleepMs); + fprintf(stdout, " -b --brightness set brightness for display (if supported by the driver) [%%]\n"); + fprintf(stdout, " (default: config file value)\n"); + fprintf(stdout, " -S --scale scale algorithm to be used\n"); + fprintf(stdout, " 0: don't scale (default)\n"); + fprintf(stdout, " 1: fit to display if larger but not if smaller (keeping aspect ratio) \n"); + fprintf(stdout, " 2: fit to display if larger or smaller (keeping aspect ratio)\n"); + fprintf(stdout, " 3: fill display (ignoring aspect ratio)\n"); + fprintf(stdout, " -C --center center image (default: no)\n"); + fprintf(stdout, "\n" ); + fprintf(stdout, " examples: %s -c /etc/graphlcd.conf vdr-logo.glcd\n", prgname); + fprintf(stdout, " %s -c /etc/graphlcd.conf -d somedisplay -u -i vdr-animation.glcd\n", prgname); + fprintf(stdout, "\n" ); } -int main(int argc, char *argv[]) -{ - static struct option long_options[] = - { - {"config", required_argument, NULL, 'c'}, - {"display", required_argument, NULL, 'd'}, - {"sleep", required_argument, NULL, 's'}, - {"endless", no_argument, NULL, 'e'}, - {"upsidedown", no_argument, NULL, 'u'}, - {"invert", no_argument, NULL, 'i'}, - {"brightness", required_argument, NULL, 'b'}, - {NULL} - }; - - std::string configName = ""; - std::string displayName = ""; - bool upsideDown = false; - bool invert = false; - int brightness = -1; - bool delay = false; - int sleepMs = 100; - bool endless = false; - unsigned int displayNumber = 0; - - int c, option_index = 0; - while ((c = getopt_long(argc, argv, "c:d:s:euib:", long_options, &option_index)) != -1) - { - switch(c) - { - case 'c': - configName = optarg; - break; - - case 'd': - displayName = optarg; - break; - - case 'u': - upsideDown = true; - break; - - case 'i': - invert = true; - break; - - case 's': - sleepMs = atoi(optarg); - delay = true; - break; - - case 'e': - endless = true; - break; - - case 'b': - brightness = atoi(optarg); - if (brightness < 0) brightness = 0; - if (brightness > 100) brightness = 100; - break; - - default: - usage(); - return 1; - } - } - - if (configName.length() == 0) - { - configName = kDefaultConfigFile; - syslog(LOG_INFO, "Error: No config file specified, using default (%s).\n", configName.c_str()); - } - - if (GLCD::Config.Load(configName) == false) - { - fprintf(stdout, "Error loading config file!\n"); - return 2; - } - if (GLCD::Config.driverConfigs.size() > 0) - { - if (displayName.length() > 0) - { - for (displayNumber = 0; displayNumber < GLCD::Config.driverConfigs.size(); displayNumber++) - { - if (GLCD::Config.driverConfigs[displayNumber].name == displayName) - break; - } - if (displayNumber == GLCD::Config.driverConfigs.size()) - { - fprintf(stdout, "ERROR: Specified display %s not found in config file!\n", displayName.c_str()); - return 3; - } - } - else - { - fprintf(stdout, "WARNING: No display specified, using first one.\n"); - displayNumber = 0; - } - } - else - { - fprintf(stdout, "ERROR: No displays specified in config file!\n"); - return 4; - } - - if (optind == argc) - { - usage(); - fprintf(stderr, "ERROR: You have to specify the image\n"); - return 5; - } - - GLCD::Config.driverConfigs[displayNumber].upsideDown ^= upsideDown; - GLCD::Config.driverConfigs[displayNumber].invert ^= invert; - if (brightness != -1) - GLCD::Config.driverConfigs[displayNumber].brightness = brightness; - GLCD::cDriver * lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[displayNumber].id, &GLCD::Config.driverConfigs[displayNumber]); - if (!lcd) - { - fprintf(stderr, "ERROR: Failed creating display object %s\n", displayName.c_str()); - return 6; - } - if (lcd->Init() != 0) - { - fprintf(stderr, "ERROR: Failed initializing display %s\n", displayName.c_str()); - delete lcd; - return 7; - } - lcd->SetBrightness(GLCD::Config.driverConfigs[displayNumber].brightness); - - signal(SIGINT, sighandler); - signal(SIGQUIT, sighandler); - signal(SIGTERM, sighandler); - signal(SIGHUP, sighandler); - - const GLCD::cBitmap * bitmap; - GLCD::cImage image; - GLCD::cGLCDFile glcd; - GLCD::cExtFormatFile extformat; - - GLCD::cBitmap * buffer = new GLCD::cBitmap(lcd->Width(), lcd->Height()); - - int optFile; - std::string picFile; - - optFile = optind; - while (optFile < argc && !stopProgramm) - { - picFile = argv[optFile++]; - if (glcd.Load(image, picFile) == false) { - if (extformat.Load(image, picFile) == false) { - fprintf(stderr, "ERROR: Failed loading file %s\n", picFile.c_str()); - return 8; - } - } - - if (delay) - image.SetDelay(sleepMs); - - lcd->Refresh(true); - while ((bitmap = image.GetBitmap()) != NULL && !stopProgramm) - { - buffer->DrawBitmap(0, 0, *bitmap); - lcd->SetScreen(buffer->Data(), buffer->Width(), buffer->Height()); - lcd->Refresh(false); - - if (image.Next(0)) // Select next image - { - usleep(image.Delay() * 1000); - } - else if (endless && argc == (optind + 1)) // Endless and one and only image - { - image.First(0); - usleep(image.Delay() * 1000); - } - else - break; - } - - if (optFile < argc || endless) - usleep(sleepMs * 1000); - if (optFile >= argc && endless) - optFile = optind; - } - - delete buffer; - lcd->DeInit(); - delete lcd; - - return 0; +int main(int argc, char *argv[]) { + static struct option long_options[] = + { + {"config", required_argument, NULL, 'c'}, + {"display", required_argument, NULL, 'd'}, + {"sleep", required_argument, NULL, 's'}, + {"endless", no_argument, NULL, 'e'}, + {"upsidedown", no_argument, NULL, 'u'}, + {"invert", no_argument, NULL, 'i'}, + {"brightness", required_argument, NULL, 'b'}, + {"scale", required_argument, NULL, 'S'}, + {"center", no_argument, NULL, 'C'}, + {NULL} + }; + + std::string configName = ""; + std::string displayName = ""; + bool upsideDown = false; + bool invert = false; + int brightness = -1; + bool delay = false; + int sleepMs = 100; + bool endless = false; + unsigned int displayNumber = 0; + int scaleAlgo = 0; + bool center = false; + + int c, option_index = 0; + while ((c = getopt_long(argc, argv, "c:d:s:S:euib:C", long_options, &option_index)) != -1) { + switch(c) { + case 'c': + configName = optarg; + break; + + case 'd': + displayName = optarg; + break; + + case 'u': + upsideDown = true; + break; + + case 'i': + invert = true; + break; + + case 's': + sleepMs = atoi(optarg); + delay = true; + break; + + case 'S': + scaleAlgo = atoi(optarg); + if (scaleAlgo < 0 || scaleAlgo > 3) scaleAlgo = 0; + break; + + case 'e': + endless = true; + break; + + case 'b': + brightness = atoi(optarg); + if (brightness < 0) brightness = 0; + if (brightness > 100) brightness = 100; + break; + + case 'C': + center = true; + break; + + default: + usage(); + return 1; + } + } + + if (configName.length() == 0) { + configName = kDefaultConfigFile; + fprintf(stderr, "Error: No config file specified, using default (%s).\n", configName.c_str()); + } + + if (GLCD::Config.Load(configName) == false) { + fprintf(stderr, "Error loading config file!\n"); + return 2; + } + if (GLCD::Config.driverConfigs.size() > 0) { + if (displayName.length() > 0) { + for (displayNumber = 0; displayNumber < GLCD::Config.driverConfigs.size(); displayNumber++) { + if (GLCD::Config.driverConfigs[displayNumber].name == displayName) + break; + } + if (displayNumber == GLCD::Config.driverConfigs.size()) { + fprintf(stderr, "ERROR: Specified display %s not found in config file!\n", displayName.c_str()); + return 3; + } + } else { + fprintf(stderr, "WARNING: No display specified, using first one.\n"); + displayNumber = 0; + } + } else { + fprintf(stderr, "ERROR: No displays specified in config file!\n"); + return 4; + } + + if (optind == argc) { + usage(); + fprintf(stderr, "ERROR: You have to specify the image\n"); + return 5; + } + + GLCD::Config.driverConfigs[displayNumber].upsideDown ^= upsideDown; + GLCD::Config.driverConfigs[displayNumber].invert ^= invert; + if (brightness != -1) + GLCD::Config.driverConfigs[displayNumber].brightness = brightness; + GLCD::cDriver * lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[displayNumber].id, &GLCD::Config.driverConfigs[displayNumber]); + if (!lcd) { + fprintf(stderr, "ERROR: Failed creating display object %s\n", displayName.c_str()); + return 6; + } + if (lcd->Init() != 0) { + fprintf(stderr, "ERROR: Failed initializing display %s\n", displayName.c_str()); + delete lcd; + return 7; + } + lcd->SetBrightness(GLCD::Config.driverConfigs[displayNumber].brightness); + + signal(SIGINT, sighandler); + signal(SIGQUIT, sighandler); + signal(SIGTERM, sighandler); + signal(SIGHUP, sighandler); + + const GLCD::cBitmap * bitmap; + GLCD::cImage image; + + GLCD::cBitmap * buffer = new GLCD::cBitmap(lcd->Width(), lcd->Height()); + + int optFile; + std::string picFile; + + optFile = optind; + while (optFile < argc && !stopProgramm) { + picFile = argv[optFile++]; + if (GLCD::cImage::LoadImage(image, picFile) == false) { + fprintf(stderr, "ERROR: Failed loading file %s\n", picFile.c_str()); + return 8; + } + + if (scaleAlgo > 0) { + uint16_t scalew = 0; + uint16_t scaleh = 0; + uint16_t imagew = image.Width(); + uint16_t imageh = image.Height(); + + switch (scaleAlgo) { + case 1: + case 2: + if (imagew > lcd->Width() || imageh > lcd->Height()) { + if ((double)imagew / (double)lcd->Width() > (double)imageh / (double)lcd->Height()) + scalew = lcd->Width(); + else + scaleh = lcd->Height(); + } else if (scaleAlgo == 2 && imagew < lcd->Width() && imageh < lcd->Height()) { + if ((double)imagew / (double)lcd->Width() > (double)imageh / (double)lcd->Height()) + scalew = lcd->Width(); + else + scaleh = lcd->Height(); + } + break; + default: /* 3 */ + scalew = lcd->Width(); + scaleh = lcd->Height(); + } + image.Scale(scalew, scaleh, false); + } + + if (delay) + image.SetDelay(sleepMs); + + + uint16_t xstart = 0; + uint16_t ystart = 0; + + if (center) { + if ((unsigned int)(lcd->Width()) > image.Width()) + xstart = (lcd->Width() - image.Width()) >> 1; + if ((unsigned int)(lcd->Height()) > image.Height()) + ystart = (lcd->Height() - image.Height()) >> 1; + } + + lcd->Refresh(true); + while ((bitmap = image.GetBitmap()) != NULL && !stopProgramm) { + buffer->Clear(); + buffer->DrawBitmap(xstart, ystart, *bitmap); + lcd->SetScreen(buffer->Data(), buffer->Width(), buffer->Height()); + lcd->Refresh(false); + + if (image.Next(0)) { // Select next image + usleep(image.Delay() * 1000); + } else if (endless && argc == (optind + 1)) { // Endless and one and only image + image.First(0); + usleep(image.Delay() * 1000); + } else { + break; + } + } + + if (optFile < argc || endless) + usleep(sleepMs * 1000); + if (optFile >= argc && endless) + optFile = optind; + } + + delete buffer; + lcd->DeInit(); + delete lcd; + + return 0; } |