From 6d901595fe251b69b37b6c527e4e5695c5272f4f Mon Sep 17 00:00:00 2001 From: Makuna Date: Sat, 23 Apr 2016 14:40:01 -0700 Subject: [PATCH] NeoBitmapFile --- examples/NeoPixelBitmap/NeoPixelBitmap.ino | 96 ++++++ examples/NeoPixelBitmap/Strings.bmp | Bin 0 -> 62262 bytes examples/NeoPixelBitmap/StringsW.bmp | Bin 0 -> 82998 bytes keywords.txt | 1 + library.json | 2 +- library.properties | 2 +- src/NeoPixelBus.h | 5 +- src/internal/NeoBitmapFile.h | 351 +++++++++++++++++++++ src/internal/NeoBuffer.h | 4 +- src/internal/NeoBufferMethods.h | 5 + 10 files changed, 460 insertions(+), 6 deletions(-) create mode 100644 examples/NeoPixelBitmap/NeoPixelBitmap.ino create mode 100644 examples/NeoPixelBitmap/Strings.bmp create mode 100644 examples/NeoPixelBitmap/StringsW.bmp create mode 100644 src/internal/NeoBitmapFile.h diff --git a/examples/NeoPixelBitmap/NeoPixelBitmap.ino b/examples/NeoPixelBitmap/NeoPixelBitmap.ino new file mode 100644 index 0000000..39c2f25 --- /dev/null +++ b/examples/NeoPixelBitmap/NeoPixelBitmap.ino @@ -0,0 +1,96 @@ +// NeoPixelBuffer +// This example will animate pixels using a bitmap stored on a SD card +// +// +// This will demonstrate the use of the NeoBitmapFile object +// NOTE: The images provided in the example directory should be copied to +// the root of the SD card so the below code will find it. +// NOTE: This sample and the included images were built for a 144 pixel strip so +// running this with a smaller string may not look as interesting. Try providing +// your own 24 bit bitmap for better results. + +#include +#include +#include +#include + +const int chipSelect = D8; // make sure to set this to your SD carder reader CS + +//typedef NeoGrbFeature MyPixelColorFeature; +typedef NeoGrbwFeature MyPixelColorFeature; + +const uint16_t PixelCount = 144; // the sample images are meant for 144 pixels +const uint16_t PixelPin = 2; +const uint16_t AnimCount = 1; // we only need one + +NeoPixelBus strip(PixelCount, PixelPin); +NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object + +// our NeoBitmapFile will use the same color feature as NeoPixelBus and +// we want it to use the SD File object +NeoBitmapFile image; + +uint16_t animState; + +void LoopAnimUpdate(const AnimationParam& param) +{ + // wait for this animation to complete, + // we are using it as a timer of sorts + if (param.state == AnimationState_Completed) + { + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + + // draw the complete row at animState to the complete strip + image.Blt(strip, 0, 0, animState, image.Width()); + animState = (animState + 1) % image.Height(); // increment and wrap + } +} + +void setup() { + Serial.begin(115200); + while (!Serial); // wait for serial attach + + strip.Begin(); + strip.Show(); + + Serial.print("Initializing SD card..."); + + // see if the card is present and can be initialized: + if (!SD.begin(chipSelect)) + { + Serial.println("Card failed, or not present"); + // don't do anything more: + return; + } + Serial.println("card initialized."); + + // open the file + File bitmapFile = SD.open("strings.bmp"); + if (!bitmapFile) + { + Serial.println("File open fail, or not present"); + // don't do anything more: + return; + } + + // initialize the image with the file + if (!image.Begin(bitmapFile)) + { + Serial.println("File format fail, not a supported bitmap"); + // don't do anything more: + return; + } + + animState = 0; + // we use the index 0 animation to time how often we rotate all the pixels + animations.StartAnimation(0, 30, LoopAnimUpdate); +} + +void loop() { + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} \ No newline at end of file diff --git a/examples/NeoPixelBitmap/Strings.bmp b/examples/NeoPixelBitmap/Strings.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0ee3be6f14647c2b65a307451aeb70aaa1260c2f GIT binary patch literal 62262 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⪚mGI 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î_Nl&bwX?mEo=-uh#ZYoJ0lbHKu9ektn!{-o^=iNMJ2_;BEpyoOwCLo zy)#=oTTEGq2t2aTj*Dkx5MyDhVfM&psIda2-a1v#k{c^Q(pFeO>>!d9U;)L84tR-( zml$Y~e3m?-0z%F{4Qil5FG`BRO^sPElvSddm8Bk1LV{1_qW*CWj0{>F46E1~RuE{$ zLx$z!3P6k5u=$#mjWr=D5z?yH)zf8WVFq2L!NjPjq!<_!2pOcZwz0;h6(oi$vOouy zGNgcaoBDtTu{}hghlxP~tw0g9I#G=qbfgBUOLzEKKnqZ{ctCZHn+PaJB*}sTA7V0A zvP>D2r-CFvTQ7BZL6#zIO9A-K()*Kz~`v9urgHQ957^H0L4*K z3819_JKhMecm%1{TM@xiSa zva%QXHa*;G^$qkP84XffB_t)<+Sy_)Bq3(NBMaKVfQUj#XhR4*vIG@Ep+s0gOTNP- zLCGGz`4JxMXpB4sP;m+uEKveA*rKFBITUjAjRGgAa-?d*laWD{l_3Yddk7qBTnm^P{J?n%R(<30Hy01+94g3>4yro1RFNSr!VOxa)ZhiWWCwh( zFcveAMpFs76N~O4B*etPAjHU^z{H>jx%L7~>VXF?1i+WR5$6{!9?)rN<-H7LJ)m=M zh|@$+74q(Y96R)@CE(h@=Q34+D^|j%)xmX*Tm~evavDHUCMrp-6C*{qLF<$tGg$$8 zcn;X)Vr3`*cen_h)HiZt2+8Njkwv95Fp;xWkrUcX7LwH)I1(L2vT|`5&<PcvMhhpvsY_ zNX{Xj$;bpc77TJMUPK1vWguEi<=GR+R?G};uzN)_@J%O???VPqet|6h&uIXiT;~-5 zx+_Y<05pybAx-Q+BF+JzDmyX@dKxEMY-ZMg#!)@OK<9NUYcZfsRZ!wO67+KOfl?8~ zVb*RSf03XWT`6Wv8AyZH#GtE#@>#%VE`c_@gD;zNpkXm+?gYwKNhP3T{fIm#ked&5 zFoKQ==x}o180cwQkbr`dnKhu}%H2aiF{r8oI?<8x!)&2}gF$g{fwC23ia((Ubh8hJ z65<7T*gzLdz;_em*@Fs0)OBshhKYc?{Lq^wSQs)WA6`Q?9i7d=1(!xFu68Bl9>f`v@fp!=n!2sJy7}V6#*R&gqY(M0cs8r<1h?0 zJZzw4>RGm+VWkEy&=SD_J3W*c88G-D84A%d5vr!9yTKr zs9salU@)`-#ZGV%=>9lJXp>Ebq=2r`Avd4uNHWBjA~qftI5Jo%qO4*9-?yj0#9)WE zaGjN*iiIHxyxNw&0~clvp!hO#z!S{0m15%nWf?^c(3#1WE)1?gptE^HQa}yzxB^5D zg5RwfkpVj5*u)Oh?*LuGNRjIx?eiLUP%)^4GM~%_-u;mRY3xBtJn%SJ4l{!rBZCq> wHtAsX*?`9vR#(wWFvEtyOdjhP1rub}0DMzb1~Y>PBZC&LI#VQhc4WsF0E{+0tpET3 literal 0 HcmV?d00001 diff --git a/examples/NeoPixelBitmap/StringsW.bmp b/examples/NeoPixelBitmap/StringsW.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8e45e137e025eb263556e0af063c79421507b06e GIT binary patch literal 82998 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 literal 0 HcmV?d00001 diff --git a/keywords.txt b/keywords.txt index e7653a1..b1cd71e 100644 --- a/keywords.txt +++ b/keywords.txt @@ -65,6 +65,7 @@ NeoBufferMethod KEYWORD1 NeoBufferProgmemMethod KEYWORD1 NeoBuffer KEYWORD1 NeoVerticalSpriteSheet KEYWORD1 +NeoBitmapFile KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) diff --git a/library.json b/library.json index cbc1dea..03ddd3d 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/Makuna/NeoPixelBus" }, - "version": "2.1.1", + "version": "2.1.2", "frameworks": "arduino", "platforms": "*" } diff --git a/library.properties b/library.properties index d3f252e..d5d6c2d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NeoPixelBus by Makuna -version=2.1.1 +version=2.1.2 author=Michael C. Miller (makuna@live.com) maintainer=Michael C. Miller (makuna@live.com) sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy. diff --git a/src/NeoPixelBus.h b/src/NeoPixelBus.h index 859fc00..13d00b3 100644 --- a/src/NeoPixelBus.h +++ b/src/NeoPixelBus.h @@ -35,6 +35,8 @@ License along with NeoPixel. If not, see #include "internal/HtmlColor.h" #include "internal/RgbwColor.h" +#include "internal/NeoColorFeatures.h" + #include "internal/Layouts.h" #include "internal/NeoTopology.h" #include "internal/NeoTiles.h" @@ -44,12 +46,11 @@ License along with NeoPixel. If not, see #include "internal/NeoBufferMethods.h" #include "internal/NeoBuffer.h" #include "internal/NeoSpriteSheet.h" +#include "internal/NeoBitmapFile.h" #include "internal/NeoEase.h" #include "internal/NeoGamma.h" -#include "internal/NeoColorFeatures.h" - #if defined(ARDUINO_ARCH_ESP8266) #include "internal/NeoEsp8266DmaMethod.h" #include "internal/NeoEsp8266UartMethod.h" diff --git a/src/internal/NeoBitmapFile.h b/src/internal/NeoBitmapFile.h new file mode 100644 index 0000000..7a1fa5e --- /dev/null +++ b/src/internal/NeoBitmapFile.h @@ -0,0 +1,351 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +const uint16_t c_BitmapFileId = 0x4d42; // "BM" + +#pragma pack(push, 2) +struct BitmapFileHeader +{ + uint16_t FileId; // only c_BitmapFileId is supported + uint32_t FileSize; + uint16_t Reserved0; + uint16_t Reserved1; + uint32_t PixelAddress; +}; + +struct BitmapInfoHeader +{ + uint32_t Size; + int32_t Width; + int32_t Height; + uint16_t Planes; // only support 1 + uint16_t BitsPerPixel; // only support 24 and 32 + uint32_t Compression; // only support BI_Rgb + uint32_t RawDateSize; // can be zero + int32_t XPpm; + int32_t YPpm; + uint32_t PaletteLength; + uint32_t ImportantColorCount; +}; +#pragma pack(pop) + +enum BmpCompression +{ + BI_Rgb, + BI_Rle8, + BI_Rle4, + BI_Bitfields, + BI_Jpeg, + BI_Png, + BI_AlphaBitfields, + BI_Cmyk = 11, + BI_CmykRle8, + BI_CmykRle4 +}; + +template class NeoBitmapFile +{ +public: + NeoBitmapFile() : + _fileAddressPixels(0), + _width(0), + _height(0), + _sizeRow(0), + _bottomToTop(true), + _bytesPerPixel(0) + { + } + + + ~NeoBitmapFile() + { + _file.close(); + } + + bool Begin(T_FILE_METHOD file) + { + if (_file) + { + _file.close(); + } + + if (!file || !file.seek(0)) + { + goto error; + } + + _file = file; + + BitmapFileHeader bmpHeader; + BitmapInfoHeader bmpInfoHeader; + int result; + + result = _file.read(&bmpHeader, sizeof(bmpHeader)); + + if (result != sizeof(bmpHeader) || + bmpHeader.FileId != c_BitmapFileId || + bmpHeader.FileSize != _file.size()) + { + goto error; + } + + result = _file.read(&bmpInfoHeader, sizeof(bmpInfoHeader)); + + if (result != sizeof(bmpInfoHeader) || + result != bmpInfoHeader.Size || + 1 != bmpInfoHeader.Planes || + BI_Rgb != bmpInfoHeader.Compression) + { + goto error; + } + + if (!(24 == bmpInfoHeader.BitsPerPixel || + 32 == bmpInfoHeader.BitsPerPixel)) + { + goto error; + } + + // save the interesting information + _width = abs(bmpInfoHeader.Width); + _height = abs(bmpInfoHeader.Height); + _fileAddressPixels = bmpHeader.PixelAddress; + // negative height means rows are top to bottom + _bottomToTop = (bmpInfoHeader.Height > 0); + // rows are 32 bit aligned so they may have padding on each row + _sizeRow = (bmpInfoHeader.BitsPerPixel * _width + 31) / 32 * 4; + _bytesPerPixel = bmpInfoHeader.BitsPerPixel / 8; + + return true; + + error: + _fileAddressPixels = 0; + _width = 0; + _height = 0; + _sizeRow = 0; + _bytesPerPixel = 0; + + _file.close(); + return false; + }; + + size_t PixelSize() const + { + return T_COLOR_FEATURE::PixelSize; + }; + + uint16_t PixelCount() const + { + return _width * _height; + }; + + uint16_t Width() const + { + return _width; + }; + + uint16_t Height() const + { + return _height; + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(int16_t x, int16_t y) const + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + typename T_COLOR_FEATURE::ColorObject color; + if (!seek(x, y) || !readPixel(&color)) + { + return 0; + } + + return color; + }; + + void Blt(NeoBufferContext destBuffer, + uint16_t indexPixel, + int16_t xSrc, + int16_t ySrc, + int16_t wSrc) + { + const uint16_t destPixelCount = destBuffer.PixelCount(); + typename T_COLOR_FEATURE::ColorObject color(0); + xSrc = constrainX(xSrc); + ySrc = constrainY(ySrc); + + if (seek(xSrc, ySrc)) + { + for (int16_t x = 0; x < wSrc && indexPixel < destPixelCount; x++, indexPixel++) + { + if (xSrc < _width) + { + if (readPixel(&color)) + { + xSrc++; + } + } + + T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color); + } + } + } + + void Blt(NeoBufferContext destBuffer, + int16_t xDest, + int16_t yDest, + int16_t xSrc, + int16_t ySrc, + int16_t wSrc, + int16_t hSrc, + LayoutMapCallback layoutMap) + { + const uint16_t destPixelCount = destBuffer.PixelCount(); + typename T_COLOR_FEATURE::ColorObject color(0); + + for (int16_t y = 0; y < hSrc; y++) + { + int16_t xFile = constrainX(xSrc); + int16_t yFile = constrainY(ySrc + y); + + if (seek(xFile, yFile)) + { + for (int16_t x = 0; x < wSrc; x++) + { + if (xFile < _width) + { + if (readPixel(&color)) + { + xFile++; + } + } + + uint16_t indexDest = layoutMap(xDest + x, yDest + y); + + if (indexDest < destPixelCount) + { + T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexDest, color); + } + } + } + } + }; + + +private: + T_FILE_METHOD _file; + uint32_t _fileAddressPixels; + uint16_t _width; + uint16_t _height; + uint32_t _sizeRow; + uint8_t _bytesPerPixel; + bool _bottomToTop; + + int16_t constrainX(int16_t x) + { + if (x < 0) + { + x = 0; + } + else if (x >= _width) + { + x = _width - 1; + } + return x; + }; + + int16_t constrainY(int16_t y) + { + if (y < 0) + { + y = 0; + } + else if (y >= _height) + { + y = _height - 1; + } + return y; + }; + + bool seek(int16_t x, int16_t y) + { + if (_bottomToTop) + { + y = (_height - 1) - y; + } + + uint32_t pos = y * _sizeRow + x * _bytesPerPixel; + pos += _fileAddressPixels; + + return _file.seek(pos); + }; + + bool readPixel(RgbColor* color) + { + uint8_t bgr[4]; + int result; + + result = _file.read(bgr, _bytesPerPixel); + + if (result != _bytesPerPixel) + { + *color = 0; + return false; + } + + color->B = bgr[0]; + color->G = bgr[1]; + color->R = bgr[2]; + + return true; + }; + + bool readPixel(RgbwColor* color) + { + uint8_t bgr[4]; + int result; + + bgr[3] = 0; // init white channel as read maybe only 3 bytes + result = _file.read(bgr, _bytesPerPixel); + + if (result != _bytesPerPixel) + { + *color = 0; + return false; + } + + color->B = bgr[0]; + color->G = bgr[1]; + color->R = bgr[2]; + color->W = bgr[3]; + + return true; + }; +}; \ No newline at end of file diff --git a/src/internal/NeoBuffer.h b/src/internal/NeoBuffer.h index 691a9b8..86176c9 100644 --- a/src/internal/NeoBuffer.h +++ b/src/internal/NeoBuffer.h @@ -55,7 +55,7 @@ public: return _method.Height(); }; - void SetPixelColor(uint16_t indexSprite, + void SetPixelColor( int16_t x, int16_t y, typename T_BUFFER_METHOD::ColorObject color) @@ -63,7 +63,7 @@ public: _method.SetPixelColor(pixelIndex(x, y), color); }; - typename T_BUFFER_METHOD::ColorObject GetPixelColor(uint16_t indexSprite, + typename T_BUFFER_METHOD::ColorObject GetPixelColor( int16_t x, int16_t y) const { diff --git a/src/internal/NeoBufferMethods.h b/src/internal/NeoBufferMethods.h index 0c1b205..4bd531f 100644 --- a/src/internal/NeoBufferMethods.h +++ b/src/internal/NeoBufferMethods.h @@ -55,6 +55,11 @@ public: } } + ~NeoBufferMethod() + { + free(_pixels); + } + operator NeoBufferContext() { return NeoBufferContext(Pixels(), PixelsSize());