aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authormrfaptastic <12006953+mrfaptastic@users.noreply.github.com>2020-08-10 21:47:13 +0100
committermrfaptastic <12006953+mrfaptastic@users.noreply.github.com>2020-08-10 21:47:13 +0100
commitb973db14ee0dd967724bd6e9c519f8440e643519 (patch)
tree6a73fcaacaa7280194f4c16f7b2ff5b3dc160bcd /examples
parent1ffce4e60c3f60a7c9662f5b6a5650bed1d16c77 (diff)
Updated GIF example
Diffstat (limited to 'examples')
-rw-r--r--examples/AnimatedGIF/AnimatedGIF.ino136
-rw-r--r--examples/AnimatedGIF/FSBrowser.h179
-rw-r--r--examples/AnimatedGIF/FilenameFunctions.cpp169
-rw-r--r--examples/AnimatedGIF/FilenameFunctions.h21
-rw-r--r--examples/AnimatedGIF/GifDecoder.h148
-rw-r--r--examples/AnimatedGIF/GifDecoder_Impl.h806
-rw-r--r--examples/AnimatedGIF/LICENSE.txt21
-rw-r--r--examples/AnimatedGIF/LzwDecoder_Impl.h169
-rw-r--r--examples/AnimatedGIF/data/Text_Animations.txt.txt1
-rw-r--r--examples/AnimatedGIFPanel/AnimatedGIFPanel.ino (renamed from examples/AnimatedGIFPanel/AnimatedGIFPanel/AnimatedGIFPanel.ino)0
-rw-r--r--examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gifbin44831 -> 0 bytes
-rw-r--r--examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gifbin39645 -> 0 bytes
-rw-r--r--examples/AnimatedGIFPanel/README.md (renamed from examples/AnimatedGIFPanel/AnimatedGIFPanel/README.md)0
-rw-r--r--examples/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif (renamed from examples/AnimatedGIF/data/ezgif.com-pacmn.gif)bin44831 -> 44831 bytes
-rw-r--r--examples/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif (renamed from examples/AnimatedGIF/data/loading.io-64x32px.gif)bin39645 -> 39645 bytes
-rw-r--r--examples/AnimatedGIFPanel/data/gifs/matrix-spin.gif (renamed from examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/matrix-spin.gif)bin174779 -> 174779 bytes
-rw-r--r--examples/AnimatedGIFPanel/data/gifs/shock.gif (renamed from examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/shock.gif)bin46806 -> 46806 bytes
17 files changed, 0 insertions, 1650 deletions
diff --git a/examples/AnimatedGIF/AnimatedGIF.ino b/examples/AnimatedGIF/AnimatedGIF.ino
deleted file mode 100644
index a5830d2..0000000
--- a/examples/AnimatedGIF/AnimatedGIF.ino
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Written by: Craig A. Lindley
- *
- * Copyright (c) 2014 Craig A. Lindley
- * Refactoring by Louis Beaudoin (Pixelmatix)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <ESP32-RGB64x32MatrixPanel-I2S-DMA.h>
-#include <SPIFFS.h>
-#include <Arduino.h>
-
-RGB64x32MatrixPanel_I2S_DMA matrix;
-
-
-#include "GifDecoder.h"
-#include "FilenameFunctions.h"
-
-/* GIF files for this particular example need to be put into the 'data' directoy of the
- * sketch and saved to the ESP32 using the "ESP32 Sketch Data Upload" tool in Arduino.
- *
- * URL: https://github.com/me-no-dev/arduino-esp32fs-plugin
- *
- */
-#define GIF_DIRECTORY "/"
-#define DISPLAY_TIME_SECONDS 5
-
-// Gif sizes should match exactly that of the RGB Matrix display.
-const uint8_t GIFWidth = 64;
-const uint8_t GIFHeight = 32;
-
-/* template parameters are maxGifWidth, maxGifHeight, lzwMaxBits
- *
- * The lzwMaxBits value of 12 supports all GIFs, but uses 16kB RAM
- * lzwMaxBits can be set to 10 or 11 for small displays, 12 for large displays
- * All 32x32-pixel GIFs tested work with 11, most work with 10
- */
-GifDecoder<GIFWidth, GIFHeight, 12> decoder;
-
-int num_files;
-
-void screenClearCallback(void) {
- //matrix.fillScreen(matrix.color565(0,0,0));
-}
-
-void updateScreenCallback(void) {
- //backgroundLayer.swapBuffers();
-}
-
-void drawPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) {
- matrix.drawPixelRGB888(x, y, red, green, blue);
-}
-
-// Setup method runs once, when the sketch starts
-void setup() {
-
- Serial.begin(115200);
- Serial.println("Starting AnimatedGIFs Sketch");
-
- // Start filesystem
- Serial.println(" * Loading SPIFFS");
- if(!SPIFFS.begin()){
- Serial.println("SPIFFS Mount Failed");
- }
-
- decoder.setScreenClearCallback(screenClearCallback);
- decoder.setUpdateScreenCallback(updateScreenCallback);
- decoder.setDrawPixelCallback(drawPixelCallback);
-
- decoder.setFileSeekCallback(fileSeekCallback);
- decoder.setFilePositionCallback(filePositionCallback);
- decoder.setFileReadCallback(fileReadCallback);
- decoder.setFileReadBlockCallback(fileReadBlockCallback);
-
-
-
- matrix.begin();
-
- // Clear screen
- matrix.fillScreen(matrix.color565(0,0,0));
-
- // Determine how many animated GIF files exist
- num_files = enumerateGIFFiles(GIF_DIRECTORY, false);
-
- if(num_files < 0) {
- Serial.println("No gifs directory");
- while(1);
- }
-
- if(!num_files) {
- Serial.println("Empty gifs directory");
- while(1);
- }
-}
-
-int file_index = -1;
-void loop() {
- static unsigned long futureTime;
-
- // int index = -1; //random(num_files);
-
- if(futureTime < millis()) {
- if (++file_index >= num_files) {
- file_index = 0;
- }
-
- if (openGifFilenameByIndex(GIF_DIRECTORY, file_index) >= 0) {
- // Can clear screen for new animation here, but this might cause flicker with short animations
- // matrix.fillScreen(COLOR_BLACK);
- // matrix.swapBuffers();
-
- decoder.startDecoding();
-
- // Calculate time in the future to terminate animation
- futureTime = millis() + (DISPLAY_TIME_SECONDS * 1000);
- }
- }
-
- decoder.decodeFrame();
-}
diff --git a/examples/AnimatedGIF/FSBrowser.h b/examples/AnimatedGIF/FSBrowser.h
deleted file mode 100644
index c380226..0000000
--- a/examples/AnimatedGIF/FSBrowser.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// ADAPTED FROM: https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/FSBrowser/FSBrowser.ino
-
-#define FILESYSTEM SPIFFS
-#define FORMAT_FILESYSTEM true
-#define DBG_OUTPUT_PORT Serial
-
-
-//holds the current upload
-File fsUploadFile;
-
-//format bytes
-String formatBytes(size_t bytes) {
- if (bytes < 1024) {
- return String(bytes) + "B";
- } else if (bytes < (1024 * 1024)) {
- return String(bytes / 1024.0) + "KB";
- } else if (bytes < (1024 * 1024 * 1024)) {
- return String(bytes / 1024.0 / 1024.0) + "MB";
- } else {
- return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
- }
-}
-
-String getContentType(String filename) {
- if (webServer.hasArg("download")) {
- return "application/octet-stream";
- } else if (filename.endsWith(".htm")) {
- return "text/html";
- } else if (filename.endsWith(".html")) {
- return "text/html";
- } else if (filename.endsWith(".css")) {
- return "text/css";
- } else if (filename.endsWith(".js")) {
- return "application/javascript";
- } else if (filename.endsWith(".png")) {
- return "image/png";
- } else if (filename.endsWith(".gif")) {
- return "image/gif";
- } else if (filename.endsWith(".jpg")) {
- return "image/jpeg";
- } else if (filename.endsWith(".ico")) {
- return "image/x-icon";
- } else if (filename.endsWith(".xml")) {
- return "text/xml";
- } else if (filename.endsWith(".pdf")) {
- return "application/x-pdf";
- } else if (filename.endsWith(".zip")) {
- return "application/x-zip";
- } else if (filename.endsWith(".gz")) {
- return "application/x-gzip";
- }
- return "text/plain";
-}
-
-bool exists(String path){
- bool yes = false;
- File file = FILESYSTEM.open(path, "r");
- if(!file.isDirectory()){
- yes = true;
- }
- file.close();
- return yes;
-}
-
-bool handleFileRead(String path) {
- DBG_OUTPUT_PORT.println("handleFileRead: " + path);
- if (path.endsWith("/")) {
- path += "index.htm";
- }
- String contentType = getContentType(path);
- String pathWithGz = path + ".gz";
- if (exists(pathWithGz) || exists(path)) {
- if (exists(pathWithGz)) {
- path += ".gz";
- }
- File file = FILESYSTEM.open(path, "r");
- webServer.streamFile(file, contentType);
- file.close();
- return true;
- }
- return false;
-}
-
-void handleFileUpload() {
- if (webServer.uri() != "/edit") {
- return;
- }
- HTTPUpload& upload = webServer.upload();
- if (upload.status == UPLOAD_FILE_START) {
- String filename = upload.filename;
- if (!filename.startsWith("/")) {
- filename = "/" + filename;
- }
- DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
- fsUploadFile = FILESYSTEM.open(filename, "w");
- filename = String();
- } else if (upload.status == UPLOAD_FILE_WRITE) {
- //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
- if (fsUploadFile) {
- fsUploadFile.write(upload.buf, upload.currentSize);
- }
- } else if (upload.status == UPLOAD_FILE_END) {
- if (fsUploadFile) {
- fsUploadFile.close();
- }
- DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
- }
-}
-
-void handleFileDelete() {
- if (webServer.args() == 0) {
- return webServer.send(500, "text/plain", "BAD ARGS");
- }
- String path = webServer.arg(0);
- DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
- if (path == "/") {
- return webServer.send(500, "text/plain", "BAD PATH");
- }
- if (!exists(path)) {
- return webServer.send(404, "text/plain", "FileNotFound");
- }
- FILESYSTEM.remove(path);
- webServer.send(200, "text/plain", "");
- path = String();
-}
-
-void handleFileCreate() {
- if (webServer.args() == 0) {
- return webServer.send(500, "text/plain", "BAD ARGS");
- }
- String path = webServer.arg(0);
- DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
- if (path == "/") {
- return webServer.send(500, "text/plain", "BAD PATH");
- }
- if (exists(path)) {
- return webServer.send(500, "text/plain", "FILE EXISTS");
- }
- File file = FILESYSTEM.open(path, "w");
- if (file) {
- file.close();
- } else {
- return webServer.send(500, "text/plain", "CREATE FAILED");
- }
- webServer.send(200, "text/plain", "");
- path = String();
-}
-
-void handleFileList() {
- if (!webServer.hasArg("dir")) {
- webServer.send(500, "text/plain", "BAD ARGS");
- return;
- }
-
- String path = webServer.arg("dir");
- DBG_OUTPUT_PORT.println("handleFileList: " + path);
-
-
- File root = FILESYSTEM.open(path);
- path = String();
-
- String output = "[";
- if(root.isDirectory()){
- File file = root.openNextFile();
- while(file){
- if (output != "[") {
- output += ',';
- }
- output += "{\"type\":\"";
- output += (file.isDirectory()) ? "dir" : "file";
- output += "\",\"name\":\"";
- output += String(file.name()).substring(1);
- output += "\"}";
- file = root.openNextFile();
- }
- }
- output += "]";
- webServer.send(200, "text/json", output);
-}
diff --git a/examples/AnimatedGIF/FilenameFunctions.cpp b/examples/AnimatedGIF/FilenameFunctions.cpp
deleted file mode 100644
index e8a8f04..0000000
--- a/examples/AnimatedGIF/FilenameFunctions.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Animated GIFs Display Code for SmartMatrix and 32x32 RGB LED Panels
- *
- * This file contains code to enumerate and select animated GIF files by name
- *
- * Written by: Craig A. Lindley
- *
- * Other references: https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/FSBrowser/FSBrowser.ino
- *
- */
-
-#include "FilenameFunctions.h"
-
-File file;
-
-int numberOfFiles;
-
-bool fileSeekCallback(unsigned long position) {
- return file.seek(position);
-}
-
-unsigned long filePositionCallback(void) {
- return file.position();
-}
-
-int fileReadCallback(void) {
- return file.read();
-}
-
-int fileReadBlockCallback(void * buffer, int numberOfBytes) {
- return file.read((uint8_t*)buffer, numberOfBytes);
-}
-
-bool isAnimationFile(const char filename []) {
- String filenameString(filename);
-
-#if defined(ESP32)
- // ESP32 filename includes the full path, so need to remove the path before looking at the filename
- int pathindex = filenameString.lastIndexOf("/");
- if(pathindex >= 0)
- filenameString.remove(0, pathindex + 1);
-#endif
-
- DBG_OUTPUT_PORT.print(filenameString);
-
- if ((filenameString[0] == '_') || (filenameString[0] == '~') || (filenameString[0] == '.')) {
- DBG_OUTPUT_PORT.println(" ignoring: leading _/~/. character");
- return false;
- }
-
- filenameString.toUpperCase();
- if (filenameString.endsWith(".GIF") != 1) {
- DBG_OUTPUT_PORT.println(" ignoring: doesn't end of .GIF");
- return false;
- }
-
- DBG_OUTPUT_PORT.println();
-
- return true;
-}
-
-// Enumerate and possibly display the animated GIF filenames in GIFS directory
-int enumerateGIFFiles(const char *directoryName, boolean displayFilenames) {
-
- numberOfFiles = 0;
-
- File directory = FILESYSTEM.open(directoryName);
- if (!directory) {
- return -1;
- }
-
- File file = directory.openNextFile();
- while (file) {
- if (isAnimationFile(file.name())) {
- numberOfFiles++;
- if (displayFilenames) {
- DBG_OUTPUT_PORT.println(file.name());
- }
- }
- file.close();
- file = directory.openNextFile();
- }
-
- file.close();
- directory.close();
-
- return numberOfFiles;
-}
-
-// Get the full path/filename of the GIF file with specified index
-void getGIFFilenameByIndex(const char *directoryName, int index, char *pnBuffer) {
-
- char* filename;
-
- // Make sure index is in range
- if ((index < 0) || (index >= numberOfFiles))
- return;
-
- File directory = FILESYSTEM.open(directoryName);
- if (!directory)
- return;
-
- File file = directory.openNextFile();
- while (file && (index >= 0)) {
- filename = (char*)file.name();
-
- if (isAnimationFile(file.name())) {
- index--;
-
-#if !defined(ESP32)
- // Copy the directory name into the pathname buffer - ESP32 SD Library includes the full path name in the filename, so no need to add the directory name
- strcpy(pnBuffer, directoryName);
- // Append the filename to the pathname
- strcat(pnBuffer, filename);
-#else
- strcpy(pnBuffer, filename);
-#endif
- }
-
- file.close();
- file = directory.openNextFile();
- }
-
- file.close();
- directory.close();
-}
-
-int openGifFilenameByIndex(const char *directoryName, int index) {
- char pathname[30]; // long filename will break this... Smash the stack! i.e:
- /*
- * Stack smashing protect failure!
- *
- * abort() was called at PC 0x400d9a90 on core 1
- *
- * Backtrace: 0x40088578:0x3ffb1ec0 0x4008877b:0x3ffb1ee0 0x400d9a90:0x3ffb1f00 0x400d1d62:0x3ffb1f20 0x400d182f:0x3ffb1f80 0x400ef86e:0x3ffb1fa0
- *
- * Rebooting...
-
- */
-
- getGIFFilenameByIndex(directoryName, index, pathname);
-
- DBG_OUTPUT_PORT.print("Pathname: ");
- DBG_OUTPUT_PORT.println(pathname);
-
- if(file)
- {
- file.close();
- DBG_OUTPUT_PORT.print("Closing old file...");
- }
-
- // Attempt to open the file for reading
- DBG_OUTPUT_PORT.print("Opening new file...");
- file = FILESYSTEM.open(pathname);
- if (!file) {
- DBG_OUTPUT_PORT.println("Error opening GIF file");
- return -1;
- }
-
- return 0;
-}
-
-
-// Return a random animated gif path/filename from the specified directory
-void chooseRandomGIFFilename(const char *directoryName, char *pnBuffer) {
-
- int index = random(numberOfFiles);
- getGIFFilenameByIndex(directoryName, index, pnBuffer);
-}
diff --git a/examples/AnimatedGIF/FilenameFunctions.h b/examples/AnimatedGIF/FilenameFunctions.h
deleted file mode 100644
index 2c92c10..0000000
--- a/examples/AnimatedGIF/FilenameFunctions.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef FILENAME_FUNCTIONS_H
-#define FILENAME_FUNCTIONS_H
-
-#include "FS.h" // for the 'File' class
-#include <SPIFFS.h>
-
-
-#define FILESYSTEM SPIFFS
-#define DBG_OUTPUT_PORT Serial
-
-
-int enumerateGIFFiles(const char *directoryName, boolean displayFilenames);
-void getGIFFilenameByIndex(const char *directoryName, int index, char *pnBuffer);
-int openGifFilenameByIndex(const char *directoryName, int index);
-
-bool fileSeekCallback(unsigned long position);
-unsigned long filePositionCallback(void);
-int fileReadCallback(void);
-int fileReadBlockCallback(void * buffer, int numberOfBytes);
-
-#endif
diff --git a/examples/AnimatedGIF/GifDecoder.h b/examples/AnimatedGIF/GifDecoder.h
deleted file mode 100644
index 8a3d14a..0000000
--- a/examples/AnimatedGIF/GifDecoder.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef _GIFDECODER_H_
-#define _GIFDECODER_H_
-
-#include <stdint.h>
-#include <Arduino.h>
-
-
-typedef void (*callback)(void);
-typedef void (*pixel_callback)(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue);
-typedef void* (*get_buffer_callback)(void);
-
-typedef bool (*file_seek_callback)(unsigned long position);
-typedef unsigned long (*file_position_callback)(void);
-typedef int (*file_read_callback)(void);
-typedef int (*file_read_block_callback)(void * buffer, int numberOfBytes);
-
-// LZW constants
-// NOTE: LZW_MAXBITS should be set to 10 or 11 for small displays, 12 for large displays
-// all 32x32-pixel GIFs tested work with 11, most work with 10
-// LZW_MAXBITS = 12 will support all GIFs, but takes 16kB RAM
-#define LZW_SIZTABLE (1 << lzwMaxBits)
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-class GifDecoder {
-public:
- int startDecoding(void);
- int decodeFrame(void);
-
- void setScreenClearCallback(callback f);
- void setUpdateScreenCallback(callback f);
- void setDrawPixelCallback(pixel_callback f);
- void setStartDrawingCallback(callback f);
-
- void setFileSeekCallback(file_seek_callback f);
- void setFilePositionCallback(file_position_callback f);
- void setFileReadCallback(file_read_callback f);
- void setFileReadBlockCallback(file_read_block_callback f);
-
-private:
- void parseTableBasedImage(void);
- void decompressAndDisplayFrame(unsigned long filePositionAfter);
- int parseData(void);
- int parseGIFFileTerminator(void);
- void parseCommentExtension(void);
- void parseApplicationExtension(void);
- void parseGraphicControlExtension(void);
- void parsePlainTextExtension(void);
- void parseGlobalColorTable(void);
- void parseLogicalScreenDescriptor(void);
- bool parseGifHeader(void);
- void copyImageDataRect(uint8_t *dst, uint8_t *src, int x, int y, int width, int height);
- void fillImageData(uint8_t colorIndex);
- void fillImageDataRect(uint8_t colorIndex, int x, int y, int width, int height);
- int readIntoBuffer(void *buffer, int numberOfBytes);
- int readWord(void);
- void backUpStream(int n);
- int readByte(void);
-
- void lzw_decode_init(int csize);
- int lzw_decode(uint8_t *buf, int len, uint8_t *bufend);
- void lzw_setTempBuffer(uint8_t * tempBuffer);
- int lzw_get_code(void);
-
- // Logical screen descriptor attributes
- int lsdWidth;
- int lsdHeight;
- int lsdPackedField;
- int lsdAspectRatio;
- int lsdBackgroundIndex;
-
- // Table based image attributes
- int tbiImageX;
- int tbiImageY;
- int tbiWidth;
- int tbiHeight;
- int tbiPackedBits;
- bool tbiInterlaced;
-
- int frameDelay;
- int transparentColorIndex;
- int prevBackgroundIndex;
- int prevDisposalMethod;
- int disposalMethod;
- int lzwCodeSize;
- bool keyFrame;
- int rectX;
- int rectY;
- int rectWidth;
- int rectHeight;
-
- unsigned long nextFrameTime_ms;
-
- int colorCount;
- rgb_24 palette[256];
-
- char tempBuffer[260];
-
- // Buffer image data is decoded into
- uint8_t imageData[maxGifWidth * maxGifHeight];
-
- // Backup image data buffer for saving portions of image disposal method == 3
- uint8_t imageDataBU[maxGifWidth * maxGifHeight];
-
- callback screenClearCallback;
- callback updateScreenCallback;
- pixel_callback drawPixelCallback;
- callback startDrawingCallback;
- file_seek_callback fileSeekCallback;
- file_position_callback filePositionCallback;
- file_read_callback fileReadCallback;
- file_read_block_callback fileReadBlockCallback;
-
- // LZW variables
- int bbits;
- int bbuf;
- int cursize; // The current code size
- int curmask;
- int codesize;
- int clear_code;
- int end_code;
- int newcodes; // First available code
- int top_slot; // Highest code for current size
- int extra_slot;
- int slot; // Last read code
- int fc, oc;
- int bs; // Current buffer size for GIF
- int bcnt;
- uint8_t *sp;
- uint8_t * temp_buffer;
-
- uint8_t stack [LZW_SIZTABLE];
- uint8_t suffix [LZW_SIZTABLE];
- uint16_t prefix [LZW_SIZTABLE];
-
- // Masks for 0 .. 16 bits
- unsigned int mask[17] = {
- 0x0000, 0x0001, 0x0003, 0x0007,
- 0x000F, 0x001F, 0x003F, 0x007F,
- 0x00FF, 0x01FF, 0x03FF, 0x07FF,
- 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
- 0xFFFF
- };
-};
-
-#include "GifDecoder_Impl.h"
-#include "LzwDecoder_Impl.h"
-
-#endif
diff --git a/examples/AnimatedGIF/GifDecoder_Impl.h b/examples/AnimatedGIF/GifDecoder_Impl.h
deleted file mode 100644
index c7c5a5d..0000000
--- a/examples/AnimatedGIF/GifDecoder_Impl.h
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- * This file contains code to parse animated GIF files
- *
- * Written by: Craig A. Lindley
- *
- * Copyright (c) 2014 Craig A. Lindley
- * Minor modifications by Louis Beaudoin (pixelmatix)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define GIFDEBUG 0
-
-// This file contains C code, and ESP32 Arduino has changed to use the C++ template version of min()/max() which we can't use with C, so we can't depend on a #define min() from Arduino anymore
-#ifndef min
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif
-
-#include "GifDecoder.h"
-
-#if GIFDEBUG == 1
-#define DEBUG_SCREEN_DESCRIPTOR 1
-#define DEBUG_GLOBAL_COLOR_TABLE 1
-#define DEBUG_PROCESSING_PLAIN_TEXT_EXT 1
-#define DEBUG_PROCESSING_GRAPHIC_CONTROL_EXT 1
-#define DEBUG_PROCESSING_APP_EXT 1
-#define DEBUG_PROCESSING_COMMENT_EXT 1
-#define DEBUG_PROCESSING_FILE_TERM 1
-#define DEBUG_PROCESSING_TABLE_IMAGE_DESC 1
-#define DEBUG_PROCESSING_TBI_DESC_START 1
-#define DEBUG_PROCESSING_TBI_DESC_INTERLACED 1
-#define DEBUG_PROCESSING_TBI_DESC_LOCAL_COLOR_TABLE 1
-#define DEBUG_PROCESSING_TBI_DESC_LZWCODESIZE 1
-#define DEBUG_PROCESSING_TBI_DESC_DATABLOCKSIZE 1
-#define DEBUG_PROCESSING_TBI_DESC_LZWIMAGEDATA_OVERFLOW 1
-#define DEBUG_PROCESSING_TBI_DESC_LZWIMAGEDATA_SIZE 1
-#define DEBUG_PARSING_DATA 1
-#define DEBUG_DECOMPRESS_AND_DISPLAY 1
-
-#define DEBUG_WAIT_FOR_KEY_PRESS 0
-
-#endif
-
-#include "GifDecoder.h"
-
-
-// Error codes
-#define ERROR_NONE 0
-#define ERROR_DONE_PARSING 1
-#define ERROR_WAITING 2
-#define ERROR_FILEOPEN -1
-#define ERROR_FILENOTGIF -2
-#define ERROR_BADGIFFORMAT -3
-#define ERROR_UNKNOWNCONTROLEXT -4
-
-#define GIFHDRTAGNORM "GIF87a" // tag in valid GIF file
-#define GIFHDRTAGNORM1 "GIF89a" // tag in valid GIF file
-#define GIFHDRSIZE 6
-
-// Global GIF specific definitions
-#define COLORTBLFLAG 0x80
-#define INTERLACEFLAG 0x40
-#define TRANSPARENTFLAG 0x01
-
-#define NO_TRANSPARENT_INDEX -1
-
-// Disposal methods
-#define DISPOSAL_NONE 0
-#define DISPOSAL_LEAVE 1
-#define DISPOSAL_BACKGROUND 2
-#define DISPOSAL_RESTORE 3
-
-
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setStartDrawingCallback(callback f) {
- startDrawingCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setUpdateScreenCallback(callback f) {
- updateScreenCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setDrawPixelCallback(pixel_callback f) {
- drawPixelCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setScreenClearCallback(callback f) {
- screenClearCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setFileSeekCallback(file_seek_callback f) {
- fileSeekCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setFilePositionCallback(file_position_callback f) {
- filePositionCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setFileReadCallback(file_read_callback f) {
- fileReadCallback = f;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::setFileReadBlockCallback(file_read_block_callback f) {
- fileReadBlockCallback = f;
-}
-
-// Backup the read stream by n bytes
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::backUpStream(int n) {
- fileSeekCallback(filePositionCallback() - n);
-}
-
-// Read a file byte
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::readByte() {
-
- int b = fileReadCallback();
- if (b == -1) {
-#if GIFDEBUG == 1
- Serial.println("Read error or EOF occurred");
-#endif
- }
- return b;
-}
-
-// Read a file word
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::readWord() {
-
- int b0 = readByte();
- int b1 = readByte();
- return (b1 << 8) | b0;
-}
-
-// Read the specified number of bytes into the specified buffer
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::readIntoBuffer(void *buffer, int numberOfBytes) {
-
- int result = fileReadBlockCallback(buffer, numberOfBytes);
- if (result == -1) {
- Serial.println("Read error or EOF occurred");
- }
- return result;
-}
-
-// Fill a portion of imageData buffer with a color index
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::fillImageDataRect(uint8_t colorIndex, int x, int y, int width, int height) {
-
- int yOffset;
-
- for (int yy = y; yy < height + y; yy++) {
- yOffset = yy * maxGifWidth;
- for (int xx = x; xx < width + x; xx++) {
- imageData[yOffset + xx] = colorIndex;
- }
- }
-}
-
-// Fill entire imageData buffer with a color index
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::fillImageData(uint8_t colorIndex) {
-
- memset(imageData, colorIndex, sizeof(imageData));
-}
-
-// Copy image data in rect from a src to a dst
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::copyImageDataRect(uint8_t *dst, uint8_t *src, int x, int y, int width, int height) {
-
- int yOffset, offset;
-
- for (int yy = y; yy < height + y; yy++) {
- yOffset = yy * maxGifWidth;
- for (int xx = x; xx < width + x; xx++) {
- offset = yOffset + xx;
- dst[offset] = src[offset];
- }
- }
-}
-
-// Make sure the file is a Gif file
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-bool GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseGifHeader() {
-
- char buffer[10];
-
- readIntoBuffer(buffer, GIFHDRSIZE);
- if ((strncmp(buffer, GIFHDRTAGNORM, GIFHDRSIZE) != 0) &&
- (strncmp(buffer, GIFHDRTAGNORM1, GIFHDRSIZE) != 0)) {
- return false;
- }
- else {
- return true;
- }
-}
-
-// Parse the logical screen descriptor
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseLogicalScreenDescriptor() {
-
- lsdWidth = readWord();
- lsdHeight = readWord();
- lsdPackedField = readByte();
- lsdBackgroundIndex = readByte();
- lsdAspectRatio = readByte();
-
-#if GIFDEBUG == 1 && DEBUG_SCREEN_DESCRIPTOR == 1
- Serial.print("lsdWidth: ");
- Serial.println(lsdWidth);
- Serial.print("lsdHeight: ");
- Serial.println(lsdHeight);
- Serial.print("lsdPackedField: ");
- Serial.println(lsdPackedField, HEX);
- Serial.print("lsdBackgroundIndex: ");
- Serial.println(lsdBackgroundIndex);
- Serial.print("lsdAspectRatio: ");
- Serial.println(lsdAspectRatio);
-#endif
-}
-
-// Parse the global color table
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseGlobalColorTable() {
-
- // Does a global color table exist?
- if (lsdPackedField & COLORTBLFLAG) {
-
- // A GCT was present determine how many colors it contains
- colorCount = 1 << ((lsdPackedField & 7) + 1);
-
-#if GIFDEBUG == 1 && DEBUG_GLOBAL_COLOR_TABLE == 1
- Serial.print("Global color table with ");
- Serial.print(colorCount);
- Serial.println(" colors present");
-#endif
- // Read color values into the palette array
- int colorTableBytes = sizeof(rgb_24) * colorCount;
- readIntoBuffer(palette, colorTableBytes);
- }
-}
-
-// Parse plain text extension and dispose of it
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parsePlainTextExtension() {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_PLAIN_TEXT_EXT == 1
- Serial.println("\nProcessing Plain Text Extension");
-#endif
- // Read plain text header length
- uint8_t len = readByte();
-
- // Consume plain text header data
- readIntoBuffer(tempBuffer, len);
-
- // Consume the plain text data in blocks
- len = readByte();
- while (len != 0) {
- readIntoBuffer(tempBuffer, len);
- len = readByte();
- }
-}
-
-// Parse a graphic control extension
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseGraphicControlExtension() {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_GRAPHIC_CONTROL_EXT == 1
- Serial.println("\nProcessing Graphic Control Extension");
-#endif
- int len = readByte(); // Check length
- if (len != 4) {
- Serial.println("Bad graphic control extension");
- }
-
- int packedBits = readByte();
- frameDelay = readWord();
- transparentColorIndex = readByte();
-
- if ((packedBits & TRANSPARENTFLAG) == 0) {
- // Indicate no transparent index
- transparentColorIndex = NO_TRANSPARENT_INDEX;
- }
- disposalMethod = (packedBits >> 2) & 7;
- if (disposalMethod > 3) {
- disposalMethod = 0;
- Serial.println("Invalid disposal value");
- }
-
- readByte(); // Toss block end
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_GRAPHIC_CONTROL_EXT == 1
- Serial.print("PacketBits: ");
- Serial.println(packedBits, HEX);
- Serial.print("Frame delay: ");
- Serial.println(frameDelay);
- Serial.print("transparentColorIndex: ");
- Serial.println(transparentColorIndex);
- Serial.print("disposalMethod: ");
- Serial.println(disposalMethod);
-#endif
-}
-
-// Parse application extension
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseApplicationExtension() {
-
- memset(tempBuffer, 0, sizeof(tempBuffer));
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_APP_EXT == 1
- Serial.println("\nProcessing Application Extension");
-#endif
-
- // Read block length
- uint8_t len = readByte();
-
- // Read app data
- readIntoBuffer(tempBuffer, len);
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_APP_EXT == 1
- // Conditionally display the application extension string
- if (strlen(tempBuffer) != 0) {
- Serial.print("Application Extension: ");
- Serial.println(tempBuffer);
- }
-#endif
-
- // Consume any additional app data
- len = readByte();
- while (len != 0) {
- readIntoBuffer(tempBuffer, len);
- len = readByte();
- }
-}
-
-// Parse comment extension
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseCommentExtension() {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_COMMENT_EXT == 1
- Serial.println("\nProcessing Comment Extension");
-#endif
-
- // Read block length
- uint8_t len = readByte();
- while (len != 0) {
- // Clear buffer
- memset(tempBuffer, 0, sizeof(tempBuffer));
-
- // Read len bytes into buffer
- readIntoBuffer(tempBuffer, len);
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_COMMENT_EXT == 1
- // Display the comment extension string
- if (strlen(tempBuffer) != 0) {
- Serial.print("Comment Extension: ");
- Serial.println(tempBuffer);
- }
-#endif
- // Read the new block length
- len = readByte();
- }
-}
-
-// Parse file terminator
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseGIFFileTerminator() {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_FILE_TERM == 1
- Serial.println("\nProcessing file terminator");
-#endif
-
- uint8_t b = readByte();
- if (b != 0x3B) {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_FILE_TERM == 1
- Serial.print("Terminator byte: ");
- Serial.println(b, HEX);
-#endif
- Serial.println("Bad GIF file format - Bad terminator");
- return ERROR_BADGIFFORMAT;
- }
- else {
- return ERROR_NONE;
- }
-}
-
-// Parse table based image data
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseTableBasedImage() {
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_START == 1
- Serial.println("\nProcessing Table Based Image Descriptor");
-#endif
-
-#if GIFDEBUG == 1 && DEBUG_PARSING_DATA == 1
- Serial.println("File Position: ");
- Serial.println(filePositionCallback());
- Serial.println("File Size: ");
- //Serial.println(file.size());
-#endif
-
- // Parse image descriptor
- tbiImageX = readWord();
- tbiImageY = readWord();
- tbiWidth = readWord();
- tbiHeight = readWord();
- tbiPackedBits = readByte();
-
-#if GIFDEBUG == 1
- Serial.print("tbiImageX: ");
- Serial.println(tbiImageX);
- Serial.print("tbiImageY: ");
- Serial.println(tbiImageY);
- Serial.print("tbiWidth: ");
- Serial.println(tbiWidth);
- Serial.print("tbiHeight: ");
- Serial.println(tbiHeight);
- Serial.print("PackedBits: ");
- Serial.println(tbiPackedBits, HEX);
-#endif
-
- // Is this image interlaced ?
- tbiInterlaced = ((tbiPackedBits & INTERLACEFLAG) != 0);
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_INTERLACED == 1
- Serial.print("Image interlaced: ");
- Serial.println((tbiInterlaced != 0) ? "Yes" : "No");
-#endif
-
- // Does this image have a local color table ?
- bool localColorTable = ((tbiPackedBits & COLORTBLFLAG) != 0);
-
- if (localColorTable) {
- int colorBits = ((tbiPackedBits & 7) + 1);
- colorCount = 1 << colorBits;
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_LOCAL_COLOR_TABLE == 1
- Serial.print("Local color table with ");
- Serial.print(colorCount);
- Serial.println(" colors present");
-#endif
- // Read colors into palette
- int colorTableBytes = sizeof(rgb_24) * colorCount;
- readIntoBuffer(palette, colorTableBytes);
- }
-
- // One time initialization of imageData before first frame
- if (keyFrame) {
- if (transparentColorIndex == NO_TRANSPARENT_INDEX) {
- fillImageData(lsdBackgroundIndex);
- }
- else {
- fillImageData(transparentColorIndex);
- }
- keyFrame = false;
-
- rectX = 0;
- rectY = 0;
- rectWidth = maxGifWidth;
- rectHeight = maxGifHeight;
- }
- // Don't clear matrix screen for these disposal methods
- if ((prevDisposalMethod != DISPOSAL_NONE) && (prevDisposalMethod != DISPOSAL_LEAVE)) {
- if(screenClearCallback)
- (*screenClearCallback)();
- }
-
- // Process previous disposal method
- if (prevDisposalMethod == DISPOSAL_BACKGROUND) {
- // Fill portion of imageData with previous background color
- fillImageDataRect(prevBackgroundIndex, rectX, rectY, rectWidth, rectHeight);
- }
- else if (prevDisposalMethod == DISPOSAL_RESTORE) {
- copyImageDataRect(imageData, imageDataBU, rectX, rectY, rectWidth, rectHeight);
- }
-
- // Save disposal method for this frame for next time
- prevDisposalMethod = disposalMethod;
-
- if (disposalMethod != DISPOSAL_NONE) {
- // Save dimensions of this frame
- rectX = tbiImageX;
- rectY = tbiImageY;
- rectWidth = tbiWidth;
- rectHeight = tbiHeight;
-
- // limit rectangle to the bounds of maxGifWidth*maxGifHeight
- if(rectX + rectWidth > maxGifWidth)
- rectWidth = maxGifWidth-rectX;
- if(rectY + rectHeight > maxGifHeight)
- rectHeight = maxGifHeight-rectY;
- if(rectX >= maxGifWidth || rectY >= maxGifHeight) {
- rectX = rectY = rectWidth = rectHeight = 0;
- }
-
- if (disposalMethod == DISPOSAL_BACKGROUND) {
- if (transparentColorIndex != NO_TRANSPARENT_INDEX) {
- prevBackgroundIndex = transparentColorIndex;
- }
- else {
- prevBackgroundIndex = lsdBackgroundIndex;
- }
- }
- else if (disposalMethod == DISPOSAL_RESTORE) {
- copyImageDataRect(imageDataBU, imageData, rectX, rectY, rectWidth, rectHeight);
- }
- }
-
- // Read the min LZW code size
- lzwCodeSize = readByte();
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_LZWCODESIZE == 1
- Serial.print("LzwCodeSize: ");
- Serial.println(lzwCodeSize);
- Serial.println("File Position Before: ");
- Serial.println(filePositionCallback());
-#endif
-
- unsigned long filePositionBefore = filePositionCallback();
-
- // Gather the lzw image data
- // NOTE: the dataBlockSize byte is left in the data as the lzw decoder needs it
- int offset = 0;
- int dataBlockSize = readByte();
- while (dataBlockSize != 0) {
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_DATABLOCKSIZE == 1
- Serial.print("dataBlockSize: ");
- Serial.println(dataBlockSize);
-#endif
- backUpStream(1);
- dataBlockSize++;
- fileSeekCallback(filePositionCallback() + dataBlockSize);
-
- offset += dataBlockSize;
- dataBlockSize = readByte();
- }
-
-#if GIFDEBUG == 1 && DEBUG_PROCESSING_TBI_DESC_LZWIMAGEDATA_SIZE == 1
- Serial.print("total lzwImageData Size: ");
- Serial.println(offset);
- Serial.println("File Position Test: ");
- Serial.println(filePositionCallback());
-#endif
-
- // this is the position where GIF decoding needs to pick up after decompressing frame
- unsigned long filePositionAfter = filePositionCallback();
-
- fileSeekCallback(filePositionBefore);
-
- // Process the animation frame for display
-
- // Initialize the LZW decoder for this frame
- lzw_decode_init(lzwCodeSize);
- lzw_setTempBuffer((uint8_t*)tempBuffer);
-
- // Make sure there is at least some delay between frames
- if (frameDelay < 1) {
- frameDelay = 1;
- }
-
- // Decompress LZW data and display the frame
- decompressAndDisplayFrame(filePositionAfter);
-
- // Graphic control extension is for a single frame
- transparentColorIndex = NO_TRANSPARENT_INDEX;
- disposalMethod = DISPOSAL_NONE;
-}
-
-// Parse gif data
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::parseData() {
- if(nextFrameTime_ms > millis())
- return ERROR_WAITING;
-
-#if GIFDEBUG == 1 && DEBUG_PARSING_DATA == 1
- Serial.println("\nParsing Data Block");
-#endif
-
- bool parsedFrame = false;
- while (!parsedFrame) {
-
-#if GIFDEBUG == 1 && DEBUG_WAIT_FOR_KEY_PRESS == 1
- Serial.println("\nPress Key For Next");
- while(Serial.read() <= 0);
-#endif
-
- // Determine what kind of data to process
- uint8_t b = readByte();
-
- if (b == 0x2c) {
- // Parse table based image
-#if GIFDEBUG == 1 && DEBUG_PARSING_DATA == 1
- Serial.println("\nParsing Table Based");
-#endif
- parseTableBasedImage();
- parsedFrame = true;
-
- }
- else if (b == 0x21) {
- // Parse extension
- b = readByte();
-
-#if GIFDEBUG == 1 && DEBUG_PARSING_DATA == 1
- Serial.println("\nParsing Extension");
-#endif
-
- // Determine which kind of extension to parse
- switch (b) {
- case 0x01:
- // Plain test extension
- parsePlainTextExtension();
- break;
- case 0xf9:
- // Graphic control extension
- parseGraphicControlExtension();
- break;
- case 0xfe:
- // Comment extension
- parseCommentExtension();
- break;
- case 0xff:
- // Application extension
- parseApplicationExtension();
- break;
- default:
- Serial.print("Unknown control extension: ");
- Serial.println(b, HEX);
- return ERROR_UNKNOWNCONTROLEXT;
- }
- }
- else {
-#if GIFDEBUG == 1 && DEBUG_PARSING_DATA == 1
- Serial.println("\nParsing Done");
-#endif
-
- // Push unprocessed byte back into the stream for later processing
- backUpStream(1);
-
- return ERROR_DONE_PARSING;
- }
- }
- return ERROR_NONE;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::startDecoding(void) {
- // Initialize variables
- keyFrame = true;
- prevDisposalMethod = DISPOSAL_NONE;
- transparentColorIndex = NO_TRANSPARENT_INDEX;
- nextFrameTime_ms = 0;
- fileSeekCallback(0);
-
- // Validate the header
- if (! parseGifHeader()) {
- Serial.println("Not a GIF file");
- return ERROR_FILENOTGIF;
- }
- // If we get here we have a gif file to process
-
- // Parse the logical screen descriptor
- parseLogicalScreenDescriptor();
-
- // Parse the global color table
- parseGlobalColorTable();
-
- return ERROR_NONE;
-}
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::decodeFrame(void) {
- // Parse gif data
- int result = parseData();
- if (result < ERROR_NONE) {
- Serial.println("Error: ");
- Serial.println(result);
- Serial.println(" occurred during parsing of data");
- return result;
- }
-
- if (result == ERROR_DONE_PARSING) {
- //startDecoding();
- // Initialize variables like with a new file
- keyFrame = true;
- prevDisposalMethod = DISPOSAL_NONE;
- transparentColorIndex = NO_TRANSPARENT_INDEX;
- nextFrameTime_ms = 0;
- fileSeekCallback(0);
-
- // parse Gif Header like with a new file
- parseGifHeader();
-
- // Parse the logical screen descriptor
- parseLogicalScreenDescriptor();
-
- // Parse the global color table
- parseGlobalColorTable();
- }
-
- return result;
-}
-
-// Decompress LZW data and display animation frame
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::decompressAndDisplayFrame(unsigned long filePositionAfter) {
-
- // Each pixel of image is 8 bits and is an index into the palette
-
- // How the image is decoded depends upon whether it is interlaced or not
- // Decode the interlaced LZW data into the image buffer
- if (tbiInterlaced) {
- // Decode every 8th line starting at line 0
- for (int line = tbiImageY + 0; line < tbiHeight + tbiImageY; line += 8) {
- lzw_decode(imageData + (line * maxGifWidth) + tbiImageX, tbiWidth, min(imageData + (line * maxGifWidth) + maxGifWidth, imageData + sizeof(imageData)));
- }
- // Decode every 8th line starting at line 4
- for (int line = tbiImageY + 4; line < tbiHeight + tbiImageY; line += 8) {
- lzw_decode(imageData + (line * maxGifWidth) + tbiImageX, tbiWidth, min(imageData + (line * maxGifWidth) + maxGifWidth, imageData + sizeof(imageData)));
- }
- // Decode every 4th line starting at line 2
- for (int line = tbiImageY + 2; line < tbiHeight + tbiImageY; line += 4) {
- lzw_decode(imageData + (line * maxGifWidth) + tbiImageX, tbiWidth, min(imageData + (line * maxGifWidth) + maxGifWidth, imageData + sizeof(imageData)));
- }
- // Decode every 2nd line starting at line 1
- for (int line = tbiImageY + 1; line < tbiHeight + tbiImageY; line += 2) {
- lzw_decode(imageData + (line * maxGifWidth) + tbiImageX, tbiWidth, min(imageData + (line * maxGifWidth) + maxGifWidth, imageData + sizeof(imageData)));
- }
- }
- else {
- // Decode the non interlaced LZW data into the image data buffer
- for (int line = tbiImageY; line < tbiHeight + tbiImageY; line++) {
- lzw_decode(imageData + (line * maxGifWidth) + tbiImageX, tbiWidth, imageData + sizeof(imageData));
- }
- }
-
-#if GIFDEBUG == 1 && DEBUG_DECOMPRESS_AND_DISPLAY == 1
- Serial.println("File Position After: ");
- Serial.println(filePositionCallback());
-#endif
-
-#if GIFDEBUG == 1 && DEBUG_WAIT_FOR_KEY_PRESS == 1
- Serial.println("\nPress Key For Next");
- while(Serial.read() <= 0);
-#endif
-
- // LZW doesn't parse through all the data, manually set position
- fileSeekCallback(filePositionAfter);
-
- // Optional callback can be used to get drawing routines ready
- if(startDrawingCallback)
- (*startDrawingCallback)();
-
- // Image data is decompressed, now display portion of image affected by frame
- int yOffset, pixel;
- for (int y = tbiImageY; y < tbiHeight + tbiImageY; y++) {
- yOffset = y * maxGifWidth;
- for (int x = tbiImageX; x < tbiWidth + tbiImageX; x++) {
- // Get the next pixel
- pixel = imageData[yOffset + x];
-
- // Check pixel transparency
- if (pixel == transparentColorIndex) {
- continue;
- }
-
- // Pixel not transparent so get color from palette and draw the pixel
- if(drawPixelCallback)
- (*drawPixelCallback)(x, y, palette[pixel].red, palette[pixel].green, palette[pixel].blue);
- }
- }
- // Make animation frame visible
- // swapBuffers() call can take up to 1/framerate seconds to return (it waits until a buffer copy is complete)
- // note the time before calling
-
- // wait until time to display next frame
- while(nextFrameTime_ms > millis());
-
- // calculate time to display next frame
- nextFrameTime_ms = millis() + (10 * frameDelay);
- if(updateScreenCallback)
- (*updateScreenCallback)();
-}
diff --git a/examples/AnimatedGIF/LICENSE.txt b/examples/AnimatedGIF/LICENSE.txt
deleted file mode 100644
index c69f703..0000000
--- a/examples/AnimatedGIF/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Craig A. Lindley
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/examples/AnimatedGIF/LzwDecoder_Impl.h b/examples/AnimatedGIF/LzwDecoder_Impl.h
deleted file mode 100644
index 720ac24..0000000
--- a/examples/AnimatedGIF/LzwDecoder_Impl.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * This file contains code to decompress the LZW encoded animated GIF data
- *
- * Written by: Craig A. Lindley, Fabrice Bellard and Steven A. Bennett
- * See my book, "Practical Image Processing in C", John Wiley & Sons, Inc.
- *
- * Copyright (c) 2014 Craig A. Lindley
- * Minor modifications by Louis Beaudoin (pixelmatix)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define LZWDEBUG 0
-
-#include "GifDecoder.h"
-
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::lzw_setTempBuffer(uint8_t * tempBuffer) {
- temp_buffer = tempBuffer;
-}
-
-// Initialize LZW decoder
-// csize initial code size in bits
-// buf input data
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-void GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::lzw_decode_init (int csize) {
-
- // Initialize read buffer variables
- bbuf = 0;
- bbits = 0;
- bs = 0;
- bcnt = 0;
-
- // Initialize decoder variables
- codesize = csize;
- cursize = codesize + 1;
- curmask = mask[cursize];
- top_slot = 1 << cursize;
- clear_code = 1 << codesize;
- end_code = clear_code + 1;
- slot = newcodes = clear_code + 2;
- oc = fc = -1;
- sp = stack;
-}
-
-// Get one code of given number of bits from stream
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::lzw_get_code() {
-
- while (bbits < cursize) {
- if (bcnt == bs) {
- // get number of bytes in next block
- readIntoBuffer(temp_buffer, 1);
- bs = temp_buffer[0];
- readIntoBuffer(temp_buffer, bs);
- bcnt = 0;
- }
- bbuf |= temp_buffer[bcnt] << bbits;
- bbits += 8;
- bcnt++;
- }
- int c = bbuf;
- bbuf >>= cursize;
- bbits -= cursize;
- return c & curmask;
-}
-
-// Decode given number of bytes
-// buf 8 bit output buffer
-// len number of pixels to decode
-// returns the number of bytes decoded
-template <int maxGifWidth, int maxGifHeight, int lzwMaxBits>
-int GifDecoder<maxGifWidth, maxGifHeight, lzwMaxBits>::lzw_decode(uint8_t *buf, int len, uint8_t *bufend) {
- int l, c, code;
-
-#if LZWDEBUG == 1
- unsigned char debugMessagePrinted = 0;
-#endif
-
- if (end_code < 0) {
- return 0;
- }
- l = len;
-
- for (;;) {
- while (sp > stack) {
- // load buf with data if we're still within bounds
- if(buf < bufend) {
- *buf++ = *(--sp);
- } else {
- // out of bounds, keep incrementing the pointers, but don't use the data
-#if LZWDEBUG == 1
- // only print this message once per call to lzw_decode
- if(buf == bufend)
- Serial.println("****** LZW imageData buffer overrun *******");
-#endif
- }
- if ((--l) == 0) {
- return len;
- }
- }
- c = lzw_get_code();
- if (c == end_code) {
- break;
-
- }
- else if (c == clear_code) {
- cursize = codesize + 1;
- curmask = mask[cursize];
- slot = newcodes;
- top_slot = 1 << cursize;
- fc= oc= -1;
-
- }
- else {
-
- code = c;
- if ((code == slot) && (fc >= 0)) {
- *sp++ = fc;
- code = oc;
- }
- else if (code >= slot) {
- break;
- }
- while (code >= newcodes) {
- *sp++ = suffix[code];
- code = prefix[code];
- }
- *sp++ = code;
- if ((slot < top_slot) && (oc >= 0)) {
- suffix[slot] = code;
- prefix[slot++] = oc;
- }
- fc = code;
- oc = c;
- if (slot >= top_slot) {
- if (cursize < lzwMaxBits) {
- top_slot <<= 1;
- curmask = mask[++cursize];
- } else {
-#if LZWDEBUG == 1
- if(!debugMessagePrinted) {
- debugMessagePrinted = 1;
- Serial.println("****** cursize >= lzwMaxBits *******");
- }
-#endif
- }
-
- }
- }
- }
- end_code = -1;
- return len - l;
-}
diff --git a/examples/AnimatedGIF/data/Text_Animations.txt.txt b/examples/AnimatedGIF/data/Text_Animations.txt.txt
deleted file mode 100644
index 8431cd4..0000000
--- a/examples/AnimatedGIF/data/Text_Animations.txt.txt
+++ /dev/null
@@ -1 +0,0 @@
-https://loading.io/animation/text/ \ No newline at end of file
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/AnimatedGIFPanel.ino b/examples/AnimatedGIFPanel/AnimatedGIFPanel.ino
index 0f08249..0f08249 100644
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/AnimatedGIFPanel.ino
+++ b/examples/AnimatedGIFPanel/AnimatedGIFPanel.ino
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif b/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif
deleted file mode 100644
index 0a219a4..0000000
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif
+++ /dev/null
Binary files differ
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif b/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif
deleted file mode 100644
index 342f8ae..0000000
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif
+++ /dev/null
Binary files differ
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/README.md b/examples/AnimatedGIFPanel/README.md
index aa55689..aa55689 100644
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/README.md
+++ b/examples/AnimatedGIFPanel/README.md
diff --git a/examples/AnimatedGIF/data/ezgif.com-pacmn.gif b/examples/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif
index 0a219a4..0a219a4 100644
--- a/examples/AnimatedGIF/data/ezgif.com-pacmn.gif
+++ b/examples/AnimatedGIFPanel/data/gifs/ezgif.com-pacmn.gif
Binary files differ
diff --git a/examples/AnimatedGIF/data/loading.io-64x32px.gif b/examples/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif
index 342f8ae..342f8ae 100644
--- a/examples/AnimatedGIF/data/loading.io-64x32px.gif
+++ b/examples/AnimatedGIFPanel/data/gifs/loading.io-64x32px.gif
Binary files differ
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/matrix-spin.gif b/examples/AnimatedGIFPanel/data/gifs/matrix-spin.gif
index 7925d68..7925d68 100644
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/matrix-spin.gif
+++ b/examples/AnimatedGIFPanel/data/gifs/matrix-spin.gif
Binary files differ
diff --git a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/shock.gif b/examples/AnimatedGIFPanel/data/gifs/shock.gif
index b07d631..b07d631 100644
--- a/examples/AnimatedGIFPanel/AnimatedGIFPanel/data/gifs/shock.gif
+++ b/examples/AnimatedGIFPanel/data/gifs/shock.gif
Binary files differ