summaryrefslogtreecommitdiff
path: root/glcdgraphics/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'glcdgraphics/bitmap.c')
-rw-r--r--glcdgraphics/bitmap.c570
1 files changed, 366 insertions, 204 deletions
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
-