Moving library to /lib

This commit is contained in:
gamblor21 2023-02-10 18:31:59 -06:00
parent 19eba41630
commit da9b6fb0e2
8 changed files with 874 additions and 366 deletions

View File

@ -0,0 +1,236 @@
//
// GIF Animator
// written by Larry Bank
// bitbank@pobox.com
// Arduino port started 7/5/2020
// Original GIF code written 20+ years ago :)
// The goal of this code is to decode images up to 480x320
// using no more than 22K of RAM (if sent directly to an LCD display)
//
// Copyright 2020 BitBank Software, Inc. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===========================================================================
#include "AnimatedGIF.h"
// Here is all of the actual code...
#include "gif.inl"
//
// Memory initialization
//
int AnimatedGIF::open(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw)
{
_gif.iError = GIF_SUCCESS;
_gif.pfnRead = readMem;
_gif.pfnSeek = seekMem;
_gif.pfnDraw = pfnDraw;
_gif.pfnOpen = NULL;
_gif.pfnClose = NULL;
_gif.GIFFile.iSize = iDataSize;
_gif.GIFFile.pData = pData;
return GIFInit(&_gif);
} /* open() */
int AnimatedGIF::openFLASH(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw)
{
_gif.iError = GIF_SUCCESS;
_gif.pfnRead = readFLASH;
_gif.pfnSeek = seekMem;
_gif.pfnDraw = pfnDraw;
_gif.pfnOpen = NULL;
_gif.pfnClose = NULL;
_gif.GIFFile.iSize = iDataSize;
_gif.GIFFile.pData = pData;
return GIFInit(&_gif);
} /* openFLASH() */
//
// Returns the first comment block found (if any)
//
int AnimatedGIF::getComment(char *pDest)
{
int32_t iOldPos;
iOldPos = _gif.GIFFile.iPos; // keep old position
(*_gif.pfnSeek)(&_gif.GIFFile, _gif.iCommentPos);
(*_gif.pfnRead)(&_gif.GIFFile, (uint8_t *)pDest, _gif.sCommentLen);
(*_gif.pfnSeek)(&_gif.GIFFile, iOldPos);
pDest[_gif.sCommentLen] = 0; // zero terminate the string
return (int)_gif.sCommentLen;
} /* getComment() */
//
// Allocate a block of memory to hold the entire canvas (as 8-bpp)
//
int AnimatedGIF::allocFrameBuf(GIF_ALLOC_CALLBACK *pfnAlloc)
{
if (_gif.iCanvasWidth > 0 && _gif.iCanvasHeight > 0 && _gif.pFrameBuffer == NULL)
{
// Allocate a little extra space for the current line
// as RGB565 or RGB888
int iCanvasSize = _gif.iCanvasWidth * (_gif.iCanvasHeight+3);
_gif.pFrameBuffer = (unsigned char *)(*pfnAlloc)(iCanvasSize);
if (_gif.pFrameBuffer == NULL)
return GIF_ERROR_MEMORY;
return GIF_SUCCESS;
}
return GIF_INVALID_PARAMETER;
} /* allocFrameBuf() */
//
// Set the DRAW callback behavior to RAW (default)
// or COOKED (requires allocating a frame buffer)
//
int AnimatedGIF::setDrawType(int iType)
{
if (iType != GIF_DRAW_RAW && iType != GIF_DRAW_COOKED)
return GIF_INVALID_PARAMETER; // invalid drawing mode
_gif.ucDrawType = (uint8_t)iType;
return GIF_SUCCESS;
} /* setDrawType() */
//
// Release the memory used by the frame buffer
//
int AnimatedGIF::freeFrameBuf(GIF_FREE_CALLBACK *pfnFree)
{
if (_gif.pFrameBuffer)
{
(*pfnFree)(_gif.pFrameBuffer);
_gif.pFrameBuffer = NULL;
return GIF_SUCCESS;
}
return GIF_INVALID_PARAMETER;
} /* freeFrameBuf() */
//
// Return a pointer to the frame buffer (if it was allocated)
//
uint8_t * AnimatedGIF::getFrameBuf()
{
return _gif.pFrameBuffer;
} /* getFrameBuf() */
int AnimatedGIF::getCanvasWidth()
{
return _gif.iCanvasWidth;
} /* getCanvasWidth() */
int AnimatedGIF::getCanvasHeight()
{
return _gif.iCanvasHeight;
} /* getCanvasHeight() */
int AnimatedGIF::getLoopCount()
{
return _gif.iRepeatCount;
} /* getLoopCount() */
int AnimatedGIF::getInfo(GIFINFO *pInfo)
{
return GIF_getInfo(&_gif, pInfo);
} /* getInfo() */
int AnimatedGIF::getLastError()
{
return _gif.iError;
} /* getLastError() */
//
// File (SD/MMC) based initialization
//
int AnimatedGIF::open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw)
{
_gif.iError = GIF_SUCCESS;
_gif.pfnRead = pfnRead;
_gif.pfnSeek = pfnSeek;
_gif.pfnDraw = pfnDraw;
_gif.pfnOpen = pfnOpen;
_gif.pfnClose = pfnClose;
_gif.GIFFile.fHandle = (*pfnOpen)(szFilename, &_gif.GIFFile.iSize);
if (_gif.GIFFile.fHandle == NULL) {
_gif.iError = GIF_FILE_NOT_OPEN;
return 0;
}
return GIFInit(&_gif);
} /* open() */
void AnimatedGIF::close()
{
if (_gif.pfnClose)
(*_gif.pfnClose)(_gif.GIFFile.fHandle);
} /* close() */
void AnimatedGIF::reset()
{
(*_gif.pfnSeek)(&_gif.GIFFile, 0);
} /* reset() */
void AnimatedGIF::begin(unsigned char ucPaletteType)
{
memset(&_gif, 0, sizeof(_gif));
if (ucPaletteType != GIF_PALETTE_RGB565_LE && ucPaletteType != GIF_PALETTE_RGB565_BE && ucPaletteType != GIF_PALETTE_RGB888)
_gif.iError = GIF_INVALID_PARAMETER;
_gif.ucPaletteType = ucPaletteType;
_gif.ucDrawType = GIF_DRAW_RAW; // assume RAW pixel handling
_gif.pFrameBuffer = NULL;
} /* begin() */
//
// Play a single frame
// returns:
// 1 = good result and more frames exist
// 0 = no more frames exist, a frame may or may not have been played: use getLastError() and look for GIF_SUCCESS to know if a frame was played
// -1 = error
int AnimatedGIF::playFrame(bool bSync, int *delayMilliseconds, void *pUser)
{
int rc;
#if !defined( __MACH__ ) && !defined( __LINUX__ )
long lTime = millis();
#endif
if (_gif.GIFFile.iPos >= _gif.GIFFile.iSize-1) // no more data exists
{
(*_gif.pfnSeek)(&_gif.GIFFile, 0); // seek to start
}
if (GIFParseInfo(&_gif, 0))
{
_gif.pUser = pUser;
if (_gif.iError == GIF_EMPTY_FRAME) // don't try to decode it
return 0;
rc = DecodeLZW(&_gif, 0);
if (rc != 0) // problem
return -1;
}
else
{
// The file is "malformed" in that there is a bunch of non-image data after
// the last frame. Return as if all is well, though if needed getLastError()
// can be used to see if a frame was actually processed:
// GIF_SUCCESS -> frame processed, GIF_EMPTY_FRAME -> no frame processed
if (_gif.iError == GIF_EMPTY_FRAME)
{
if (delayMilliseconds)
*delayMilliseconds = 0;
return 0;
}
return -1; // error parsing the frame info, we may be at the end of the file
}
// Return 1 for more frames or 0 if this was the last frame
if (bSync)
{
#if !defined( __MACH__ ) && !defined( __LINUX__ )
lTime = millis() - lTime;
if (lTime < _gif.iFrameDelay) // need to pause a bit
delay(_gif.iFrameDelay - lTime);
#endif // __LINUX__
}
if (delayMilliseconds) // if not NULL, return the frame delay time
*delayMilliseconds = _gif.iFrameDelay;
return (_gif.GIFFile.iPos < _gif.GIFFile.iSize-10);
} /* playFrame() */

