diff --git a/example/demo1.cpp b/example/demo1.cpp index bdda2ff..82a28ab 100644 --- a/example/demo1.cpp +++ b/example/demo1.cpp @@ -41,7 +41,7 @@ unsigned long long currentTimeMillis() { } -void drawSine(Image image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { +void drawSine(Image &image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { bool first = true;; int lx = -1, ly = -1; double vx = 0; @@ -62,7 +62,7 @@ void drawSine(Image image, float offset, float speed, int maxX, int maxY, float } -bool demoSineWave(int frameCount, long long start, Image image) { +bool demoSineWave(int frameCount, long long start, Image &image) { long long now = currentTimeMillis(); float refVoltage = 5; @@ -148,6 +148,20 @@ void rotationDemo() { } +void imageDemo(Image &img) { + Image images[] = { + img, + img.scale(0.75, 0.75, BILINEAR), + img.scale(0.50, 0.50, BILINEAR), + img.scale(0.25 ,0.25, BILINEAR) + }; + for (int i = 0; i < sizeof(images)/sizeof(img); i++) { + Image &thisImg = images[i]; + d1.showImage(thisImg, DEGREE_270); + delay(2000); + } + } + void display1Demo() { printf("demo1\n"); fflush(stdout); @@ -170,8 +184,7 @@ void display1Demo() { delay(solidsDelay); d1.clearScreen(BLACK); - d1.showImage(bmp, DEGREE_270); - delay(2000); + imageDemo(bmp); rotationDemo(); delay(4000); @@ -215,14 +228,6 @@ int main(int argc, char **argv) digitalWrite(10, HIGH); digitalWrite(11, HIGH); - int demos = 3; - pthread_t threads[demos]; - char message[demos][256]; - - for (int i = 0; i < demos; ++i) { - sprintf(message[i], "demo thread %d", i); - } - configureDisplay1(); printf("press control-c to quit\n"); diff --git a/example/demo2.cpp b/example/demo2.cpp index 5a53314..1ceae9a 100644 --- a/example/demo2.cpp +++ b/example/demo2.cpp @@ -42,7 +42,7 @@ unsigned long long currentTimeMillis() { } -void drawSine(Image image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { +void drawSine(Image &image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { bool first = true;; int lx = -1, ly = -1; double vx = 0; @@ -63,7 +63,7 @@ void drawSine(Image image, float offset, float speed, int maxX, int maxY, float } -bool demoSineWave(int frameCount, long long start, Image image) { +bool demoSineWave(int frameCount, long long start, Image &image) { long long now = currentTimeMillis(); float refVoltage = 5; diff --git a/example/neopixel2.cpp b/example/neopixel2.cpp index bfcb1e9..367e3e8 100644 --- a/example/neopixel2.cpp +++ b/example/neopixel2.cpp @@ -73,7 +73,7 @@ unsigned long long currentTimeMillis() { } -void drawSine(Image image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { +void drawSine(Image &image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { bool first = true; int lx = -1, ly = -1; double vx = 0; @@ -94,7 +94,7 @@ void drawSine(Image image, float offset, float speed, int maxX, int maxY, float } -bool demoSineWave(int frameCount, long long start, Image image) { +bool demoSineWave(int frameCount, long long start, Image &image) { long long now = currentTimeMillis(); float refVoltage = 5; diff --git a/example/wsePaperV2.cpp b/example/wsePaperV2.cpp index 76fb6b9..f674872 100644 --- a/example/wsePaperV2.cpp +++ b/example/wsePaperV2.cpp @@ -39,7 +39,7 @@ unsigned long long currentTimeMillis() { } -void drawSine(Image image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { +void drawSine(Image &image, float offset, float speed, int maxX, int maxY, float waveHeight, Color color, int width) { bool first = true;; int lx = -1, ly = -1; double vx = 0; @@ -60,7 +60,7 @@ void drawSine(Image image, float offset, float speed, int maxX, int maxY, float } -bool demoSineWave(int frameCount, long long start, Image image) { +bool demoSineWave(int frameCount, long long start, Image &image) { long long now = currentTimeMillis(); float refVoltage = 5; diff --git a/src/controller/Color.cpp b/src/controller/Color.cpp index 520b513..7fd51a5 100644 --- a/src/controller/Color.cpp +++ b/src/controller/Color.cpp @@ -1,6 +1,6 @@ #include "Color.h" #include -#include +#include Color::Color() { color.red = 0; @@ -9,22 +9,22 @@ Color::Color() { color.opacity = 255; } - Color::Color(ColorType color) { - this->color.red = color.red; - this->color.green = color.green; - this->color.blue = color.blue; - this->color.opacity = color.opacity; + setColor(color.red, color.green, color.blue, color.opacity); } - Color::Color(_byte red, _byte green, _byte blue) { - color.red = red; - color.green = green; - color.blue = blue; - color.opacity = 255; + setColor(red, green, blue, 255); +} + +Color::Color(_byte red, _byte green, _byte blue, _byte opacity) { + setColor(red, green, blue, opacity); } +Color::Color(uint32_t colorRGB24) { + setRGB24(colorRGB24); +} + Color::Color(const char* hexbytes) { char buf[3]; int intensity; @@ -108,23 +108,20 @@ bool Color::equals(ColorType *otherColor) { } -Color::Color(_byte red, _byte green, _byte blue, _byte opacity) { - color.red = red; - color.green = green; - color.blue = blue; - color.opacity = opacity; -} - -ColorType Color::toType() { - return color; +inline void Color::setColor(_byte red, _byte green, _byte blue, _byte opacity) { + color.red = red; + color.green = green; + color.blue = blue; + color.opacity = opacity; } - -int32_t Color::rgb24() { - return (color.green<<16)+(color.red<<8)+(color.blue); +inline void Color::setRGB24(uint32_t colorRGB24) { + color.red = (_byte)(colorRGB24 & 0xFF); + color.green = (_byte)((colorRGB24 & 0xFF00) >> 8); + color.blue = (_byte)((colorRGB24 & 0xFF0000) >> 16); + color.opacity = (_byte)((colorRGB24 & 0xFF000000) >> 24); } - Color::Color(int clr) { color.opacity = 255; diff --git a/src/controller/Color.h b/src/controller/Color.h index b6e3f03..52c0b83 100644 --- a/src/controller/Color.h +++ b/src/controller/Color.h @@ -12,6 +12,9 @@ struct ColorStruct { typedef ColorStruct ColorType; +inline uint32_t getRGB24(const ColorType *color) { + return (color->opacity << 24 ) | (color->blue << 16) | (color->green << 8) | color->red; +} class Color { public: @@ -19,14 +22,17 @@ class Color { Color(); Color(ColorType color); - Color(_byte red, _byte blue, _byte green); + Color(_byte red, _byte green, _byte blue); + Color(_byte red, _byte green, _byte blue, _byte opacity); + Color(uint32_t colorRGB24); Color(const char *hexbytes); - Color(_byte red, _byte blue, _byte green, _byte opacity); - + Color(int pos); - ColorType toType(); - int32_t rgb24(); + inline ColorType toType() { return color; } + inline uint32_t rgb24() { return getRGB24(&color); } + inline void setColor(_byte red, _byte green, _byte blue, _byte opacity); + inline void setRGB24(uint32_t colorRGB24); void print(); bool equals(Color otherColor); bool equals(ColorType otherColor); diff --git a/src/controller/Image.cpp b/src/controller/Image.cpp index d5e5614..8ce6dbc 100644 --- a/src/controller/Image.cpp +++ b/src/controller/Image.cpp @@ -6,26 +6,48 @@ using namespace udd; -Image::Image() { - width=0; - height=0; - backgroundColor=BLACK; +#undef max // in case any sys header defines it +inline float max(float a, float b) { return (a < b) ? a : b; }; +inline float lerp(float s, float e, float t){return s+(e-s)*t;} +inline float blerp(float c00, float c10, float c01, float c11, float tx, float ty) { + return lerp(lerp(c00, c10, tx), lerp(c01, c11, tx), ty); } +#define getByte(value, n) (value >> (n*8) & 0xFF) +// Default c'tor +Image::Image() : Image(0, 0, BLACK) { +} +// Copy c'tor +Image::Image(const Image &img) { + width = img.width; + height = img.height; + backgroundColor = img.backgroundColor; + init(); + memcpy(canvas, img.canvas, width * height * sizeof(ColorType)); +} Image::Image(int width, int height, Color backgroundColor) { this->width = width; this->height = height; this->backgroundColor = backgroundColor; + init(); + clear(backgroundColor); +} +// Private initializer helper +void Image::init() { uint32_t imageSize = width * height; - uint32_t memorySize = imageSize * sizeof(ColorType); - - canvas = (ColorType*)malloc(memorySize); + canvas = NULL; + if (imageSize > 0) { + canvas = new ColorType[imageSize]; + } +} - clear(backgroundColor); +// D'tor +Image::~Image() { + close(); } int udd::Image::getWidth() { @@ -49,7 +71,10 @@ void Image::clear(Color backgroundColor) { } void Image::close() { - free(canvas); + if (NULL != canvas) { + delete canvas; + canvas = NULL; + } } void Image::drawPixel(int x, int y, Color color) { @@ -65,12 +90,6 @@ void Image::drawPixel(int x, int y, Color color) { xp->blue = color.color.blue; xp->opacity = color.color.opacity; - - if (color.color.red != 0 || - color.color.green != 0 || - color.color.blue != 0 - ) { - } } @@ -86,20 +105,19 @@ void Image::printPixel(int x, int y) { } } -ColorType* Image::getPixelColor(int x, int y) { +ColorType* Image::getPixelColor(int x, int y) const { if (x<0 || x >= width || y<0 || y>=height) { return NULL; } long offset = (y * width) + x; - ColorType* xp = canvas + offset; - return xp; + return &canvas[offset]; } -ColorType* Image::getPixel(int x, int y, Rotation rotation) { +ColorType* Image::getPixel(int x, int y, Rotation rotation) const { switch (rotation) { case DEGREE_0: return getPixelColor(x, y); case DEGREE_90: return getPixelColor(y, height-x-1); @@ -468,7 +486,38 @@ void Image::drawPieSlice(int x, int y, int radius, float degree1, float degree2, } } } +} +Image Image::scale(float scaleX, float scaleY, ScaleMode mode) { + int newWidth = (int)(width * scaleX); + int newHeight = (int)(height * scaleY); + Image newImage = Image(newWidth, newHeight, backgroundColor); + switch (mode) { + case BILINEAR: + Image::scaleBilinear(*this, newImage); + break; + default: + fprintf(stderr, "not yet implemented (mode=%d)\n", mode); + } + return newImage; +} - -} \ No newline at end of file +void Image::scaleBilinear(const Image &src, Image &dst) { + for (int y = 0; y < dst.height; y++) { + for (int x = 0; x < dst.width; x++) { + float gx = max(x / (float)(dst.width) * (src.width) - 0.5f, src.width - 1); + float gy = max(y / (float)(dst.height) * (src.height) - 0.5, src.height - 1); + int gxi = (int)gx; + int gyi = (int)gy; + uint32_t result=0; + uint32_t c00 = getRGB24(src.getPixelColor(gxi, gyi)); + uint32_t c10 = getRGB24(src.getPixelColor(gxi+1, gyi)); + uint32_t c01 = getRGB24(src.getPixelColor(gxi, gyi+1)); + uint32_t c11 = getRGB24(src.getPixelColor(gxi+1, gyi+1)); + for(uint8_t i = 0; i < 3; i++){ + result |= (uint8_t)blerp(getByte(c00, i), getByte(c10, i), getByte(c01, i), getByte(c11, i), gx - gxi, gy -gyi) << (8*i); + } + dst.drawPixel(x,y, Color(result)); + } + } +} diff --git a/src/controller/Image.h b/src/controller/Image.h index f4b384c..bac2549 100644 --- a/src/controller/Image.h +++ b/src/controller/Image.h @@ -17,6 +17,8 @@ namespace udd { class Image { public: Image(); + Image(const Image &img); + virtual ~Image(); Image(int width, int height, Color backgroundColor); @@ -51,9 +53,14 @@ namespace udd { void drawPieSlice(int x, int y, int radius, float degree1, float degree2, Color color, LineStyle style, int width); void printPixel(int x, int y); - ColorType* getPixel(int x, int y, udd::Rotation rotation); + ColorType* getPixel(int x, int y, udd::Rotation rotation) const; - ColorType* getPixelColor(int x, int y); + ColorType* getPixelColor(int x, int y) const; + + Image scale(float scaleX, float scaleY, ScaleMode mode); + + private: + static void scaleBilinear(const Image &src, Image &dst); private: @@ -64,6 +71,6 @@ namespace udd { Color backgroundColor; _word color2word(ColorType* xp); - + void init(); }; } diff --git a/src/controller/Metadata.h b/src/controller/Metadata.h index 95853dc..77195a1 100644 --- a/src/controller/Metadata.h +++ b/src/controller/Metadata.h @@ -36,6 +36,8 @@ namespace udd { MASK } FillPattern; - + typedef enum { + BILINEAR + } ScaleMode; } diff --git a/src/displays/DisplayNeoPixel.cpp b/src/displays/DisplayNeoPixel.cpp index 87fcc1a..689ec8b 100644 --- a/src/displays/DisplayNeoPixel.cpp +++ b/src/displays/DisplayNeoPixel.cpp @@ -56,7 +56,7 @@ namespace udd { render(config.screenRotation); } - void DisplayNeoPixel::showImage(Image image, Rotation rotation, ScreenMirror mirror) { + void DisplayNeoPixel::showImage(Image &image, Rotation rotation, ScreenMirror mirror) { int row=0; int pos=0; @@ -104,12 +104,12 @@ namespace udd { } - void DisplayNeoPixel::showImage(Image image, Rotation rotation) { + void DisplayNeoPixel::showImage(Image &image, Rotation rotation) { showImage(image, rotation, config.screenMirror); } - void DisplayNeoPixel::showImage(Image image) { + void DisplayNeoPixel::showImage(Image &image) { showImage(image, config.screenRotation, config.screenMirror); } diff --git a/src/displays/DisplayNeoPixel.h b/src/displays/DisplayNeoPixel.h index d2f27fd..c5098d5 100644 --- a/src/displays/DisplayNeoPixel.h +++ b/src/displays/DisplayNeoPixel.h @@ -32,9 +32,9 @@ namespace udd { void clearScreen(Color color); - void showImage(Image image, Rotation rotation, ScreenMirror mirror); - void showImage(Image image, Rotation rotation); - void showImage(Image image); + void showImage(Image &image, Rotation rotation, ScreenMirror mirror); + void showImage(Image &image, Rotation rotation); + void showImage(Image &image); void setPixel(Pixel pixel); private: