-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
fix POV Display usermod #4427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
fix POV Display usermod #4427
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
41f31b8
POV Display usermod
Liliputech a5d1c37
Apply suggestions from code review
Liliputech 0ce9ac6
improve file extension checks
Liliputech 4ef95ee
improve README, remove PNGdec reference, clean usermod
Liliputech 4cb6e8f
improve readme
Liliputech 1311102
restrain to esp32 platform + reduce memory footprint with malloc
Liliputech 804dca8
Update usermods/pov_display/README.md
Liliputech 9275b6c
update readme
Liliputech File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| ##POV Display usermod | ||
|
|
||
| this usermod adds a new effect called "POV Image". | ||
|
|
||
| To get it working: | ||
| - resize your image, the height should be same number of pixels as your led strip. | ||
| - rotate your image 90 degrees clockwise (height is now width...) | ||
| - upload a bmp image to the ESP filesystem using "/edit" url. | ||
| - select "POV Image" effect. | ||
| - set the segment name with the absolute path of the image (ie: "/myimage.bmp"). | ||
| - rotate the segment at approximately 20 RPM. | ||
| - enjoy the show! | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| #include "bmpimage.h" | ||
| #define BUF_SIZE 64000 | ||
|
|
||
| byte _buffer[BUF_SIZE]; | ||
|
|
||
| uint16_t read16(File &f) { | ||
| uint16_t result; | ||
| f.read((uint8_t *)&result,2); | ||
| return result; | ||
| } | ||
|
|
||
| uint32_t read32(File &f) { | ||
| uint32_t result; | ||
| f.read((uint8_t *)&result,4); | ||
| return result; | ||
| } | ||
|
|
||
| bool BMPimage::init(const char * fn) { | ||
| File bmpFile; | ||
| int bmpDepth; | ||
| //first, check if filename exists | ||
| if (!WLED_FS.exists(fn)) { | ||
| return false; | ||
| } | ||
|
|
||
| bmpFile = WLED_FS.open(fn); | ||
| if (!bmpFile) { | ||
| _valid=false; | ||
| return false; | ||
| } | ||
|
|
||
| //so, the file exists and is opened | ||
| // Parse BMP header | ||
| uint16_t header = read16(bmpFile); | ||
| if(header != 0x4D42) { // BMP signature | ||
| _valid=false; | ||
| bmpFile.close(); | ||
| return false; | ||
| } | ||
|
|
||
| //read and ingnore file size | ||
| read32(bmpFile); | ||
| (void)read32(bmpFile); // Read & ignore creator bytes | ||
| _imageOffset = read32(bmpFile); // Start of image data | ||
| // Read DIB header | ||
| read32(bmpFile); | ||
| _width = read32(bmpFile); | ||
| _height = read32(bmpFile); | ||
| if(read16(bmpFile) != 1) { // # planes -- must be '1' | ||
| _valid=false; | ||
| bmpFile.close(); | ||
| return false; | ||
| } | ||
| bmpDepth = read16(bmpFile); // bits per pixel | ||
| if((bmpDepth != 24) || (read32(bmpFile) != 0)) { // 0 = uncompressed { | ||
| _width=0; | ||
| _valid=false; | ||
| bmpFile.close(); | ||
| return false; | ||
| } | ||
| // If _height is negative, image is in top-down order. | ||
| // This is not canon but has been observed in the wild. | ||
| if(_height < 0) { | ||
| _height = -_height; | ||
| } | ||
| //now, we have successfully got all the basics | ||
| // BMP rows are padded (if needed) to 4-byte boundary | ||
| _rowSize = (_width * 3 + 3) & ~3; | ||
| //check image size - if it is too large, it will be unusable | ||
| if (_rowSize*_height>BUF_SIZE) { | ||
| _valid=false; | ||
| bmpFile.close(); | ||
| return false; | ||
| } | ||
|
|
||
| bmpFile.close(); | ||
| strcpy(filename,fn); | ||
| return true; | ||
| } | ||
Liliputech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| void BMPimage::clear(){ | ||
| strcpy(filename, ""); | ||
| _width=0; | ||
| _height=0; | ||
| _rowSize=0; | ||
| _imageOffset=0; | ||
| _loaded=false; | ||
| _valid=false; | ||
| } | ||
|
|
||
| bool BMPimage::load(){ | ||
| uint16_t size= _rowSize * _height; | ||
| if (BUF_SIZE < size ){ | ||
| return false; | ||
| } | ||
|
|
||
| File bmpFile = WLED_FS.open(filename); | ||
| if (!bmpFile) { | ||
| return false; | ||
| } | ||
| bmpFile.seek(_imageOffset); | ||
| bmpFile.read(_buffer, size); | ||
| bmpFile.close(); | ||
| _loaded = true; | ||
| return true; | ||
| } | ||
Liliputech marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| byte* BMPimage::line(uint16_t n){ | ||
| if (_loaded) { | ||
| return (_buffer+n*_rowSize); | ||
| } else { | ||
| return NULL; | ||
| } | ||
| } | ||
|
|
||
| uint32_t BMPimage::pixelColor(uint16_t x, uint16_t y){ | ||
| uint32_t pos; | ||
| byte b,g,r; //colors | ||
| if (! _loaded) { | ||
| return 0; | ||
| } | ||
| if ( (x>=_width) || (y>=_height) ) { | ||
| return 0; | ||
| } | ||
| pos=y*_rowSize + 3*x; | ||
| //get colors. Note that in BMP files, they go in BGR order | ||
| b= _buffer[pos++]; | ||
| g= _buffer[pos++]; | ||
| r= _buffer[pos]; | ||
| return (r<<16|g<<8|b); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #ifndef _BMPIMAGE_H | ||
| #define _BMPIMAGE_H | ||
| #include "Arduino.h" | ||
| #include "wled.h" | ||
|
|
||
| /* | ||
| * This class describes a bitmap image. Each object refers to a bmp file on | ||
| * filesystem fatfs. | ||
| * To initialize, call init(), passign to it name of a bitmap file | ||
| * at the root of fatfs filesystem: | ||
| * | ||
| * BMPimage myImage; | ||
| * myImage.init("logo.bmp"); | ||
| * | ||
| * For performance reasons, before actually usign the image, you need to load | ||
| * it from filesystem to RAM: | ||
| * myImage.load(); | ||
| * All load() operations use the same reserved buffer in RAM, so you can only | ||
| * have one file loaded at a time. Before loading a new file, always unload the | ||
| * previous one: | ||
| * myImage.unload(); | ||
| */ | ||
|
|
||
| class BMPimage { | ||
| public: | ||
| int height() {return _height; } | ||
| int width() {return _width; } | ||
| int rowSize() {return _rowSize;} | ||
| bool isLoaded() {return _loaded; } | ||
| bool load(); | ||
| void unload() {_loaded=false; } | ||
| byte * line(uint16_t n); | ||
| uint32_t pixelColor(uint16_t x,uint16_t y); | ||
| bool init(const char* fn); | ||
| void clear(); | ||
| char * getFilename() {return filename;}; | ||
|
|
||
| private: | ||
| char filename[WLED_MAX_SEGNAME_LEN+1]=""; | ||
| int _width=0; | ||
| int _height=0; | ||
| int _rowSize=0; | ||
| int _imageOffset=0; | ||
| bool _loaded=false; | ||
| bool _valid=false; | ||
| }; | ||
|
|
||
| extern byte _buffer[]; | ||
|
|
||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,5 @@ | |
| "name:": "pov_display", | ||
| "build": { "libArchive": false}, | ||
| "dependencies": { | ||
| "bitbank2/PNGdec":"^1.0.3" | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #include "pov.h" | ||
|
|
||
| POV::POV() {} | ||
|
|
||
| void POV::showLine(byte * line, uint16_t size){ | ||
| uint16_t i,pos; | ||
| uint8_t r,g,b; | ||
| for (i=0; i<SEGLEN; i++) { | ||
| if (i<size) { | ||
| pos=3*i; | ||
| //using bgr order | ||
| b=line[pos++]; | ||
| g=line[pos++]; | ||
| r=line[pos]; | ||
| SEGMENT.setPixelColor(i, CRGB(r,g,b)); | ||
| } else { | ||
| SEGMENT.setPixelColor(i, CRGB::Black); | ||
| } | ||
| } | ||
| strip.show(); | ||
| lastLineUpdate=micros(); | ||
| } | ||
Liliputech marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| bool POV::loadImage(char * filename){ | ||
| if(!image.init(filename)) return false; | ||
| if(!image.load()) return false; | ||
| currentLine=0; | ||
| return true; | ||
| } | ||
|
|
||
| int16_t POV::showNextLine(){ | ||
| if (!image.isLoaded()) return 0; | ||
| //move to next line | ||
| showLine(image.line(currentLine), image.width()); | ||
| currentLine++; | ||
| if (currentLine == image.height()) {currentLine=0;} | ||
| return currentLine; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #ifndef _POV_H | ||
| #define _POV_H | ||
| #include "bmpimage.h" | ||
|
|
||
|
|
||
| class POV { | ||
| public: | ||
| POV(); | ||
|
|
||
| /* Shows one line. line should be pointer to array which holds pixel colors | ||
| * (3 bytes per pixel, in BGR order). Note: 3, not 4!!! | ||
| * size should be size of array (number of pixels, not number of bytes) | ||
| */ | ||
| void showLine(byte * line, uint16_t size); | ||
|
|
||
| /* Reads from file an image and making it current image */ | ||
| bool loadImage(char * filename); | ||
|
|
||
| /* Show next line of active image | ||
| Retunrs the index of next line to be shown (not yet shown!) | ||
| If it retunrs 0, it means we have completed showing the image and | ||
| next call will start again | ||
| */ | ||
| int16_t showNextLine(); | ||
|
|
||
| //time since strip was last updated, in micro sec | ||
| uint32_t timeSinceUpdate() {return (micros()-lastLineUpdate);} | ||
|
|
||
|
|
||
| BMPimage * currentImage() {return ℑ} | ||
|
|
||
| char * getFilename() {return image.getFilename();} | ||
|
|
||
| private: | ||
| BMPimage image; | ||
| int16_t currentLine=0; //next line to be shown | ||
| uint32_t lastLineUpdate=0; //time in microseconds | ||
| }; | ||
|
|
||
|
|
||
|
|
||
| #endif |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.