Skip to content

Commit

Permalink
Merge pull request #553 from davepl/EffectTable
Browse files Browse the repository at this point in the history
Fix animated GIF effects
  • Loading branch information
rbergen authored Dec 1, 2023
2 parents f6e1fb0 + 5d38376 commit f61b561
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 102 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,19 @@ Add whatever you want and/or need to make your LED dreams come true. Fix my blun

## Time it takes to build this project

To replicate, build the mesmerizer project. Then delete pio/build_cache and build again, taking the time for the second build.

- HP Z6 G5A, 7995WX, 128GB [96-core, 192-thread]
-> [davepl 11/29/2023] 25.270 seconds

- 3970X, 128GB [32-core, 64-thread] Windows11+WSL2/Ubuntu02.04LTS
-> [davepl 11/29/2023] 34.292 seconds

- Mac M1 Ultra Studio [10-core, 20-thread]
-> [davepl 11/29/2023] 48.368 seconds

## Old Build times, no longer relevant with current platformio, just historical curiosity:

Time to build the SPECTRUM config (`pio run -e spectrum`). Assumes a clean build after everything has been installed and downloaded.

- AMD 3970 32-cores, 128GB, RAID SSD
Expand Down
108 changes: 20 additions & 88 deletions include/effects/matrix/PatternAnimatedGIF.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ struct GIFInfo : public EmbeddedFile
{}
};

static std::map<GIFIdentifier, GIFInfo, std::less<GIFIdentifier>, psram_allocator<std::pair<GIFIdentifier, GIFInfo>>> AnimatedGIFs =
static std::map<GIFIdentifier, const GIFInfo, std::less<GIFIdentifier>, psram_allocator<std::pair<GIFIdentifier, const GIFInfo>>> AnimatedGIFs =
{
{ GIFIdentifier::Banana, GIFInfo(banana_start, banana_end, 32, 32, 10 ) },
{ GIFIdentifier::Banana, GIFInfo(banana_start, banana_end, 32, 32, 12 ) },
{ GIFIdentifier::Pacman, GIFInfo(pacman_start, pacman_end, 64, 12, 20 ) },
{ GIFIdentifier::Atomic, GIFInfo(atomic_start, atomic_end, 32, 32, 60 ) },
{ GIFIdentifier::ColorSphere, GIFInfo(colorsphere_start, colorsphere_end, 32, 32, 16 ) },
Expand All @@ -107,13 +107,8 @@ static std::map<GIFIdentifier, GIFInfo, std::less<GIFIdentifier>, psram_allocato

struct
{
long _seek = 0;
const uint8_t * _pgif = nullptr;
long _len = 0;
int _offsetX = 0;
int _offsetY = 0;
int _width = 0;
int _height = 0;
byte _fps = 24;
CRGB _bkColor = CRGB::Black;
}
Expand All @@ -138,44 +133,8 @@ class PatternAnimatedGIF : public LEDStripEffect

// GIF decoder callbacks. These are static because the decoder doesn't allow you to pass any context, so they
// have to be global. We use the global g_gifDecoderState to track state. The GifDecoder code calls back to
// these callbacks to do the actual work of fetching the bits from teh embedded GIF file and plotting them on
// the LED matrix.
// these callbacks to do the actual work of plotting them on the LED matrix.

static int fileSizeCallback(void)
{
return g_gifDecoderState._len;
}

// Seek to the given position in the GIF file. The GIF decoder will call this to seek to a position in the GIF file.

static bool fileSeekCallback(unsigned long position)
{
g_gifDecoderState._seek = position;
return true;
}

// Return the current position in the GIF file. The GIF decoder will call this to get the current position.

static unsigned long filePositionCallback(void)
{
return g_gifDecoderState._seek;
}

// Read a byte from the GIF file. The GIF decoder will call this to read the GIF data.

static int fileReadCallback(void)
{
return pgm_read_byte(g_gifDecoderState._pgif + g_gifDecoderState._seek++);
}

// Read N bytes from the GIF file into the buffer. The GIF decoder will call this to read the GIF data.

static int fileReadBlockCallback(void * buffer, int numberOfBytes)
{
memcpy(buffer, g_gifDecoderState._pgif + g_gifDecoderState._seek, numberOfBytes);
g_gifDecoderState._seek += numberOfBytes;
return numberOfBytes;
}

// screenClearCallback - clears the screen with the color given to the constructor

Expand All @@ -189,7 +148,7 @@ class PatternAnimatedGIF : public LEDStripEffect

static void updateScreenCallback(void)
{
debugV("UpdateScreenCallback");
debugV("UpdateScreenCallback from AnimatedGIF decoder.");
}

// drawPixelCallback
Expand Down Expand Up @@ -220,37 +179,6 @@ class PatternAnimatedGIF : public LEDStripEffect
throw new std::runtime_error("drawLineCallback not implemented for animated GIFs");
}