View File

@ -0,0 +1,216 @@
// Copyright 2020 BitBank Software, Inc. All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===========================================================================
#ifndef __ANIMATEDGIF__
#define __ANIMATEDGIF__
#if defined( PICO_BUILD ) || defined( __MACH__ ) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#define memcpy_P memcpy
#define PROGMEM
#else
#include <Arduino.h>
#endif
//
// GIF Animator
// Written by Larry Bank
// Copyright (c) 2020 BitBank Software, Inc.
// bitbank@pobox.com
//
// Designed to decode images up to 480x320
// using less than 22K of RAM
//
/* GIF Defines and variables */
#define MAX_CHUNK_SIZE 255
#define LZW_BUF_SIZE (6*MAX_CHUNK_SIZE)
#define LZW_HIGHWATER (4*MAX_CHUNK_SIZE)
#ifdef __LINUX__
#define MAX_WIDTH 2048
#else
#define MAX_WIDTH 320
#endif // __LINUX__
#define FILE_BUF_SIZE 4096
#define PIXEL_FIRST 0
#define PIXEL_LAST 4096
#define LINK_UNUSED 5911 // 0x1717 to use memset
#define LINK_END 5912
#define MAX_HASH 5003
#define MAXMAXCODE 4096
enum {
GIF_PALETTE_RGB565_LE = 0, // little endian (default)
GIF_PALETTE_RGB565_BE, // big endian
GIF_PALETTE_RGB888 // original 24-bpp entries
};
// for compatibility with older code
#define LITTLE_ENDIAN_PIXELS GIF_PALETTE_RGB565_LE
#define BIG_ENDIAN_PIXELS GIF_PALETTE_RGB565_BE
//
// Draw callback pixel type
// RAW = 8-bit palettized pixels requiring transparent pixel handling
// COOKED = 16 or 24-bpp fully rendered pixels ready for display
//
enum {
GIF_DRAW_RAW = 0,
GIF_DRAW_COOKED
};
enum {
GIF_SUCCESS = 0,
GIF_DECODE_ERROR,
GIF_TOO_WIDE,
GIF_INVALID_PARAMETER,
GIF_UNSUPPORTED_FEATURE,
GIF_FILE_NOT_OPEN,
GIF_EARLY_EOF,
GIF_EMPTY_FRAME,
GIF_BAD_FILE,
GIF_ERROR_MEMORY
};
typedef struct gif_file_tag
{
int32_t iPos; // current file position
int32_t iSize; // file size
uint8_t *pData; // memory file pointer
void * fHandle; // class pointer to File/SdFat or whatever you want
} GIFFILE;
typedef struct gif_info_tag
{
int32_t iFrameCount; // total frames in file
int32_t iDuration; // duration of animation in milliseconds
int32_t iMaxDelay; // maximum frame delay
int32_t iMinDelay; // minimum frame delay
} GIFINFO;
typedef struct gif_draw_tag
{
int iX, iY; // Corner offset of this frame on the canvas
int y; // current line being drawn (0 = top line of image)
int iWidth, iHeight; // size of this frame
void *pUser; // user supplied pointer
uint8_t *pPixels; // 8-bit source pixels for this line
uint16_t *pPalette; // little or big-endian RGB565 palette entries (default)
uint8_t *pPalette24; // RGB888 palette (optional)
uint8_t ucTransparent; // transparent color
uint8_t ucHasTransparency; // flag indicating the transparent color is in use
uint8_t ucDisposalMethod; // frame disposal method
uint8_t ucBackground; // background color
uint8_t ucIsGlobalPalette; // Flag to indicate that a global palette, rather than a local palette is being used
} GIFDRAW;
// Callback function prototypes
typedef int32_t (GIF_READ_CALLBACK)(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen);
typedef int32_t (GIF_SEEK_CALLBACK)(GIFFILE *pFile, int32_t iPosition);
typedef void (GIF_DRAW_CALLBACK)(GIFDRAW *pDraw);
typedef void * (GIF_OPEN_CALLBACK)(const char *szFilename, int32_t *pFileSize);
typedef void (GIF_CLOSE_CALLBACK)(void *pHandle);
typedef void * (GIF_ALLOC_CALLBACK)(uint32_t iSize);
typedef void (GIF_FREE_CALLBACK)(void *buffer);
//
// our private structure to hold a GIF image decode state
//
typedef struct gif_image_tag
{
int iWidth, iHeight, iCanvasWidth, iCanvasHeight;
int iX, iY; // GIF corner offset
int iBpp;
int iError; // last error
int iFrameDelay; // delay in milliseconds for this frame
int iRepeatCount; // NETSCAPE animation repeat count. 0=forever
int iXCount, iYCount; // decoding position in image (countdown values)
int iLZWOff; // current LZW data offset
int iLZWSize; // current quantity of data in the LZW buffer
int iCommentPos; // file offset of start of comment data
short sCommentLen; // length of comment
GIF_READ_CALLBACK *pfnRead;
GIF_SEEK_CALLBACK *pfnSeek;
GIF_DRAW_CALLBACK *pfnDraw;
GIF_OPEN_CALLBACK *pfnOpen;
GIF_CLOSE_CALLBACK *pfnClose;
GIFFILE GIFFile;
void *pUser;
unsigned char *pFrameBuffer;
unsigned char *pPixels, *pOldPixels;
unsigned char ucLineBuf[MAX_WIDTH]; // current line
unsigned char ucFileBuf[FILE_BUF_SIZE]; // holds temp data and pixel stack
unsigned short pPalette[384]; // can hold RGB565 or RGB888 - set in begin()
unsigned short pLocalPalette[384]; // color palettes for GIF images
unsigned char ucLZW[LZW_BUF_SIZE]; // holds 6 chunks (6x255) of GIF LZW data packed together
unsigned short usGIFTable[4096];
unsigned char ucGIFPixels[8192];
unsigned char bEndOfFrame;
unsigned char ucGIFBits, ucBackground, ucTransparent, ucCodeStart, ucMap, bUseLocalPalette;
unsigned char ucPaletteType; // RGB565 or RGB888
unsigned char ucDrawType; // RAW or COOKED
} GIFIMAGE;
#ifdef __cplusplus
//
// The GIF class wraps portable C code which does the actual work
//
class AnimatedGIF
{
public:
int open(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
int openFLASH(uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
int open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw);
void close();
void reset();
void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE);
void begin(int iEndian, unsigned char ucPaletteType) { begin(ucPaletteType); };
int playFrame(bool bSync, int *delayMilliseconds, void *pUser = NULL);
int getCanvasWidth();
int allocFrameBuf(GIF_ALLOC_CALLBACK *pfnAlloc);
int setDrawType(int iType);
int freeFrameBuf(GIF_FREE_CALLBACK *pfnFree);
uint8_t *getFrameBuf();
int getCanvasHeight();
int getLoopCount();
int getInfo(GIFINFO *pInfo);
int getLastError();
int getComment(char *destBuffer);
private:
GIFIMAGE _gif;
};
#else
// C interface
int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw);
int GIF_openFile(GIFIMAGE *pGIF, const char *szFilename, GIF_DRAW_CALLBACK *pfnDraw);
void GIF_close(GIFIMAGE *pGIF);
void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType);
void GIF_reset(GIFIMAGE *pGIF);
int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser);
int GIF_getCanvasWidth(GIFIMAGE *pGIF);
int GIF_getCanvasHeight(GIFIMAGE *pGIF);
int GIF_getComment(GIFIMAGE *pGIF, char *destBuffer);
int GIF_getInfo(GIFIMAGE *pGIF, GIFINFO *pInfo);
int GIF_getLastError(GIFIMAGE *pGIF);
int GIF_getLoopCount(GIFIMAGE *pGIF);
#endif // __cplusplus
// Due to unaligned memory causing an exception, we have to do these macros the slow way
#define INTELSHORT(p) ((*p) + (*(p+1)<<8))
#define INTELLONG(p) ((*p) + (*(p+1)<<8) + (*(p+2)<<16) + (*(p+3)<<24))
#define MOTOSHORT(p) (((*(p))<<8) + (*(p+1)))
#define MOTOLONG(p) (((*p)<<24) + ((*(p+1))<<16) + ((*(p+2))<<8) + (*(p+3)))
// Must be a 32-bit target processor
#define REGISTER_WIDTH 32
#endif // __ANIMATEDGIF__

