summaryrefslogtreecommitdiff
path: root/glcdgraphics
diff options
context:
space:
mode:
Diffstat (limited to 'glcdgraphics')
-rw-r--r--glcdgraphics/Makefile41
-rw-r--r--glcdgraphics/bitmap.c570
-rw-r--r--glcdgraphics/bitmap.h114
-rw-r--r--glcdgraphics/common.c68
-rw-r--r--glcdgraphics/common.h8
-rw-r--r--glcdgraphics/extformats.c184
-rw-r--r--glcdgraphics/extformats.h37
-rw-r--r--glcdgraphics/font.c262
-rw-r--r--glcdgraphics/font.h26
-rw-r--r--glcdgraphics/glcd.c57
-rw-r--r--glcdgraphics/image.c189
-rw-r--r--glcdgraphics/image.h10
-rw-r--r--glcdgraphics/imagefile.c21
-rw-r--r--glcdgraphics/imagefile.h7
-rw-r--r--glcdgraphics/pbm.c93
15 files changed, 1283 insertions, 404 deletions
diff --git a/glcdgraphics/Makefile b/glcdgraphics/Makefile
index 7f7ff74..2d6e7ff 100644
--- a/glcdgraphics/Makefile
+++ b/glcdgraphics/Makefile
@@ -4,31 +4,39 @@
-include ../Make.config
+# External image lib to use: imagemagick, graphicsmagick, or none
+# (two ifdef/endif are used because older installations may not support 'else ifdef')
+IMAGELIB =
+ifdef HAVE_GRAPHICSMAGICK
+ IMAGELIB = graphicsmagick
+endif
+ifdef HAVE_IMAGEMAGICK
+ IMAGELIB = imagemagick
+endif
+
+
CXXFLAGS += -fPIC
VERMAJOR = 2
-VERMINOR = 0
+VERMINOR = 1
VERMICRO = 0
BASENAME = libglcdgraphics.so
LIBNAME = $(BASENAME).$(VERMAJOR).$(VERMINOR).$(VERMICRO)
-OBJS = bitmap.o common.o font.o glcd.o image.o imagefile.o pbm.o
+OBJS = bitmap.o common.o font.o glcd.o image.o imagefile.o pbm.o extformats.o
-HEADERS = bitmap.h font.h glcd.h image.h imagefile.h pbm.h
+HEADERS = bitmap.h font.h glcd.h image.h imagefile.h pbm.h extformats.h
### Implicit rules:
%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+ $(CXX) $(CXXEXTRA) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
# Dependencies:
-MAKEDEP = g++ -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile
- @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+DEPFILE = $(OBJS:%.o=%.d)
-include $(DEPFILE)
@@ -41,7 +49,22 @@ ifdef HAVE_FREETYPE2
LIBS += -lfreetype
endif
DEFINES += -DHAVE_FREETYPE2
-endif### Targets:
+endif
+
+# two ifdef/endif are used because older installations may not support 'else ifdef'
+ifeq ($(IMAGELIB), imagemagick)
+ DEFINES += -DHAVE_IMAGEMAGICK
+ INCLUDES += $(shell pkg-config --cflags ImageMagick++)
+ LIBS += $(shell pkg-config --libs ImageMagick++)
+endif
+ifeq ($(IMAGELIB), graphicsmagick)
+ DEFINES += -DHAVE_IMAGEMAGICK # yep, really HAVE_IMAGEMAGICK here
+ INCLUDES += $(shell pkg-config --cflags GraphicsMagick++)
+ LIBS += $(shell pkg-config --libs GraphicsMagick++)
+endif
+
+
+### Targets:
all: $(LIBNAME)
diff --git a/glcdgraphics/bitmap.c b/glcdgraphics/bitmap.c
index fe4b497..227e140 100644
--- a/glcdgraphics/bitmap.c
+++ b/glcdgraphics/bitmap.c
@@ -9,14 +9,15 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
-#include <syslog.h>
#include "bitmap.h"
#include "common.h"
@@ -26,21 +27,100 @@
namespace GLCD
{
+const uint32_t cColor::Black = GRAPHLCD_Black;
+const uint32_t cColor::White = GRAPHLCD_White;
+const uint32_t cColor::Red = 0xFFFF0000;
+const uint32_t cColor::Green = 0xFF00FF00;
+const uint32_t cColor::Blue = 0xFF0000FF;
+const uint32_t cColor::Magenta = 0xFFFF00FF;
+const uint32_t cColor::Cyan = 0xFF00FFFF;
+const uint32_t cColor::Yellow = 0xFFFFFF00;
+const uint32_t cColor::Transparent = GRAPHLCD_Transparent;
+const uint32_t cColor::ERRCOL = GRAPHLCD_ERRCOL;
+
+
+cColor cColor::ParseColor(std::string col) {
+ if (col == "black") return cColor(cColor::Black);
+ else if (col == "white") return cColor(cColor::White);
+ else if (col == "red") return cColor(cColor::Red);
+ else if (col == "green") return cColor(cColor::Green);
+ else if (col == "blue") return cColor(cColor::Blue);
+ else if (col == "magenta") return cColor(cColor::Magenta);
+ else if (col == "cyan") return cColor(cColor::Cyan);
+ else if (col == "yellow") return cColor(cColor::Yellow);
+ else if (col == "transparent") return cColor(cColor::Transparent);
+ else if (col.substr(0, 2) == "0x" || col.substr(0, 2) == "0X") {
+ if (col.length() <= 2 || col.length() > 10)
+ return cColor(cColor::ERRCOL);
+
+ char* tempptr;
+ const char* str = col.c_str();
+ uint32_t rv = (uint32_t) strtoul(str, &tempptr, 16);
+
+ if ((str == tempptr) || (*tempptr != '\0'))
+ return cColor(cColor::ERRCOL);
+
+ if (col.length() <= 8) // eg. 0xRRGGBB -> 0xFFRRGGBB
+ rv |= 0xFF000000;
+ return cColor(rv);
+ }
+ return cColor(cColor::ERRCOL);
+}
+
+cColor cColor::Invert(void)
+{
+ return cColor( (uint32_t)(color ^ 0x00FFFFFF) ) ;
+}
+
+uint32_t cColor::AlignAlpha (uint32_t col) {
+ switch (col) {
+ case Transparent:
+ case ERRCOL:
+ return col;
+ default:
+ return (col & 0xFF000000) ? col : (col | 0xFF000000);
+ }
+}
+
const unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
const unsigned char bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
const unsigned char bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
-cBitmap::cBitmap(int width, int height, unsigned char * data)
+cBitmap::cBitmap(int width, int height, uint32_t * data)
: width(width),
height(height),
- bitmap(NULL)
+ bitmap(NULL),
+ ismonochrome(false),
+ processAlpha(true)
{
- // lines are byte aligned
- lineSize = (width + 7) / 8;
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) cBitmap Size %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, width, height);
+#endif
+ if (width > 0 && height > 0) {
+ bitmap = new uint32_t[width * height];
+ if (data && bitmap) {
+ memcpy(bitmap, data, width * height * sizeof(uint32_t));
+ }
+ }
+ backgroundColor = cColor::White;
+}
- bitmap = new unsigned char[lineSize * height];
- if (data)
- memcpy(bitmap, data, lineSize * height);
+
+cBitmap::cBitmap(int width, int height, uint32_t initcol)
+: width(width),
+ height(height),
+ bitmap(NULL),
+ ismonochrome(false),
+ processAlpha(true)
+{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) cBitmap Size %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, width, height);
+#endif
+
+ if (width > 0 && height > 0) {
+ bitmap = new uint32_t[width * height];
+ Clear(initcol);
+ }
}
cBitmap::cBitmap(const cBitmap & b)
@@ -48,63 +128,91 @@ cBitmap::cBitmap(const cBitmap & b)
width = b.width;
height = b.height;
lineSize = b.lineSize;
- bitmap = new unsigned char[lineSize * height];
- if (b.bitmap)
- memcpy(bitmap, b.bitmap, lineSize * height);
+ backgroundColor = b.backgroundColor;
+ ismonochrome = b.ismonochrome;
+ processAlpha = b.processAlpha;
+ bitmap = new uint32_t[b.width * b.height];
+ if (b.bitmap && bitmap) {
+ memcpy(bitmap, b.bitmap, b.width * b.height * sizeof(uint32_t));
+ }
}
cBitmap::~cBitmap()
{
- delete[] bitmap;
+ if (bitmap)
+ delete[] bitmap;
+ bitmap = NULL;
}
-void cBitmap::Clear()
+void cBitmap::Clear(uint32_t color)
{
- memset(bitmap, 0, lineSize * height);
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, width, height, color);
+#endif
+ //uint32_t col = initcol; //(initcol == cColor::Transparent) ? backgroundColor : initcol;
+
+ // force clearing (== background) colour to contain alpha level = 0xFF
+ if ( color != cColor::Transparent )
+ color = (color & 0x00FFFFFF) | 0xFF000000;
+
+ for (int i = 0; i < width * height; i++)
+ bitmap[i] = color;
+ backgroundColor = color;
}
void cBitmap::Invert()
{
int i;
- for (i = 0; i < lineSize * height; i++)
+ for (i = 0; i < width * height; i++)
{
- bitmap[i] ^= 0xFF;
+ bitmap[i] ^= 0xFFFFFF;
}
}
-void cBitmap::DrawPixel(int x, int y, eColor color)
+void cBitmap::DrawPixel(int x, int y, uint32_t color)
{
if (x < 0 || x > width - 1)
return;
if (y < 0 || y > height - 1)
return;
- unsigned char c = 0x80 >> (x % 8);
- if (color == clrBlack)
- bitmap[lineSize * y + x / 8] |= c;
- else
- bitmap[lineSize * y + x / 8] &= ~c;
+ if (color != GLCD::cColor::Transparent) {
+ uint32_t col = cColor::AlignAlpha(color);
+ if (processAlpha) {
+ uint32_t bg = bitmap[x + (width * y)];
+ uint32_t afg = (col & 0xFF000000) >> 24;
+ uint32_t rfg = (col & 0x00FF0000) >> 16;
+ uint32_t gfg = (col & 0x0000FF00) >> 8;
+ uint32_t bfg = (col & 0x000000FF);
+
+ uint32_t rbg = (bg & 0x00FF0000) >> 16;
+ uint32_t gbg = (bg & 0x0000FF00) >> 8;
+ uint32_t bbg = (bg & 0x000000FF);
+
+ // calculate colour channels of new colour depending on alpha channel and background colour
+ rfg = (rfg * afg + rbg * (255 - afg)) / 255;
+ gfg = (gfg * afg + gbg * (255 - afg)) / 255;
+ bfg = (bfg * afg + bbg * (255 - afg)) / 255;
+
+ // as we draw from bottom to top, the new colour will always have alpha level == 0xFF
+ // (it will serve as background colour for future objects that will be drawn onto the current object)
+ col = 0xFF000000 | (rfg << 16) | (gfg << 8) | bfg;
+ }
+ bitmap[x + (width * y)] = col;
+ }
+ //else
+ // bitmap[x + (width * y)] = cColor::AlignAlpha(backgroundColor);
}
-void cBitmap::Draw8Pixels(int x, int y, unsigned char pixels, eColor color)
-{
- if (x < 0 || x > width - 1)
- return;
- if (y < 0 || y > height - 1)
- return;
- if (color == clrBlack)
- bitmap[lineSize * y + x / 8] |= pixels;
- else
- bitmap[lineSize * y + x / 8] &= ~pixels;
-}
-
-void cBitmap::DrawLine(int x1, int y1, int x2, int y2, eColor color)
+void cBitmap::DrawLine(int x1, int y1, int x2, int y2, uint32_t color)
{
int d, sx, sy, dx, dy;
unsigned int ax, ay;
+ color = cColor::AlignAlpha(color);
+
dx = x2 - x1;
ax = abs(dx) << 1;
if (dx < 0)
@@ -152,43 +260,43 @@ void cBitmap::DrawLine(int x1, int y1, int x2, int y2, eColor color)
}
}
-void cBitmap::DrawHLine(int x1, int y, int x2, eColor color)
+void cBitmap::DrawHLine(int x1, int y, int x2, uint32_t color)
{
- sort(x1,x2);
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d -> %03d, %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, x2, y, color);
+#endif
+ color = cColor::AlignAlpha(color);
- if (x1 / 8 == x2 / 8)
- {
- // start and end in the same byte
- Draw8Pixels(x1, y, bitmaskr[x1 % 8] & bitmaskl[x2 % 8], color);
- }
- else
- {
- // start and end in different bytes
- Draw8Pixels(x1, y, bitmaskr[x1 % 8], color);
- x1 = ((x1 + 8) / 8) * 8;
- while (x1 < (x2 / 8) * 8)
- {
- Draw8Pixels(x1, y, 0xff, color);
- x1 += 8;
- }
- Draw8Pixels(x2, y, bitmaskl[x2 % 8], color);
- }
+ sort(x1,x2);
+ while (x1 <= x2) {
+ DrawPixel(x1, y, color);
+ x1++;
+ };
}
-void cBitmap::DrawVLine(int x, int y1, int y2, eColor color)
+void cBitmap::DrawVLine(int x, int y1, int y2, uint32_t color)
{
- int y;
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d, %03d -> %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x, y1, y2, color);
+#endif
+ color = cColor::AlignAlpha(color);
sort(y1,y2);
-
- for (y = y1; y <= y2; y++)
- DrawPixel(x, y, color);
+ while (y1 <= y2) {
+ DrawPixel(x, y1, color);
+ y1++;
+ }
}
-void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled)
+void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color);
+#endif
int y;
+ color = cColor::AlignAlpha(color);
+
sort(x1,x2);
sort(y1,y2);
@@ -208,8 +316,13 @@ void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool f
}
}
-void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int type)
+void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int type)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color);
+#endif
+ color = cColor::AlignAlpha(color);
+
sort(x1,x2);
sort(y1,y2);
@@ -231,10 +344,14 @@ void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, b
if (type == 4)
{
// round the ugly fat box...
- DrawPixel(x1 + 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
- DrawPixel(x1 + 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
- DrawPixel(x2 - 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
- DrawPixel(x2 - 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
+// DrawPixel(x1 + 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
+// DrawPixel(x1 + 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
+// DrawPixel(x2 - 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
+// DrawPixel(x2 - 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
+ DrawPixel(x1 + 1, y1 + 1, backgroundColor);
+ DrawPixel(x1 + 1, y2 - 1, backgroundColor);
+ DrawPixel(x2 - 1, y1 + 1, backgroundColor);
+ DrawPixel(x2 - 1, y2 - 1, backgroundColor);
}
}
else
@@ -257,8 +374,13 @@ void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, b
}
}
-void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants)
+void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int quadrants)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d -> %03d * %03d (color %08x)\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2, color);
+#endif
+ color = cColor::AlignAlpha(color);
+
// Algorithm based on http://homepage.smc.edu/kennedy_john/BELIPSE.PDF
int rx = x2 - x1;
int ry = y2 - y1;
@@ -398,8 +520,13 @@ void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool fil
}
}
-void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type)
+void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, uint32_t color, int type)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d -> %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2);
+#endif
+ color = cColor::AlignAlpha(color);
+
bool upper = type & 0x01;
bool falling = type & 0x02;
bool vertical = type & 0x04;
@@ -411,7 +538,7 @@ void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type)
if (falling)
c = -c;
int x = int((x2 - x1 + 1) * c / 2);
- if (upper && !falling || !upper && falling)
+ if ((upper && !falling) || (!upper && falling))
DrawRectangle(x1, y, (x1 + x2) / 2 + x, y, color, true);
else
DrawRectangle((x1 + x2) / 2 + x, y, x2, y, color, true);
@@ -433,82 +560,59 @@ void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type)
}
}
-void cBitmap::DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color)
+void cBitmap::DrawBitmap(int x, int y, const cBitmap & bitmap, uint32_t color, uint32_t bgcolor, int opacity)
{
- unsigned char cl = 0;
- int xt, yt;
- const unsigned char * data = bitmap.Data();
- unsigned short temp;
- int h, w;
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) '%03d' x '%03d' \n", __FILE__, __FUNCTION__, __LINE__, x, y);
+#endif
+ color = cColor::AlignAlpha(color);
+ bgcolor = cColor::AlignAlpha(bgcolor);
- w = bitmap.Width();
- h = bitmap.Height();
+ uint32_t cl = 0;
+ const uint32_t * data = bitmap.Data();
+ bool ismono = bitmap.IsMonochrome();
+
+ int xt, yt;
+ uint32_t alpha;
if (data)
{
- if (!(x % 8))
+ for (yt = 0; yt < bitmap.Height(); yt++)
{
- // Bitmap is byte alligned (0,8,16,...)
- for (yt = 0; yt < h; yt++)
- {
- for (xt = 0; xt < (w / 8); xt++)
- {
- cl = *data;
- Draw8Pixels(x + (xt * 8), y + yt, cl, color);
- data++;
- }
- if (w % 8)
- {
- cl = *data;
- Draw8Pixels(x + ((w / 8) * 8), y + yt, cl & bitmaskl[w % 8 - 1], color);
- data++;
- }
- }
- }
- else
- {
- // Bitmap is not byte alligned
- for (yt = 0; yt < h; yt++)
- {
- temp = 0;
- for (xt = 0; xt < (w + (x % 8)) / 8; xt++)
- {
- cl = *(data + yt * ((w + 7) / 8) + xt);
- temp = temp | ((unsigned short) cl << (8 - (x % 8)));
- cl = (temp & 0xff00) >> 8;
- if (!xt)
- {
- // first byte
- Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl & bitmaskr[x % 8], color);
- }
- else
- {
- // not the first byte
- Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl, color);
- }
- temp <<= 8;
- }
- if ((w + (x % 8) + 7) / 8 != (w + (x % 8)) / 8)
- {
- // print the rest
- cl = *(data + (yt + 1) * ((w + 7) / 8) - 1);
- temp = temp | ((unsigned short) cl << (8 - (x % 8)));
- cl = (temp & 0xff00) >> 8;
- Draw8Pixels(x - (x % 8) + (((w + (x % 8)) / 8) * 8), y + yt, cl & bitmaskl[(w + x) % 8 - 1], color);
- }
- }
- }
+ for (xt = 0; xt < bitmap.Width(); xt++)
+ {
+ cl = data[(yt * bitmap.Width())+xt];
+ if (cl != cColor::Transparent) {
+ if (ismono) {
+ cl = (cl == cColor::Black) ? color : bgcolor;
+ }
+ if (opacity != 255) {
+ alpha = (cl & 0xFF000000) >> 24;
+ alpha = (alpha * opacity) / 255;
+ cl = (cl & 0x00FFFFFF) | (alpha << 24);
+ }
+ if (cl & 0xFF000000) // only draw if alpha > 0
+ DrawPixel(xt+x, yt+y, cl);
+ }
+ }
+ }
}
}
int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cFont * font,
- eColor color, bool proportional, int skipPixels)
+ uint32_t color, uint32_t bgcolor, bool proportional, int skipPixels)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) text '%s', color '%08x'/'%08x'\n", __FILE__, __FUNCTION__, __LINE__, text.c_str(), color, bgcolor);
+#endif
int xt;
int yt;
unsigned int i;
- int c;
- int start;
+ uint32_t c;
+ unsigned int start;
+
+ color = cColor::AlignAlpha(color);
+ bgcolor = cColor::AlignAlpha(bgcolor);
clip(x, 0, width - 1);
clip(y, 0, height - 1);
@@ -537,17 +641,22 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF
if (skipPixels >= font->Width(text))
start = text.length();
else
- while (skipPixels > font->Width(text[start]))
+ {
+ while (skipPixels > font->SpaceBetween() + font->Width(text.substr(start), 1 /*text[start]*/))
{
- skipPixels -= font->Width(text[start]);
+ encodedCharAdjustCounter(font->IsUTF8(), text, c, start);
+ skipPixels -= font->Width(c/*text[start]*/);
skipPixels -= font->SpaceBetween();
start++;
}
+ }
}
}
- for (i = start; i < (int) text.length(); i++)
+
+ i = start;
+ while ( i < (unsigned int)text.length() )
{
- cFont::Utf8CodeAdjustCounter(text, c, i);
+ encodedCharAdjustCounter(font->IsUTF8(), text, c, i);
if (xt > xmax)
{
@@ -559,13 +668,13 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF
{
if (skipPixels > 0)
{
- DrawCharacter(xt, yt, xmax, c, font, color, skipPixels);
+ DrawCharacter(xt, yt, xmax, c, font, color, bgcolor, skipPixels);
xt += font->TotalWidth() - skipPixels;
skipPixels = 0;
}
else
{
- DrawCharacter(xt, yt, xmax, c, font, color);
+ DrawCharacter(xt, yt, xmax, c, font, color, bgcolor);
xt += font->TotalWidth();
}
}
@@ -573,12 +682,12 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF
{
if (skipPixels > 0)
{
- xt += DrawCharacter(xt, yt, xmax, c, font, color, skipPixels);
+ xt += DrawCharacter(xt, yt, xmax, c, font, color, bgcolor, skipPixels);
skipPixels = 0;
}
else
{
- xt += DrawCharacter(xt, yt, xmax, c, font, color);
+ xt += DrawCharacter(xt, yt, xmax, c, font, color, bgcolor);
}
if (xt <= xmax)
{
@@ -586,15 +695,26 @@ int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cF
}
}
}
+ i++;
}
}
return xt;
}
-int cBitmap::DrawCharacter(int x, int y, int xmax, int c, const cFont * font,
- eColor color, int skipPixels)
+int cBitmap::DrawCharacter(int x, int y, int xmax, uint32_t c, const cFont * font,
+ uint32_t color, uint32_t bgcolor, int skipPixels)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d char '%c' color '%08x' bgcolor '%08x'\n", __FILE__, __FUNCTION__, __LINE__, x, y, c, color, bgcolor);
+#endif
const cBitmap * charBitmap;
+ cBitmap * drawBitmap;
+
+ //color = cColor::AlignAlpha(color);
+ //bgcolor = cColor::AlignAlpha(bgcolor);
+
+ uint32_t dot = 0;
+ int xt, yt;
clip(x, 0, width - 1);
clip(y, 0, height - 1);
@@ -602,32 +722,54 @@ int cBitmap::DrawCharacter(int x, int y, int xmax, int c, const cFont * font,
charBitmap = font->GetCharacter(c);
if (charBitmap)
{
- cBitmap * drawBitmap = charBitmap->SubBitmap(skipPixels, 0, xmax - x + skipPixels, charBitmap->Height() - 1);
- if (drawBitmap)
- DrawBitmap(x, y, *drawBitmap, color);
- delete drawBitmap;
- return charBitmap->Width() - skipPixels;
+ int drawWidth = charBitmap->Width() - skipPixels;
+ if ( x + drawWidth-1 > xmax)
+ drawWidth = xmax - x + 1;
+
+ drawBitmap = new cBitmap(drawWidth /*charBitmap->Width()-skipPixels*/,charBitmap->Height());
+ if (drawBitmap) {
+ drawBitmap->SetProcessAlpha(false);
+ drawBitmap->Clear(bgcolor);
+
+ for (xt = 0; xt < drawWidth; xt++) {
+ for (yt = 0; yt < charBitmap->Height() ; yt++) {
+ dot = charBitmap->GetPixel(xt+skipPixels,yt);
+ if ((dot | 0xFF000000) == cColor::Black) { // todo: does not work with antialising?
+ drawBitmap->DrawPixel(xt, yt, color);
+ } else {
+ drawBitmap->DrawPixel(xt, yt, bgcolor);
+ }
+ }
+ }
+ DrawBitmap(x, y, *drawBitmap);
+ delete drawBitmap;
+ }
+ return drawWidth; //charBitmap->Width() - skipPixels;
}
return 0;
}
-unsigned char cBitmap::GetPixel(int x, int y) const
+uint32_t cBitmap::GetPixel(int x, int y) const
{
- unsigned char value;
+ if (x < 0 || x > width - 1)
+ return cColor::Transparent;
+ if (y < 0 || y > height - 1)
+ return cColor::Transparent;
- value = bitmap[y * lineSize + x / 8];
- value = (value >> (7 - (x % 8))) & 1;
+ uint32_t value;
+ value = bitmap[y * width + x];
return value;
}
cBitmap * cBitmap::SubBitmap(int x1, int y1, int x2, int y2) const
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) %03d * %03d / %03d * %03d\n", __FILE__, __FUNCTION__, __LINE__, x1, y1, x2, y2);
+#endif
int w, h;
int xt, yt;
cBitmap * bmp;
- unsigned char cl;
- unsigned char * data;
- unsigned short temp;
+ uint32_t cl;
sort(x1,x2);
sort(y1,y2);
@@ -644,62 +786,80 @@ cBitmap * cBitmap::SubBitmap(int x1, int y1, int x2, int y2) const
if (!bmp || !bmp->Data())
return NULL;
bmp->Clear();
- if (x1 % 8 == 0)
+ bmp->SetMonochrome(this->IsMonochrome());
+
+ for (yt = 0; yt < h; yt++)
{
- // Bitmap is byte alligned (0,8,16,...)
- for (yt = 0; yt < h; yt++)
- {
- data = &bitmap[(y1 + yt) * lineSize + x1 / 8];
- for (xt = 0; xt < (w / 8) * 8; xt += 8)
- {
- cl = *data;
- bmp->Draw8Pixels(xt, yt, cl, clrBlack);
- data++;
- }
- if (w % 8 != 0)
- {
- cl = *data;
- bmp->Draw8Pixels(xt, yt, cl & bitmaskl[w % 8 - 1], clrBlack);
+ for (xt = 0; xt < w; xt++)
+ {
+ cl = this->GetPixel(xt+x1, yt+y1);
+ bmp->DrawPixel(xt,yt, cl);
+ }
+ }
+ return bmp;
+}
+
+
+// convert a new 32 bpp bitmap to an old style 1bpp bitmap (bit order: from least to most sig. bit: byte: [ 0, 1, 2, 3, 4, 5, 6, 7 ])
+// if IsMonochrome(): ignore threshold
+const unsigned char* cBitmap::ConvertTo1BPP(const cBitmap & bitmap, int threshold)
+{
+ if (bitmap.Width() <= 0 || bitmap.Height() <= 0)
+ return NULL;
+
+ int cols = (bitmap.Width() + 7 ) / 8;
+ unsigned char* monobmp = new unsigned char[ cols * bitmap.Height() ];
+ if (!monobmp)
+ return NULL;
+
+ memset(monobmp, 0, cols * bitmap.Height());
+
+ uint32_t col;
+ unsigned char greyval = 0;
+ bool ismono = bitmap.IsMonochrome();
+
+ for (int y = 0; y < bitmap.Height(); y++) {
+ for (int x = 0; x < bitmap.Width(); x++) {
+ col = bitmap.GetPixel(x, y);
+ if (! ismono) {
+ // col -> grey level
+ greyval = (((0x00FF0000 & col) >> 16) * 77 + ((0x0000FF00 * col) >> 8) * 150 + (0x000000FF & col) * 28) / 255;
+ col = (greyval >= threshold) ? cColor::White : cColor::Black;
}
+
+ if ( col == cColor::Black)
+ monobmp[ y * cols + (x >> 3) ] |= ( 1 << ( 7 - (x % 8) ) );
}
}
- else
- {
- // Bitmap is not byte alligned
- for (yt = 0; yt < h; yt++)
- {
- temp = 0;
- data = &bitmap[(y1 + yt) * lineSize + x1 / 8];
- for (xt = 0; xt <= ((w / 8)) * 8; xt += 8)
- {
- cl = *data;
- temp = temp | ((unsigned short) cl << (x1 % 8));
- cl = (temp & 0xff00) >> 8;
- if (xt > 0)
- {
- bmp->Draw8Pixels(xt - 8, yt, cl, clrBlack);
- }
- temp <<= 8;
- data++;
- }
- if (w % 8 != 0)
- {
- // print the rest
- if (8 - (x1 % 8) < w % 8)
- {
- cl = *data;
- temp = temp | ((unsigned short) cl << (x1 % 8));
- }
- cl = (temp & 0xff00) >> 8;
- bmp->Draw8Pixels(xt - 8, yt, cl & bitmaskl[(w % 8) - 1], clrBlack);
- }
+ return monobmp;
+}
+
+
+// convert an old style 1 bpp bitmap to new 32 bpp bitmap (bit order: from least to most sig. bit: byte: [ 0, 1, 2, 3, 4, 5, 6, 7 ])
+const cBitmap* cBitmap::ConvertFrom1BPP(const unsigned char* monobmp, int w, int h, uint32_t fg, uint32_t bg)
+{
+ if (w <= 0 || h <= 0 || !monobmp)
+ return NULL;
+
+ cBitmap* bmp = new cBitmap(w, h, bg);
+ if (bmp == NULL)
+ return NULL;
+
+ int cols = (w + 7 ) / 8;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ bmp->DrawPixel(x, y, ( monobmp[ y * cols + (x >> 3) ] & ( 1 << (7 - (x % 8)) ) ) ? fg : bg );
}
}
return bmp;
}
+#if 0
bool cBitmap::LoadPBM(const std::string & fileName)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d)\n", __FILE__, __FUNCTION__, __LINE__);
+#endif
FILE * pbmFile;
char str[32];
int i;
@@ -775,13 +935,12 @@ bool cBitmap::LoadPBM(const std::string & fileName)
str[i] = 0;
h = atoi(str);
- delete[] bitmap;
+ if (bitmap)
+ delete[] bitmap;
width = w;
height = h;
- // lines are byte aligned
- lineSize = (width + 7) / 8;
- bitmap = new unsigned char[lineSize * height];
- fread(bitmap, lineSize * height, 1, pbmFile);
+ bitmap = new uint32_t [width * height];
+ fread(bitmap, width * height, 1, pbmFile);
fclose(pbmFile);
return true;
@@ -789,6 +948,9 @@ bool cBitmap::LoadPBM(const std::string & fileName)
void cBitmap::SavePBM(const std::string & fileName)
{
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d)\n", __FILE__, __FUNCTION__, __LINE__);
+#endif
int i;
char str[32];
FILE * fp;
@@ -805,6 +967,6 @@ void cBitmap::SavePBM(const std::string & fileName)
fclose(fp);
}
}
+#endif
} // end of namespace
-
diff --git a/glcdgraphics/bitmap.h b/glcdgraphics/bitmap.h
index 9e5c7e6..2c4a2af 100644
--- a/glcdgraphics/bitmap.h
+++ b/glcdgraphics/bitmap.h
@@ -9,22 +9,79 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#ifndef _GLCDGRAPHICS_BITMAP_H_
#define _GLCDGRAPHICS_BITMAP_H_
#include <string>
+#include <inttypes.h>
+
+// graphlcd-base uses ARGB bitmaps instead of 1bit ones
+// this flag will be checked in current versions of vdr-graphlcd-plugin
+#define GRAPHLCD_CBITMAP_ARGB
+
+// colour definitions for glcddrivers so that libglcddrivers.so isn't link-dependent on libglcdgraphics.so
+#define GRAPHLCD_Black 0xFF000000
+#define GRAPHLCD_White 0xFFFFFFFF
+#define GRAPHLCD_Transparent 0x00FFFFFF
+#define GRAPHLCD_ERRCOL 0x00000000
+
namespace GLCD
{
+#if 0
enum eColor
{
- clrBlack,
- clrWhite
+ clrTransparent,
+ clrGray50,
+ clrBlack,
+ clrRed,
+ clrGreen,
+ clrYellow,
+ clrMagenta,
+ clrBlue,
+ clrCyan,
+ clrWhite
};
+#endif
+
+
+class cColor
+{
+protected:
+ uint32_t color;
+
+public:
+ cColor(uint32_t col) { color = col; }
+ cColor(const cColor & col) { color = col.color; }
+
+ static const uint32_t Black;
+ static const uint32_t White;
+ static const uint32_t Red;
+ static const uint32_t Green;
+ static const uint32_t Blue;
+ static const uint32_t Magenta;
+ static const uint32_t Cyan;
+ static const uint32_t Yellow;
+ static const uint32_t Transparent;
+ static const uint32_t ERRCOL;
+
+ uint32_t GetColor (void) { return color; }
+ void SetColor (uint32_t col) { color = col; }
+
+ cColor Invert (void);
+
+ operator uint32_t(void) { return GetColor(); }
+
+ static cColor ParseColor (std::string col);
+ static uint32_t AlignAlpha (uint32_t col);
+};
+
class cFont;
@@ -34,40 +91,55 @@ protected:
int width;
int height;
int lineSize;
- unsigned char * bitmap;
+ uint32_t * bitmap;
+ bool ismonochrome;
+ bool processAlpha;
+
+ uint32_t backgroundColor;
public:
- cBitmap(int width, int height, unsigned char * data = NULL);
+ cBitmap(int width, int height, uint32_t * data = NULL);
+ cBitmap(int width, int height, uint32_t initcol);
cBitmap(const cBitmap & b);
~cBitmap();
int Width() const { return width; }
int Height() const { return height; }
int LineSize() const { return lineSize; }
- const unsigned char * Data() const { return bitmap; }
+ const uint32_t * Data() const { return bitmap; }
- void Clear();
+ void Clear(uint32_t color = cColor::Transparent);
void Invert();
- void DrawPixel(int x, int y, eColor color);
- void Draw8Pixels(int x, int y, unsigned char pixels, eColor color);
- void DrawLine(int x1, int y1, int x2, int y2, eColor color);
- void DrawHLine(int x1, int y, int x2, eColor color);
- void DrawVLine(int x, int y1, int y2, eColor color);
- void DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled);
- void DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int size);
- void DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants);
- void DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type);
- void DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color);
+ void DrawPixel(int x, int y, uint32_t color);
+ void DrawLine(int x1, int y1, int x2, int y2, uint32_t color);
+ void DrawHLine(int x1, int y, int x2, uint32_t color);
+ void DrawVLine(int x, int y1, int y2, uint32_t color);
+ void DrawRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled);
+ void DrawRoundRectangle(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int size);
+ void DrawEllipse(int x1, int y1, int x2, int y2, uint32_t color, bool filled, int quadrants);
+ void DrawSlope(int x1, int y1, int x2, int y2, uint32_t color, int type);
+ void DrawBitmap(int x, int y, const cBitmap & bitmap, uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black, int opacity = 255);
int DrawText(int x, int y, int xmax, const std::string & text, const cFont * font,
- eColor color = clrBlack, bool proportional = true, int skipPixels = 0);
- int DrawCharacter(int x, int y, int xmax, int c, const cFont * font,
- eColor color = clrBlack, int skipPixels = 0);
+ uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black, bool proportional = true, int skipPixels = 0);
+ int DrawCharacter(int x, int y, int xmax, uint32_t c, const cFont * font,
+ uint32_t color = cColor::White, uint32_t bgcolor = cColor::Black, int skipPixels = 0);
cBitmap * SubBitmap(int x1, int y1, int x2, int y2) const;
- unsigned char GetPixel(int x, int y) const;
+ uint32_t GetPixel(int x, int y) const;
+
+ void SetMonochrome(bool ismono) { ismonochrome = ismono; }
+ bool IsMonochrome(void) const { return ismonochrome; }
+ void SetProcessAlpha(bool procAlpha) { processAlpha = procAlpha; }
+ bool IsProcessAlpha(void) const { return processAlpha; }
+
+ static const unsigned char* ConvertTo1BPP(const cBitmap & bitmap, int threshold = 127);
+ static const cBitmap* ConvertFrom1BPP(const unsigned char* monobmp, int w, int h, uint32_t fg = cColor::White, uint32_t bg = cColor::Black);
+
+#if 0
bool LoadPBM(const std::string & fileName);
void SavePBM(const std::string & fileName);
+#endif
};
} // end of namespace
diff --git a/glcdgraphics/common.c b/glcdgraphics/common.c
index 8942424..0fd78b8 100644
--- a/glcdgraphics/common.c
+++ b/glcdgraphics/common.c
@@ -6,10 +6,12 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2012 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#include <ctype.h>
+#include <syslog.h>
#include "common.h"
@@ -48,7 +50,7 @@ std::string trim(const std::string & s)
start++;
}
end = s.length() - 1;
- while (end >= 0)
+ while (end > start)
{
if (!isspace(s[end]))
break;
@@ -57,4 +59,66 @@ std::string trim(const std::string & s)
return s.substr(start, end - start + 1);
}
+
+bool encodedCharAdjustCounter(const bool isutf8, const std::string & str, uint32_t & c, unsigned int & i, const uint32_t errChar)
+{
+ bool rv = false;
+
+ if (i >= str.length())
+ return rv;
+
+ if ( isutf8 ) {
+ uint8_t c0,c1,c2,c3;
+ c = str[i];
+ c0 = str[i];
+ c1 = (i+1 < str.length()) ? str[i+1] : 0;
+ c2 = (i+2 < str.length()) ? str[i+2] : 0;
+ c3 = (i+3 < str.length()) ? str[i+3] : 0;
+
+ if ( (c0 & 0x80) == 0x00) {
+ // one byte: 0xxxxxxx
+ c = c0;
+ rv = true;
+ } else if ( (c0 & 0xE0) == 0xC0 ) {
+ // two byte utf8: 110yyyyy 10xxxxxx -> 00000yyy yyxxxxxx
+ if ( (c1 & 0xC0) == 0x80 ) {
+ c = ( (c0 & 0x1F) << 6 ) | ( (c1 & 0x3F) );
+ rv = true;
+ } else {
+ //syslog(LOG_INFO, "GraphLCD: illegal 2-byte UTF-8 sequence found: %02x %02x, pos=%d, str: %s\n", c0,c1,i,str.c_str());
+ c = errChar;
+ }
+ i += 1;
+ } else if ( (c0 & 0xF0) == 0xE0 ) {
+ // three byte utf8: 1110zzzz 10yyyyyy 10xxxxxx -> zzzzyyyy yyxxxxxx
+ if ( ((c1 & 0xC0) == 0x80) && ((c2 & 0xC0) == 0x80) ) {
+ c = ( (c0 & 0x0F) << 12 ) | ( (c1 & 0x3F) << 6 ) | ( c2 & 0x3F );
+ rv = true;
+ } else {
+ //syslog(LOG_INFO, "GraphLCD: illegal 3-byte UTF-8 sequence found: %02x %02x %02x, pos=%d, str: %s\n", c0,c1,c2,i,str.c_str());
+ c = errChar;
+ }
+ i += 2;
+ } else if ( (c0 & 0xF8) == 0xF0 ) {
+ // four byte utf8: 11110www 10zzzzzz 10yyyyyy 10xxxxxx -> 000wwwzz zzzzyyyy yyxxxxxx
+ if ( ((c1 & 0xC0) == 0x80) && ((c2 & 0xC0) == 0x80) && ((c3 & 0xC0) == 0x80) ) {
+ c = ( (c0 & 0x07) << 18 ) | ( (c1 & 0x3F) << 12 ) | ( (c2 & 0x3F) << 6 ) | (c3 & 0x3F);
+ rv = true;
+ } else {
+ //syslog(LOG_INFO, "GraphLCD: illegal 4-byte UTF-8 sequence found: %02x %02x %02x %02x, pos=%d, str: %s\n", c0,c1,c2,c3,i,str.c_str());
+ c = errChar;
+ }
+ i += 3;
+ } else {
+ // 1xxxxxxx is invalid!
+ //syslog(LOG_INFO, "GraphLCD: illegal 1-byte UTF-8 char found: %02x, pos=%d, str: %s\n", c0,i,str.c_str());
+ c = errChar;
+ }
+ } else {
+ c = str[i];
+ rv = true;
+ }
+ return rv;
+}
+
} // end of namespace
diff --git a/glcdgraphics/common.h b/glcdgraphics/common.h
index 2865602..f0376bf 100644
--- a/glcdgraphics/common.h
+++ b/glcdgraphics/common.h
@@ -13,6 +13,13 @@
#define _GLCDGRAPHICS_COMMON_H_
#include <string>
+#include <stdint.h>
+
+// character to return when erraneous utf-8 sequence (for now: space)
+//#define UTF8_ERRCHAR 0x0020
+// for debugging issues return '_' instead:
+#define UTF8_ERRCHAR 0x005F
+
namespace GLCD
{
@@ -20,6 +27,7 @@ namespace GLCD
void clip(int & value, int min, int max);
void sort(int & value1, int & value2);
std::string trim(const std::string & s);
+bool encodedCharAdjustCounter(const bool isutf8, const std::string & str, uint32_t & c, unsigned int & i, const uint32_t errChar = UTF8_ERRCHAR);
} // end of namespace
diff --git a/glcdgraphics/extformats.c b/glcdgraphics/extformats.c
new file mode 100644
index 0000000..5734fce
--- /dev/null
+++ b/glcdgraphics/extformats.c
@@ -0,0 +1,184 @@
+/*
+ * GraphLCD graphics library
+ *
+ * extformats.c - loading and saving of external formats (via ImageMagick)
+ *
+ * based on bitmap.[ch] from text2skin: http://projects.vdr-developer.org/projects/show/plg-text2skin
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2011-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <syslog.h>
+
+#include <cstring>
+
+#include "bitmap.h"
+#include "extformats.h"
+#include "image.h"
+
+#ifdef HAVE_IMAGEMAGICK
+#include <Magick++.h>
+//#elif defined(HAVE_IMLIB2)
+//#include "quantize.h"
+//#include <Imlib2.h>
+#endif
+
+
+namespace GLCD
+{
+
+using namespace std;
+
+
+cExtFormatFile::cExtFormatFile()
+{
+#ifdef HAVE_IMAGEMAGICK
+ Magick::InitializeMagick(NULL);
+#endif
+}
+
+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<Magick::Image> extimages;
+ try {
+ uint16_t width = 0;
+ uint16_t height = 0;
+ //uint16_t count;
+ uint32_t delay;
+
+ std::vector<Magick::Image>::iterator it;
+ readImages(&extimages, fileName);
+ if (extimages.size() == 0) {
+ syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s' (cExtFormatFile::LoadScaled)", fileName.c_str());
+ return false;
+ }
+
+ delay = (uint32_t)(extimages[0].animationDelay() * 10);
+
+ image.Clear();
+ image.SetDelay(delay);
+
+ bool firstImage = true;
+
+ for (it = extimages.begin(); it != extimages.end(); ++it) {
+ bool ignoreImage = false;
+
+ //(*it).quantizeColorSpace( Magick::RGBColorspace );
+ //(*it).quantizeColors( 256*256*256 /*colors*/ );
+ //(*it).quantize();
+
+ 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).sample(Magick::Geometry(scalew, scaleh));
+ width = scalew;
+ height = scaleh;
+ } else {
+ // not scaled => reset to 0
+ scalew = 0;
+ scaleh = 0;
+ }
+
+ image.SetWidth(width);
+ image.SetHeight(height);
+ } else {
+ if (scalew && scaleh) {
+ (*it).sample(Magick::Geometry(scalew, scaleh));
+ } else
+ if ( (width != (uint16_t)((*it).columns())) || (height != (uint16_t)((*it).rows())) ) {
+ ignoreImage = true;
+ }
+ }
+
+ if (! ignoreImage) {
+ /*
+ if ((*it).depth() > 8) {
+ esyslog("ERROR: text2skin: More than 8bpp images are not supported");
+ return false;
+ }
+ */
+ uint32_t * bmpdata = new uint32_t[height * width];
+ //Dprintf("this image has %d colors\n", (*it).totalColors());
+
+ bool isMatte = (*it).matte();
+ //bool isMonochrome = ((*it).totalColors() <= 2) ? true : false;
+ const Magick::PixelPacket *pix = (*it).getConstPixels(0, 0, (int)width, (int)height);
+
+ for (int iy = 0; iy < (int)height; ++iy) {
+ for (int ix = 0; ix < (int)width; ++ix) {
+ if ( isMatte && Magick::Color::scaleQuantumToDouble(pix->opacity) * 255 == 255 ) {
+ bmpdata[iy*width+ix] = cColor::Transparent;
+ } else {
+ bmpdata[iy*width+ix] = (uint32_t)(
+ (uint32_t(255 - (Magick::Color::scaleQuantumToDouble(pix->opacity) * 255)) << 24) |
+ (uint32_t( Magick::Color::scaleQuantumToDouble(pix->red) * 255) << 16) |
+ (uint32_t( Magick::Color::scaleQuantumToDouble(pix->green) * 255) << 8) |
+ uint32_t( Magick::Color::scaleQuantumToDouble(pix->blue) * 255)
+ );
+ //if ( isMonochrome ) { // if is monochrome: exchange black and white
+ // uint32_t c = bmpdata[iy*width+ix];
+ // switch(c) {
+ // case cColor::White: c = cColor::Black; break;
+ // case cColor::Black: c = cColor::White; break;
+ // }
+ // bmpdata[iy*width+ix] = c;
+ //}
+ }
+ ++pix;
+ }
+ }
+ cBitmap * b = new cBitmap(width, height, bmpdata);
+ //b->SetMonochrome(isMonochrome);
+ image.AddBitmap(b);
+ delete[] bmpdata;
+ bmpdata = NULL;
+ }
+ }
+ } catch (Magick::Exception &e) {
+ syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s': %s (cExtFormatFile::LoadScaled)", fileName.c_str(), e.what());
+ return false;
+ } catch (...) {
+ syslog(LOG_ERR, "glcdgraphics: Couldn't load '%s': Unknown exception caught (cExtFormatFile::LoadScaled)", fileName.c_str());
+ return false;
+ }
+ return true;
+#else
+ return false;
+#endif
+}
+
+// to be done ...
+bool cExtFormatFile::Save(cImage & image, const string & fileName)
+{
+ return false;
+}
+
+} // end of namespace
diff --git a/glcdgraphics/extformats.h b/glcdgraphics/extformats.h
new file mode 100644
index 0000000..23f6ea2
--- /dev/null
+++ b/glcdgraphics/extformats.h
@@ -0,0 +1,37 @@
+/*
+ * GraphLCD graphics library
+ *
+ * extformats.h - loading and saving of external formats (via ImageMagick)
+ *
+ * based on bitmap.[ch] from text2skin: http://projects.vdr-developer.org/projects/show/plg-text2skin
+ *
+ * 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>
+ */
+
+#ifndef _GLCDGRAPHICS_EXTFORMATS_H_
+#define _GLCDGRAPHICS_EXTFORMATS_H_
+
+#include "imagefile.h"
+
+namespace GLCD
+{
+
+class cImage;
+
+class cExtFormatFile : public cImageFile
+{
+public:
+ cExtFormatFile();
+ virtual ~cExtFormatFile();
+ virtual bool Load(cImage & image, const std::string & fileName);
+ virtual bool Save(cImage & image, const std::string & fileName);
+
+ virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c
index 3b71247..db14638 100644
--- a/glcdgraphics/font.c
+++ b/glcdgraphics/font.c
@@ -9,7 +9,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#include <stdio.h>
@@ -18,9 +20,7 @@
#include <fcntl.h>
#include <unistd.h>
-#include <cstring>
#include <algorithm>
-#include <cstring>
#include "common.h"
#include "font.h"
@@ -28,6 +28,9 @@
#ifdef HAVE_FREETYPE2
#include <ft2build.h>
#include FT_FREETYPE_H
+#include <iconv.h>
+#else
+#include <string.h>
#endif
namespace GLCD
@@ -64,13 +67,13 @@ private:
protected:
cBitmapCache *next; // next bitmap
cBitmap *ptr;
- int charcode;
+ uint32_t charcode;
public:
cBitmapCache();
~cBitmapCache();
- void PushBack(int ch, cBitmap *bitmap);
- cBitmap *GetBitmap(int ch) const;
+ void PushBack(uint32_t ch, cBitmap *bitmap);
+ cBitmap *GetBitmap(uint32_t ch) const;
};
cBitmapCache::cBitmapCache()
@@ -86,7 +89,7 @@ cBitmapCache::~cBitmapCache()
delete next;
}
-void cBitmapCache::PushBack(int ch, cBitmap *bitmap)
+void cBitmapCache::PushBack(uint32_t ch, cBitmap *bitmap)
{
if (!ptr)
{
@@ -102,7 +105,7 @@ void cBitmapCache::PushBack(int ch, cBitmap *bitmap)
next->PushBack(ch, bitmap);
}
-cBitmap *cBitmapCache::GetBitmap(int ch) const
+cBitmap *cBitmapCache::GetBitmap(uint32_t ch) const
{
if (ptr && charcode==ch)
return ptr;
@@ -124,11 +127,12 @@ cFont::~cFont()
Unload();
}
-bool cFont::LoadFNT(const std::string & fileName)
+bool cFont::LoadFNT(const std::string & fileName, const std::string & encoding)
{
// cleanup if we already had a loaded font
Unload();
- loadedFontType = lftFNT; //original fonts
+ fontType = ftFNT; //original fonts
+ isutf8 = (encoding == "UTF-8");
FILE * fontFile;
int i;
@@ -148,6 +152,7 @@ bool cFont::LoadFNT(const std::string & fileName)
buffer[3] != kFontFileSign[3])
{
fclose(fontFile);
+ syslog(LOG_ERR, "cFont::LoadFNT(): Cannot open file: %s - not the correct fileheader.\n",fileName.c_str());
return false;
}
@@ -165,11 +170,32 @@ bool cFont::LoadFNT(const std::string & fileName)
character = chdr[0] | (chdr[1] << 8);
charWidth = chdr[2] | (chdr[3] << 8);
fread(buffer, fontHeight * ((charWidth + 7) / 8), 1, fontFile);
- if (characters[character])
- delete characters[character];
- characters[character] = new cBitmap(charWidth, fontHeight, buffer);
- if (characters[character]->Width() > maxWidth)
- maxWidth = characters[character]->Width();
+#ifdef HAVE_DEBUG
+ printf ("fontHeight %0d - charWidth %0d - character %0d - bytes %0d\n", fontHeight, charWidth, character,fontHeight * ((charWidth + 7) / 8));
+#endif
+
+ int y; int loop;
+ int num = 0;
+ uint dot; uint b;
+ cBitmap * charBitmap = new cBitmap(charWidth, fontHeight);
+ charBitmap->SetMonochrome(true);
+ charBitmap->Clear();
+ for (num=0; num<fontHeight * ((charWidth + 7) / 8);num++) {
+ y = (charWidth + 7) / 8;
+ for (loop=0;loop<((charWidth + 7) / 8); loop++) {
+ for (b=0;b<charWidth;b++) {
+ dot=buffer[num+loop] & (0x80 >> b);
+ if (dot) {
+ charBitmap->DrawPixel(b+((loop*8)),num/y,cColor::Black);
+ }
+ }
+ }
+ num=num+y-1;
+ }
+ SetCharacter(character, charBitmap);
+
+ if (charWidth > maxWidth)
+ maxWidth = charWidth;
}
fclose(fontFile);
@@ -197,7 +223,7 @@ bool cFont::SaveFNT(const std::string & fileName) const
numChars = 0;
for (i = 0; i < 256; i++)
{
- if (characters[i])
+ if (GetCharacter(i))
{
numChars++;
}
@@ -220,16 +246,20 @@ bool cFont::SaveFNT(const std::string & fileName) const
// write font file header
fwrite(fhdr, kFontHeaderSize, 1, fontFile);
+ const cBitmap* charbmp = NULL;
for (i = 0; i < 256; i++)
{
- if (characters[i])
+ charbmp = GetCharacter(i);
+ if (charbmp)
{
chdr[0] = (uint8_t) i;
chdr[1] = (uint8_t) (i >> 8);
- chdr[2] = (uint8_t) characters[i]->Width();
- chdr[3] = (uint8_t) (characters[i]->Width() >> 8);
+ chdr[2] = (uint8_t) charbmp->Width();
+ chdr[3] = (uint8_t) (charbmp->Width() >> 8);
fwrite(chdr, kCharHeaderSize, 1, fontFile);
- fwrite(characters[i]->Data(), totalHeight * characters[i]->LineSize(), 1, fontFile);
+ const unsigned char* monobmp = cBitmap::ConvertTo1BPP(*charbmp);
+ fwrite(monobmp /*characters[i]->Data()*/, totalHeight * ((charbmp->Width() + 7) / 8), 1, fontFile);
+ delete[] monobmp;
}
}
@@ -245,7 +275,9 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding,
{
// cleanup if we already had a loaded font
Unload();
- loadedFontType = lftFT2; // ft2 fonts
+ fontType = ftFT2; // ft2 fonts
+ isutf8 = (encoding == "UTF-8");
+
#ifdef HAVE_FREETYPE2
if (access(fileName.c_str(), F_OK) != 0)
{
@@ -286,6 +318,40 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding,
// set Size
FT_Set_Char_Size(face, 0, size * 64, 0, 0);
+ // generate lookup table for encoding conversions (encoding != UTF8)
+ if (! (isutf8 || dingBats) )
+ {
+ iconv_t cd;
+ if ((cd = iconv_open("WCHAR_T", encoding.c_str())) == (iconv_t) -1)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Iconv encoding not supported: %s", encoding.c_str());
+ error = FT_Done_Face(face);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error);
+ error = FT_Done_FreeType(library);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error);
+ return false;
+ }
+ for (int c = 0; c < 256; c++)
+ {
+ char char_buff = c;
+ wchar_t wchar_buff;
+ char * in_buff,* out_buff;
+ size_t in_len, out_len, count;
+
+ in_len = 1;
+ out_len = 4;
+ in_buff = (char *) &char_buff;
+ out_buff = (char *) &wchar_buff;
+ count = iconv(cd, &in_buff, &in_len, &out_buff, &out_len);
+ iconv_lut[c] = ((size_t) -1 == count) ? (wchar_t)'?' : wchar_buff;
+ }
+ iconv_close(cd);
+ } else {
+ // don't leave LUT uninitialised
+ for (int c = 0; c < 256; c++)
+ iconv_lut[c] = (wchar_t)c;
+ }
+
// get some global parameters
SetTotalHeight( (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6) );
SetTotalWidth ( face->size->metrics.max_advance >> 6 );
@@ -304,7 +370,7 @@ bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding,
#endif
}
-int cFont::Width(int ch) const
+int cFont::Width(uint32_t ch) const
{
const cBitmap *bitmap = GetCharacter(ch);
if (bitmap)
@@ -313,72 +379,32 @@ int cFont::Width(int ch) const
return 0;
}
-void cFont::Utf8CodeAdjustCounter(const std::string & str, int & c, unsigned int & i)
-{
- int c0,c1,c2,c3;
- if (i < str.length())
- {
- c = str[i];
- c0 = str[i];
- c1 = (i+1 < str.length()) ? str[i+1] : 0;
- c2 = (i+2 < str.length()) ? str[i+2] : 0;
- c3 = (i+3 < str.length()) ? str[i+3] : 0;
- c0 &=0xff; c1 &=0xff; c2 &=0xff; c3 &=0xff;
-
- if( c0 >= 0xc2 && c0 <= 0xdf && c1 >= 0x80 && c1 <= 0xbf ){ //2 byte UTF-8 sequence found
- i+=1;
- c = ((c0&0x1f)<<6) | (c1&0x3f);
- }else if( (c0 == 0xE0 && c1 >= 0xA0 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf)
- || (c0 >= 0xE1 && c1 <= 0xEC && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf)
- || (c0 == 0xED && c1 >= 0x80 && c1 <= 0x9f && c2 >= 0x80 && c2 <= 0xbf)
- || (c0 >= 0xEE && c0 <= 0xEF && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf) ){ //3 byte UTF-8 sequence found
- c = ((c0&0x0f)<<4) | ((c1&0x3f)<<6) | (c2&0x3f);
- i+=2;
- }else if( (c0 == 0xF0 && c1 >= 0x90 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf)
- || (c0 >= 0xF1 && c0 >= 0xF3 && c1 >= 0x80 && c1 <= 0xbf && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf)
- || (c0 == 0xF4 && c1 >= 0x80 && c1 <= 0x8f && c2 >= 0x80 && c2 <= 0xbf && c3 >= 0x80 && c3 <= 0xbf) ){ //4 byte UTF-8 sequence found
- c = ((c0&0x07)<<2) | ((c1&0x3f)<<4) | ((c2&0x3f)<<6) | (c3&0x3f);
- i+=3;
- }
- }
-}
-
int cFont::Width(const std::string & str) const
{
- unsigned int i;
- int sum = 0;
- int symcount=0;
- int c;
-
- for (i = 0; i < str.length(); i++)
- {
- Utf8CodeAdjustCounter(str, c, i);
- symcount++;
- sum += Width(c);
- }
- sum += spaceBetween * (symcount - 1);
- return sum;
+ return Width(str, (unsigned int) str.length());
}
int cFont::Width(const std::string & str, unsigned int len) const
{
unsigned int i;
int sum = 0;
- int symcount=0;
- int c;
+ unsigned int symcount=0;
+ uint32_t c;
- for (i = 0; i < str.length() && symcount < len; i++)
+ i = 0;
+ while (i < (unsigned int)str.length() && symcount < len)
{
- Utf8CodeAdjustCounter(str, c, i);
+ encodedCharAdjustCounter(IsUTF8(), str, c, i);
symcount++;
sum += Width(c);
+ i++;
}
sum += spaceBetween * (symcount - 1);
return sum;
}
-int cFont::Height(int ch) const
+int cFont::Height(uint32_t ch) const
{
const cBitmap *bitmap = GetCharacter(ch);
if (bitmap)
@@ -407,10 +433,10 @@ int cFont::Height(const std::string & str, unsigned int len) const
return sum;
}
-const cBitmap * cFont::GetCharacter(int ch) const
+const cBitmap * cFont::GetCharacter(uint32_t ch) const
{
#ifdef HAVE_FREETYPE2
- if ( loadedFontType == lftFT2 ) {
+ if ( fontType == ftFT2 ) {
//lookup in cache
cBitmap *ptr=characters_cache->GetBitmap(ch);
if (ptr)
@@ -419,7 +445,11 @@ const cBitmap * cFont::GetCharacter(int ch) const
FT_Face face = (FT_Face) ft2_face;
FT_UInt glyph_index;
//Get FT char index
- glyph_index = FT_Get_Char_Index(face, ch);
+ if (isutf8) {
+ glyph_index = FT_Get_Char_Index(face, ch);
+ } else {
+ glyph_index = FT_Get_Char_Index(face, iconv_lut[(unsigned char)ch]);
+ }
//Load the char
int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
@@ -443,7 +473,8 @@ const cBitmap * cFont::GetCharacter(int ch) const
} else {
// now, fill our pixel data
cBitmap *charBitmap = new cBitmap(face->glyph->advance.x >> 6, TotalHeight());
- charBitmap->Clear();
+ charBitmap->Clear(cColor::White);
+ charBitmap->SetMonochrome(true);
unsigned char * bufPtr = face->glyph->bitmap.buffer;
unsigned char pixel;
for (int y = 0; y < face->glyph->bitmap.rows; y++)
@@ -454,7 +485,7 @@ const cBitmap * cFont::GetCharacter(int ch) const
if (pixel)
charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x,
(face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y,
- GLCD::clrBlack);
+ /*GLCD::clrBlack*/ cColor::Black);
}
bufPtr += face->glyph->bitmap.pitch;
}
@@ -475,7 +506,7 @@ const cBitmap * cFont::GetCharacter(int ch) const
void cFont::SetCharacter(char ch, cBitmap * bitmapChar)
{
#ifdef HAVE_FREETYPE2
- if ( loadedFontType == lftFT2 ) {
+ if ( fontType == ftFT2 ) {
syslog(LOG_ERR, "cFont::SetCharacter: is not supported with FreeType2 fonts!!!");
return;
}
@@ -503,12 +534,12 @@ void cFont::Init()
{
characters[i] = NULL;
}
- loadedFontType = lftFNT;
#ifdef HAVE_FREETYPE2
ft2_library = NULL;
ft2_face = NULL;
characters_cache = NULL;
#endif
+ fontType = ftFNT;
}
void cFont::Unload()
@@ -539,97 +570,84 @@ void cFont::WrapText(int Width, int Height, std::string & Text,
int lineCount;
int textWidth;
std::string::size_type start;
- std::string::size_type pos;
+ unsigned int pos;
std::string::size_type posLast;
+ uint32_t c;
Lines.clear();
- maxLines = 2000;
+ maxLines = 100;
if (Height > 0)
{
maxLines = Height / LineHeight();
- if (maxLines == 0)
- maxLines = 1;
+ //if (maxLines == 0)
+ maxLines += 1;
}
- lineCount = 0;
+ lineCount = 0;
pos = 0;
start = 0;
posLast = 0;
textWidth = 0;
- while (pos < Text.length() && (Height == 0 || lineCount < maxLines))
+
+ while ((pos < Text.length()) && (lineCount <= maxLines))
{
- if (Text[pos] == '\n')
+ unsigned int posraw = pos;
+ encodedCharAdjustCounter(IsUTF8(), Text, c, posraw);
+
+ if (c == '\n')
{
Lines.push_back(trim(Text.substr(start, pos - start)));
- start = pos + 1;
- posLast = pos + 1;
+ start = pos /*+ 1*/;
+ posLast = pos /*+ 1*/;
textWidth = 0;
lineCount++;
}
- else if (textWidth > Width && (lineCount + 1) < maxLines)
+ else if (textWidth + this->Width(c) > Width && (lineCount + 1) < maxLines)
{
if (posLast > start)
{
Lines.push_back(trim(Text.substr(start, posLast - start)));
- start = posLast + 1;
+ start = posLast /*+ 1*/;
posLast = start;
textWidth = this->Width(Text.substr(start, pos - start + 1)) + spaceBetween;
}
else
{
Lines.push_back(trim(Text.substr(start, pos - start)));
- start = pos + 1;
+ start = pos /*+ 1*/;
posLast = start;
- textWidth = this->Width(Text[pos]) + spaceBetween;
+ textWidth = this->Width(c) + spaceBetween;
}
lineCount++;
}
- else if (Text[pos] == ' ')
+ else if (isspace(c))
{
posLast = pos;
- textWidth += this->Width(Text[pos]) + spaceBetween;
+ textWidth += this->Width(c) + spaceBetween;
+ }
+ else if ( (c < 0x80) && strchr("-.,:;!?_", (int)c) )
+ {
+ posLast = pos+1;
+ textWidth += this->Width(c) + spaceBetween;
}
else
{
- textWidth += this->Width(Text[pos]) + spaceBetween;
+ textWidth += this->Width(c) + spaceBetween;
}
+ pos = posraw;
pos++;
}
+ if (start < Text.length()) {
+ Lines.push_back(trim(Text.substr(start)));
+ }
- if (Height == 0 || lineCount < maxLines)
- {
- if (textWidth > Width && (lineCount + 1) < maxLines)
- {
- if (posLast > start)
- {
- Lines.push_back(trim(Text.substr(start, posLast - start)));
- start = posLast + 1;
- posLast = start;
- textWidth = this->Width(Text.substr(start, pos - start + 1)) + spaceBetween;
- }
- else
- {
- Lines.push_back(trim(Text.substr(start, pos - start)));
- start = pos + 1;
- posLast = start;
- textWidth = this->Width(Text[pos]) + spaceBetween;
- }
- lineCount++;
- }
- if (pos > start)
- {
- Lines.push_back(trim(Text.substr(start)));
- lineCount++;
- }
+ if (ActualWidth) {
textWidth = 0;
for (int i = 0; i < lineCount; i++)
textWidth = std::max(textWidth, this->Width(Lines[i]));
textWidth = std::min(textWidth, Width);
- }
- else
- textWidth = Width;
- if (ActualWidth)
*ActualWidth = textWidth;
+ }
}
} // end of namespace
diff --git a/glcdgraphics/font.h b/glcdgraphics/font.h
index f3427d5..a77de14 100644
--- a/glcdgraphics/font.h
+++ b/glcdgraphics/font.h
@@ -9,7 +9,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2011 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#ifndef _GLCDGRAPHICS_FONT_H_
@@ -28,12 +30,12 @@ class cBitmapCache;
class cFont
{
public:
- enum eLoadedFntType
+ enum eFontType
{
// native glcd font loaded
- lftFNT,
+ ftFNT,
// freetype2 font loaded
- lftFT2
+ ftFT2
};
private:
int totalWidth;
@@ -43,7 +45,10 @@ private:
int lineHeight;
cBitmap * characters[256];
- eLoadedFntType loadedFontType;
+ eFontType fontType;
+
+ bool isutf8;
+ wchar_t iconv_lut[256]; // lookup table needed if encoding != UTF-8
cBitmapCache *characters_cache;
void *ft2_library; //FT_Library
@@ -55,7 +60,7 @@ public:
cFont();
~cFont();
- bool LoadFNT(const std::string & fileName);
+ bool LoadFNT(const std::string & fileName, const std::string & encoding = "UTF-8");
bool SaveFNT(const std::string & fileName) const;
bool LoadFT2(const std::string & fileName, const std::string & encoding,
int size, bool dingBats = false);
@@ -71,20 +76,19 @@ public:
void SetSpaceBetween(int width) { spaceBetween = width; };
void SetLineHeight(int height) { lineHeight = height; };
- int Width(int ch) const;
+ int Width(uint32_t ch) const;
int Width(const std::string & str) const;
int Width(const std::string & str, unsigned int len) const;
- int Height(int ch) const;
+ int Height(uint32_t ch) const;
int Height(const std::string & str) const;
int Height(const std::string & str, unsigned int len) const;
- const cBitmap * GetCharacter(int ch) const;
+ const cBitmap * GetCharacter(uint32_t ch) const;
void SetCharacter(char ch, cBitmap * bitmapChar);
void WrapText(int Width, int Height, std::string & Text,
std::vector <std::string> & Lines, int * TextWidth = NULL) const;
-
- static void Utf8CodeAdjustCounter(const std::string & str, int & c, unsigned int & i);
+ bool IsUTF8(void) const { return isutf8; }
};
} // end of namespace
diff --git a/glcdgraphics/glcd.c b/glcdgraphics/glcd.c
index e79b6b8..6e97208 100644
--- a/glcdgraphics/glcd.c
+++ b/glcdgraphics/glcd.c
@@ -9,7 +9,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2004-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#include <stdio.h>
@@ -67,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;
}
@@ -96,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;
}
@@ -112,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;
}
@@ -124,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;
}
@@ -134,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;
}
@@ -144,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;
}
@@ -154,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;
}
@@ -163,32 +165,55 @@ bool cGLCDFile::Load(cImage & image, const string & fileName)
image.SetWidth(width);
image.SetHeight(height);
image.SetDelay(delay);
- unsigned char * bmpdata = new unsigned char[height * ((width + 7) / 8)];
- if (bmpdata)
+ unsigned char * bmpdata_raw = new unsigned char[height * ((width + 7) / 8)];
+ uint32_t * bmpdata = new uint32_t[height * width];
+ if (bmpdata && bmpdata_raw)
{
for (unsigned int n = 0; n < count; n++)
{
- if (fread(bmpdata, height * ((width + 7) / 8), 1, fp) != 1)
+ if (fread(bmpdata_raw, height * ((width + 7) / 8), 1, fp) != 1)
{
delete[] bmpdata;
fclose(fp);
image.Clear();
return false;
}
- image.AddBitmap(new cBitmap(width, height, bmpdata));
+ int colsize = (width+7)/8;
+ for (int j = 0; j < height; j++) {
+ for (int i = 0; i < width; i++) {
+ if ( bmpdata_raw[j*colsize + (i>>3)] & (1 << (7-(i%8))) ) {
+ bmpdata[j*width+i] = cColor::Black;
+ } else {
+ bmpdata[j*width+i] = cColor::White;
+ }
+ }
+ }
+#ifdef HAVE_DEBUG
+ printf("%s:%s(%d) - filename: '%s', count %d\n", __FILE__, __FUNCTION__, __LINE__, fileName.c_str(), n);
+#endif
+ cBitmap * b = new cBitmap(width, height, bmpdata);
+ b->SetMonochrome(true);
+ //image.AddBitmap(new cBitmap(width, height, bmpdata));
+ image.AddBitmap(b);
}
delete[] bmpdata;
}
else
{
syslog(LOG_ERR, "glcdgraphics: malloc failed (cGLCDFile::Load).");
+ if (bmpdata)
+ delete[] bmpdata;
+ if (bmpdata_raw)
+ delete[] bmpdata_raw;
fclose(fp);
image.Clear();
return false;
}
fclose(fp);
+ 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;
}
@@ -209,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;
}
@@ -260,7 +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( cBitmap::ConvertTo1BPP(*bitmap), height * ((width + 7) / 8), 1, fp) != 1)
{
fclose(fp);
return false;
@@ -270,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 2f56f4a..0f9ec25 100644
--- a/glcdgraphics/imagefile.c
+++ b/glcdgraphics/imagefile.c
@@ -6,11 +6,13 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#include "image.h"
#include "imagefile.h"
+#include "bitmap.h"
namespace GLCD
{
@@ -32,4 +34,21 @@ bool cImageFile::Save(cImage & image, const std::string & fileName)
return false;
}
+
+
+bool cImageFile::LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh)
+{
+ if (Load(image, fileName)) {
+ if (scalew || scaleh) {
+ return image.Scale(scalew, scaleh, true);
+ } else {
+ return true;
+ }
+ } else {
+ scalew = 0;
+ scaleh = 0;
+ return false;
+ }
+}
+
} // end of namespace
diff --git a/glcdgraphics/imagefile.h b/glcdgraphics/imagefile.h
index bf5ff5e..fd7dbcc 100644
--- a/glcdgraphics/imagefile.h
+++ b/glcdgraphics/imagefile.h
@@ -6,7 +6,8 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
*/
#ifndef _GLCDGRAPHICS_IMAGEFILE_H_
@@ -26,6 +27,10 @@ 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 true; }
+
+ virtual bool LoadScaled(cImage & image, const std::string & fileName, uint16_t & scalew, uint16_t & scaleh);
};
} // end of namespace
diff --git a/glcdgraphics/pbm.c b/glcdgraphics/pbm.c
index 2bca3ef..3bf94c1 100644
--- a/glcdgraphics/pbm.c
+++ b/glcdgraphics/pbm.c
@@ -6,7 +6,9 @@
* This file is released under the GNU General Public License. Refer
* to the COPYING file distributed with this package.
*
- * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2006-2010 Andreas Regel <andreas.regel AT powarman.de>
+ * (c) 2010-2013 Wolfgang Astleitner <mrwastl AT users sourceforge net>
+ * Andreas 'randy' Weinberger
*/
#include <stdio.h>
@@ -113,18 +115,35 @@ bool cPBMFile::Load(cImage & image, const std::string & fileName)
image.SetWidth(w);
image.SetHeight(h);
image.SetDelay(100);
- unsigned char * bmpdata = new unsigned char[h * ((w + 7) / 8)];
- if (bmpdata)
+
+ unsigned char * bmpdata_raw = new unsigned char[h * ((w + 7) / 8)];
+ uint32_t * bmpdata = new uint32_t[h * w];
+ if (bmpdata && bmpdata_raw)
{
- if (fread(bmpdata, h * ((w + 7) / 8), 1, pbmFile) != 1)
- {
+ if (fread(bmpdata_raw, h * ((w + 7) / 8), 1, pbmFile) != 1)
+ {
+ delete[] bmpdata;
+ fclose(pbmFile);
+ image.Clear();
+ return false;
+ }
+ int colsize = (w+7)/8;
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < w; i++) {
+ if ( bmpdata_raw[j*colsize + (i>>3)] & (1 << (7-(i%8))) ) {
+ bmpdata[j*w+i] = cColor::Black;
+ } else {
+ bmpdata[j*w+i] = cColor::White;
+ }
+ }
+ }
+ delete [] bmpdata_raw;
+
+ cBitmap * b = new cBitmap(w, h, bmpdata);
+ b->SetMonochrome(true);
+ //image.AddBitmap(new cBitmap(width, height, bmpdata));
+ image.AddBitmap(b);
delete[] bmpdata;
- fclose(pbmFile);
- image.Clear();
- return false;
- }
- image.AddBitmap(new cBitmap(w, h, bmpdata));
- delete[] bmpdata;
}
else
{
@@ -133,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;
}
@@ -143,6 +162,9 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName)
FILE * fp;
char str[32];
const cBitmap * bitmap;
+ unsigned char* rawdata = NULL;
+ int rawdata_size = 0;
+ const uint32_t * bmpdata = NULL;
if (image.Count() == 1)
{
@@ -150,34 +172,71 @@ bool cPBMFile::Save(cImage & image, const std::string & fileName)
if (fp)
{
bitmap = image.GetBitmap(0);
- if (bitmap)
+ rawdata_size = ((bitmap->Width() + 7) / 8) * bitmap->Height();
+ rawdata = new unsigned char[ rawdata_size ];
+ bmpdata = bitmap->Data();
+
+ if (bitmap && rawdata && bmpdata)
{
+ memset(rawdata, 0, rawdata_size );
+ for (int y = 0; y < bitmap->Height(); y++) {
+ int startpos = y * ((bitmap->Width() + 7) / 8);
+ for (int x = 0; x < bitmap->Width(); x++) {
+ if (bmpdata[ y * bitmap->Width() + x ] == cColor::White) {
+ rawdata[ startpos + (x / 8) ] |= (1 << ( 7 - ( x % 8 ) ));
+ }
+ }
+ }
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);
+ delete[] rawdata;
+ rawdata = NULL;
}
}
else
{
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)
{
bitmap = image.GetBitmap(i);
- if (bitmap)
+ rawdata_size = ((bitmap->Width() + 7) / 8) * bitmap->Height();
+ rawdata = new unsigned char[ rawdata_size ];
+ bmpdata = bitmap->Data();
+
+ if (bitmap && rawdata && bmpdata)
{
+ memset(rawdata, 0, rawdata_size );
+ for (int y = 0; y < bitmap->Height(); y++) {
+ int startpos = y * ((bitmap->Width() + 7) / 8);
+ for (int x = 0; x < bitmap->Width(); x++) {
+ if (bmpdata[ y * bitmap->Width() + x ] == cColor::Black) {
+ rawdata[ startpos + (x / 8) ] |= (1 << ( 7 - ( x % 8 ) ));
+ }
+ }
+ }
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);
+ delete[] rawdata;
+ rawdata = NULL;
}
}
}