// OpenGif
//
// Fetches the EmbeddedFile for the given GIF index and sets up the GIF decoder to use it

bool OpenGif()
{
auto gif = AnimatedGIFs.find(_gifIndex);
if (gif == AnimatedGIFs.end())
{
debugW("GIF not found by index: %d", to_value(_gifIndex));
return false;
}

uint16_t x, y;
g_ptrGIFDecoder->getSize(&x, &y);

// Set up the gifDecoderState with all of the context that it will need to decode and
// draw the GIF, since the static callbacks will have no other context to work with.

g_gifDecoderState._pgif = gif->second.contents;
g_gifDecoderState._len = gif->second.length;
g_gifDecoderState._offsetX = (MATRIX_WIDTH - gif->second._width) / 2;
g_gifDecoderState._offsetY = (MATRIX_HEIGHT - gif->second._height) / 2;
g_gifDecoderState._width = gif->second._width;
g_gifDecoderState._height = gif->second._height;
g_gifDecoderState._fps = gif->second._fps;
g_gifDecoderState._bkColor = _bkColor;
g_gifDecoderState._seek = 0;

return true;
}

size_t DesiredFramesPerSecond() const override
{
Expand Down Expand Up @@ -294,6 +222,19 @@ class PatternAnimatedGIF : public LEDStripEffect
{
g()->Clear(_bkColor);

// Open the GIF and start decoding

auto gif = AnimatedGIFs.find(_gifIndex);
if (gif == AnimatedGIFs.end())
throw std::runtime_error(str_sprintf("Unable to locate GIF by index %d in the map.", (int) _gifIndex).c_str());

// Set up the gifDecoderState with all of the context that it will need to decode and
// draw the GIF, since the static callbacks will have no other context to work with.

g_gifDecoderState._offsetX = (MATRIX_WIDTH - gif->second._width) / 2;
g_gifDecoderState._offsetY = (MATRIX_HEIGHT - gif->second._height) / 2;
g_gifDecoderState._fps = gif->second._fps;
g_gifDecoderState._bkColor = _bkColor;

// Set the GIF decoder callbacks to our static functions

Expand All @@ -302,17 +243,8 @@ class PatternAnimatedGIF : public LEDStripEffect
g_ptrGIFDecoder->setDrawPixelCallback( drawPixelCallback );
g_ptrGIFDecoder->setDrawLineCallback( drawLineCallback );

g_ptrGIFDecoder->setFileSeekCallback( fileSeekCallback );
g_ptrGIFDecoder->setFilePositionCallback( filePositionCallback );
g_ptrGIFDecoder->setFileReadCallback( fileReadCallback );
g_ptrGIFDecoder->setFileReadBlockCallback( fileReadBlockCallback );
g_ptrGIFDecoder->setFileSizeCallback( fileSizeCallback );

// Open the GIF and start decoding

if (OpenGif())
if (ERROR_NONE != g_ptrGIFDecoder->startDecoding())
debugW("Failed to start decoding GIF");
if (ERROR_NONE != g_ptrGIFDecoder->startDecoding((uint8_t *) gif->second.contents, gif->second.length))
debugW("Failed to start decoding GIF");
}

void Draw() override
Expand All @@ -324,7 +256,7 @@ class PatternAnimatedGIF : public LEDStripEffect
if (_preClear)
g()->Clear(_bkColor);

g_ptrGIFDecoder->decodeFrame(false); /* code */
g_ptrGIFDecoder->decodeFrame(false);
}
};

Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ build_flags = -DMESMERIZER=1
${remote_flags.build_flags}