View File

@ -9,6 +9,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// ===========================================================================
//
// Modified 2023 by Mark Komus to work for CircuitPython
//
#ifndef __ANIMATEDGIF__
#define __ANIMATEDGIF__

View File

@ -0,0 +1,5 @@
This library is from the AnimatedGIF Arduino GIF decoder by Larry Bank.
Released under the Apache License 2.0
[AnimatedGIF](https://github.com/bitbank2/AnimatedGIF)
It has been modified for use in CircuitPython by Mark Komus.

File diff suppressed because it is too large Load Diff

View File

@ -580,7 +580,6 @@ SRC_SHARED_MODULE_ALL = \
displayio/I2CDisplay.c \
displayio/OnDiskBitmap.c \
displayio/OnDiskGif.c \
displayio/gif.c \
displayio/Palette.c \
displayio/Shape.c \
displayio/TileGrid.c \
@ -699,10 +698,10 @@ SRC_MOD += $(addprefix lib/protomatter/src/, \
$(BUILD)/lib/protomatter/src/core.o: CFLAGS += -include "shared-module/rgbmatrix/allocator.h" -DCIRCUITPY -Wno-missing-braces -Wno-missing-prototypes
endif
#SRC_MOD += $(addprefix lib/AnimatedGIF/, \
#gif.c \
#)
#$(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -Wno-missing-braces -Wno-missing-prototypes
SRC_MOD += $(addprefix lib/AnimatedGIF/, \
gif.c \
)
$(BUILD)/lib/AnimatedGIF/gif.o: CFLAGS += -DCIRCUITPY
ifeq ($(CIRCUITPY_ZLIB),1)
SRC_MOD += $(addprefix lib/uzlib/, \

View File

@ -32,8 +32,7 @@
#include "py/obj.h"
// #include "lib/AnimatedGIF/AnimatedGIF_circuitpy.h"
#include "AnimatedGIF_circuitpy.h"
#include "lib/AnimatedGIF/AnimatedGIF_circuitpy.h"
#include "Bitmap.h"
#include "extmod/vfs_fat.h"