82 lines
2.9 KiB
C++
82 lines
2.9 KiB
C++
/**
|
|
Animations are structured in AnimationData as follows:
|
|
|
|
.colors contains .color_count*3 uint8_t values for R, G and B.
|
|
|
|
.offsets contains the frame start offsets within .data + the length of the data. (So
|
|
you can always do something like `for (int i=anim.offsets[i]; i<anim.offsets[i+1]; i++)`.
|
|
Accordingly it has a length of .frame_count+1.
|
|
|
|
.data contains all frames data with a run-length compression with escape char 255.
|
|
This data references the index of one or multiple pixels in .colors. It starts at the
|
|
top left pixel and walks each row to the right before starting the next row.
|
|
To decode it: Start at a frame (indicated by .offsets). Get one byte as x.
|
|
If x is <255: This is a single pixel of color x.
|
|
if x is 255: Run-length-encoding. The next byte indicates of often the byte after that
|
|
will be repeated. So, {255, 4, 10} is equal to {10, 10, 10, 10}.
|
|
A special case that may happen in larger GIFs is that there are more than 255 repetitions
|
|
of a color. Those will be split, so 355*color #10 will be: {255, 255, 10, 255, 100, 10},
|
|
e.g. 255*10 + 100*10. Usually this shouldn't need special handling within a decoder.
|
|
Regarding colors in .data:
|
|
Color 0 means "keep the color from the previous frame". This color should never appear on frame #0.
|
|
Color 1 means "show the background color".
|
|
All other color values point to a color in .colors - with an offset of 2.
|
|
So if in .data there's a color 3, paint this pixel in .colors[1].
|
|
|
|
.individual_delays contains either 1 or .frame_count delays. They are given in ms and
|
|
indicate how long the matching frame should be displayed. If all times are equal, then
|
|
it contains only one entry and .individual_delays will be false.
|
|
|
|
.w and .h contain the dimensions of the image.
|
|
**/
|
|
|
|
#pragma once
|
|
#include <Arduino.h>
|
|
#include "prototypes.h"
|
|
#include "my_fastled.h"
|
|
#include "Window.h"
|
|
|
|
class Animation {
|
|
protected:
|
|
unsigned long currentFrameSince;
|
|
uint8_t currentFrame = 0;
|
|
uint8_t* animation_data;
|
|
CRGB** _colors = NULL;
|
|
CRGB* fgColor = NULL;
|
|
CRGB* bgColor = new CRGB(0x000000);
|
|
int8_t xOffset = 0;
|
|
int8_t yOffset = 0;
|
|
uint8_t _startFrame = 0;
|
|
uint8_t _endFrame = 0;
|
|
Window* _window;
|
|
uint8_t _width;
|
|
uint8_t _height;
|
|
uint8_t _frame_count = 0;
|
|
uint8_t _color_count = 0;
|
|
uint16_t* _frame_times = NULL;
|
|
uint16_t* _frame_data_lengths = NULL;
|
|
uint8_t** _frame_data = NULL;
|
|
bool _data_valid = false;
|
|
|
|
virtual CRGB* getColor(uint8_t color_index);
|
|
|
|
void drawPixel(int index, CRGB* color);
|
|
uint16_t getFrameDelay(int frame);
|
|
bool _load_from_file(const char* c);
|
|
public:
|
|
Animation(const char* filename, Window* win);
|
|
void setFgColor(uint32_t c);
|
|
void setBgColor(uint32_t c);
|
|
bool invert();
|
|
void setOffsets(int8_t x, int8_t y);
|
|
void setStartFrame(uint8_t sf);
|
|
void setEndFrame(uint8_t ef);
|
|
void setFrameRange(uint8_t sf, uint8_t ef);
|
|
void setSingleFrame(uint8_t frame);
|
|
virtual ~Animation();
|
|
void draw();
|
|
void drawFrame();
|
|
void drawFrame(uint8_t frame_index);
|
|
virtual bool advance();
|
|
};
|