diff options
Diffstat (limited to 'glcdgraphics/bitmap.c')
-rw-r--r-- | glcdgraphics/bitmap.c | 570 |
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 - |