lib_deps = https://github.com/PlummersSoftwareLLC/SmartMatrix.git
https://github.com/PlummersSoftwareLLC/GifDecoder.git
bitbank2/AnimatedGIF @ ^1.4.7
pixelmatix/GifDecoder @ ^1.1.0

board_build.embed_files = assets/bmp/brokenclouds.jpg
assets/bmp/brokencloudsnight.jpg
Expand Down
25 changes: 12 additions & 13 deletions src/effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,24 +199,23 @@ void LoadEffectFactories()
#elif MESMERIZER

#ifndef EFFECT_SET_VERSION
#define EFFECT_SET_VERSION 4 // Bump version if default set changes in a meaningful way
#define EFFECT_SET_VERSION 5 // Bump version if default set changes in a meaningful way
#endif

ADD_EFFECT(EFFECT_MATRIX_SPECTRUMBAR, SpectrumBarEffect, "Audiograph");
ADD_EFFECT_DISABLED(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Pacman", GIFIdentifier::Pacman);
ADD_EFFECT_DISABLED(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Three Rings", GIFIdentifier::ThreeRings);
ADD_EFFECT_DISABLED(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Atomic", GIFIdentifier::Atomic);
ADD_EFFECT_DISABLED(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Bananadance", GIFIdentifier::Banana, true, CRGB::DarkBlue);

ADD_EFFECT_DISABLED(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Colorball", GIFIdentifier::ColorSphere);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "AudioWave", MATRIX_WIDTH, CRGB(0,0,40), 0, 1.25, 1.25);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum", NUM_BANDS, spectrumBasicColors, false, 100, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "USA", NUM_BANDS, USAColors_p, true, 0, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum 2", 32, spectrumBasicColors, false, 100, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum++", NUM_BANDS, spectrumBasicColors, false, 0, 40, -1.0, 2.0);
ADD_EFFECT(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Pacman", GIFIdentifier::Pacman);
ADD_EFFECT(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Colorball", GIFIdentifier::ColorSphere);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "AudioWave", MATRIX_WIDTH, CRGB(0,0,40), 0, 1.25, 1.25);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum", NUM_BANDS, spectrumBasicColors, false, 100, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "USA", NUM_BANDS, USAColors_p, true, 0, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum 2", 32, spectrumBasicColors, false, 100, 0, 0.75, 0.75);
ADD_EFFECT(EFFECT_MATRIX_SPECTRUM_ANALYZER, SpectrumAnalyzerEffect, "Spectrum++", NUM_BANDS, spectrumBasicColors, false, 0, 40, -1.0, 2.0);
ADD_EFFECT(EFFECT_MATRIX_SMFIRE2021, PatternSMFire2021);
ADD_EFFECT(EFFECT_MATRIX_GHOST_WAVE, GhostWave, "GhostWave", 0, 30, false, 10);
ADD_EFFECT(EFFECT_MATRIX_GHOST_WAVE, GhostWave, "GhostWave", 0, 30, false, 10);
ADD_EFFECT(EFFECT_MATRIX_SMGAMMA, PatternSMGamma);
ADD_EFFECT(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Three Rings", GIFIdentifier::ThreeRings);
ADD_EFFECT(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Atomic", GIFIdentifier::Atomic);
ADD_EFFECT(EFFECT_MATRIX_ANIMATEDGIF, PatternAnimatedGIF, "Bananaman", GIFIdentifier::Banana, true, CRGB::DarkBlue);
ADD_EFFECT(EFFECT_MATRIX_SMMETA_BALLS, PatternSMMetaBalls);
ADD_EFFECT(EFFECT_MATRIX_SMSUPERNOVA, PatternSMSupernova);
ADD_EFFECT(EFFECT_MATRIX_CUBE, PatternCube);
Expand Down

0 comments on commit f61b561

Please sign in to comment.