This commit is contained in:
Stephan Mühl
2023-03-22 12:15:18 +01:00
committed by GitHub
parent 3e12414a87
commit adb5102869
203 changed files with 35010 additions and 0 deletions

17
lib/TJpg_Decoder/.gitattributes vendored Normal file
View File

@@ -0,0 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

23
lib/TJpg_Decoder/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================

1
lib/TJpg_Decoder/.piopm Normal file
View File

@@ -0,0 +1 @@
{"type": "library", "name": "TJpg_Decoder", "version": "1.0.8", "spec": {"owner": "bodmer", "id": 6906, "name": "TJpg_Decoder", "requirements": null, "uri": null}}

View File

@@ -0,0 +1,19 @@
Arduino TJpg_Decoder library
===========
This Arduino library supports the rendering of Jpeg files stored both on SD card and in arrays within program memory (FLASH) onto a TFT display. In addition images stored in the SPIFFS (ESP32, ESP8266) and LittleFS (ESP32, ESP8266, RP2040) Flash filing systems or alternatively "PROGMEM" arrays can be used.
The library has been tested on the Arduino Due, ESP32 and ESP8266 (e.g. NodeMCU 1.0), STM32 and RP2040 processors. Other processors should work too if they have sufficient memory. Use with the ESP32 requires Arduino board package 2.0.0 or later.
Jpeg files must be in 24bit format (8 bit not supported). Jpeg files in the "Progressive" format (where image data is compressed in multiple passes with progressively higher detail) are not supported either since this would require much more memory.
When storing the jpeg in a memory array bear in mind that some Arduino boards have a maximum 32767 byte limit for the maximum size of an array (32 KBytes minus 1 byte).
The decompression of Jpeg images needs more RAM than an UNO provides, thus this library is targetted at processors with more RAM. The decoder has a very small memory footprint, typically 3.5K Bytes of RAM (for workspace, Independent of Image Dimensions) and 3.5-8.5K Bytes of ROM for text and constants.
On a Mega the number of images stored in FLASH must be limited because it they are large enough to push the executable code start over the 64K 16 bit address limit then the Mega will fail to boot even though the sketch compiles and uploads correctly. This is a limitation imposed by the Arduino environment not this library! The Arduino Mega is not recommended as it does not reliably decode some jpeg images possibly due to a shortage of RAM. The Due will work fine with much bigger image sets in FLASH.
This library uses the TJpgDec decompressor engine detailed here:
http://elm-chan.org/fsw/tjpgd/00index.html
TJpgDec is a generic JPEG image decompressor module that highly optimized for small embedded systems.

View File

@@ -0,0 +1,27 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
TJpg_Decoder KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
TJpgDec KEYWORD2
TJpg_Decoder KEYWORD2
drawJpg KEYWORD2
drawSdJpg KEYWORD2
drawFsJpg KEYWORD2
getJpgSize KEYWORD2
getSdJpgSize KEYWORD2
getFsJpgSize KEYWORD2
setJpgScale KEYWORD2
setCallback KEYWORD2
//tft_output KEYWORD2

View File

@@ -0,0 +1,22 @@
{
"name": "TJpg_Decoder",
"version": "1.0.8",
"keywords": "jpeg, jpg, tft, display, RP2040, STM32, ESP8266, ESP32",
"description": "A JPEG decoder library based on Tiny JPEG Decompressor",
"repository":
{
"type": "git",
"url": "https://github.com/Bodmer/TJpg_Decoder"
},
"authors":
[
{
"name": "Bodmer",
"email": "bodmer@anola.net",
"maintainer": true
}
],
"frameworks": "arduino",
"platforms": "raspberrypi, espressif8266, espressif32, ststm32",
"headers": "TJpg_Decoder.h"
}

View File

@@ -0,0 +1,10 @@
name=TJpg_Decoder
version=1.0.8
author=Bodmer
maintainer=Bodmer
sentence=A JPEG decoder based on tjpgd
paragraph=Renders jpeg images to TFT displays.
category=Display
url=https://github.com/Bodmer/TJpg_Decoder
architectures=*
includes=TJpg_Decoder.h

View File

@@ -0,0 +1,54 @@
This library incorporate the Tiny JPEG Decompressor code files:
"tjpgd.h" and "tjpgd.c". The licence for these files is:
/*----------------------------------------------------------------------------/
/ TJpgDec - Tiny JPEG Decompressor R0.01c (C)ChaN, 2019
/-----------------------------------------------------------------------------/
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2019, ChaN, all right reserved.
/
/ * The TJpgDec module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/
/-----------------------------------------------------------------------------/
This Arduino library "TJpd_Decoder" has been created by Bodmer, for all the
additional code the FreeBSD licence applies and is compatible with the GNU GPL:
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Software License Agreement (FreeBSD License)
Copyright (c) 2019 Bodmer (https://github.com/Bodmer)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^End^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -0,0 +1,197 @@
/*
TJpg_Decoder.cpp
Created by Bodmer 18/10/19
Modified by Blueforcer 02/23
Latest version here:
https://github.com/Bodmer/TJpg_Decoder
*/
#include "TJpg_Decoder.h"
// Create a class instance to be used by the sketch (defined as extern in header)
TJpg_Decoder TJpgDec;
/***************************************************************************************
** Function name: TJpg_Decoder
** Description: Constructor
***************************************************************************************/
TJpg_Decoder::TJpg_Decoder()
{
// Setup a pointer to this class for static functions
thisPtr = this;
}
/***************************************************************************************
** Function name: ~TJpg_Decoder
** Description: Destructor
***************************************************************************************/
TJpg_Decoder::~TJpg_Decoder()
{
// Bye
}
/***************************************************************************************
** Function name: setJpgScale
** Description: Set the reduction scale factor (1, 2, 4 or 8)
***************************************************************************************/
void TJpg_Decoder::setSwapBytes(bool swapBytes)
{
_swap = swapBytes;
}
/***************************************************************************************
** Function name: setJpgScale
** Description: Set the reduction scale factor (1, 2, 4 or 8)
***************************************************************************************/
void TJpg_Decoder::setJpgScale(uint8_t scaleFactor)
{
switch (scaleFactor)
{
case 1:
jpgScale = 0;
break;
case 2:
jpgScale = 1;
break;
case 4:
jpgScale = 2;
break;
case 8:
jpgScale = 3;
break;
default:
jpgScale = 0;
}
}
/***************************************************************************************
** Function name: setCallback
** Description: Set the sketch callback function to render decoded blocks
***************************************************************************************/
void TJpg_Decoder::setCallback(SketchCallback sketchCallback)
{
tft_output = sketchCallback;
}
/***************************************************************************************
** Function name: jd_input (declared static)
** Description: Called by tjpgd.c to get more data
***************************************************************************************/
unsigned int TJpg_Decoder::jd_input(JDEC *jdec, uint8_t *buf, unsigned int len)
{
TJpg_Decoder *thisPtr = TJpgDec.thisPtr;
jdec = jdec; // Supress warning
// Handle an array input
if (thisPtr->jpg_source == TJPG_ARRAY)
{
// Avoid running off end of array
if (thisPtr->array_index + len > thisPtr->array_size)
{
len = thisPtr->array_size - thisPtr->array_index;
}
// If buf is valid then copy len bytes to buffer
if (buf)
memcpy_P(buf, (const uint8_t *)(thisPtr->array_data + thisPtr->array_index), len);
// Move pointer
thisPtr->array_index += len;
}
#ifdef TJPGD_LOAD_FFS
// Handle SPIFFS input
else if (thisPtr->jpg_source == TJPG_FS_FILE)
{
// Check how many bytes are available
uint32_t bytesLeft = thisPtr->jpgFile.available();
if (bytesLeft < len)
len = bytesLeft;
if (buf)
{
// Read into buffer, pointer moved as well
thisPtr->jpgFile.read(buf, len);
}
else
{
// Buffer is null, so skip data by moving pointer
thisPtr->jpgFile.seek(thisPtr->jpgFile.position() + len);
}
}
#endif
#if defined(TJPGD_LOAD_SD_LIBRARY)
// Handle SD library input
else if (thisPtr->jpg_source == TJPG_SD_FILE)
{
// Check how many bytes are available
uint32_t bytesLeft = thisPtr->jpgSdFile.available();
if (bytesLeft < len)
len = bytesLeft;
if (buf)
{
// Read into buffer, pointer moved as well
thisPtr->jpgSdFile.read(buf, len);
}
else
{
// Buffer is null, so skip data by moving pointer
thisPtr->jpgSdFile.seek(thisPtr->jpgSdFile.position() + len);
}
}
#endif
return len;
}
/***************************************************************************************
** Function name: jd_output (declared static)
** Description: Called by tjpgd.c with an image block for rendering
***************************************************************************************/
// Pass image block back to the sketch for rendering, may be a complete or partial MCU
int TJpg_Decoder::jd_output(JDEC *jdec, void *bitmap, JRECT *jrect)
{
TJpg_Decoder *thisPtr = TJpgDec.thisPtr;
jdec = jdec; // Supress warning as ID is not used
int16_t x = jrect->left + thisPtr->jpeg_x;
int16_t y = jrect->top + thisPtr->jpeg_y;
uint16_t w = jrect->right + 1 - jrect->left;
uint16_t h = jrect->bottom + 1 - jrect->top;
// Pass the image block and rendering parameters in a callback to the sketch
return thisPtr->tft_output(x, y, w, h, (uint16_t *)bitmap);
}
/***************************************************************************************
** Function name: drawFsJpg für AWTRIX
** Description: Draw a jpg with opened file handle at x,y
***************************************************************************************/
JRESULT TJpg_Decoder::drawFsJpg(int32_t x, int32_t y, fs::File inFile)
{
JDEC jdec;
JRESULT jresult = JDR_OK;
jpg_source = TJPG_FS_FILE;
jpeg_x = x;
jpeg_y = y;
jdec.swap = _swap;
jpgFile = inFile;
jresult = jd_prepare(&jdec, jd_input, workspace, TJPGD_WORKSPACE_SIZE, (unsigned int)0);
// Extract image and render
if (jresult == JDR_OK)
{
jresult = jd_decomp(&jdec, jd_output, jpgScale);
}
inFile.seek(0);
return jresult;
}

View File

@@ -0,0 +1,128 @@
/*
TJpg_Decoder.h
JPEG Decoder for Arduino using TJpgDec:
http://elm-chan.org/fsw/tjpgd/00index.html
Incorporated into an Arduino library by Bodmer 18/10/19
Latest version here:
https://github.com/Bodmer/TJpg_Decoder
*/
#ifndef TJpg_Decoder_H
#define TJpg_Decoder_H
#include "User_Config.h"
#include "Arduino.h"
#include "tjpgd.h"
#if defined (ESP8266) || defined (ESP32)
#include <pgmspace.h>
#include <FS.h>
#include <LittleFS.h>
#ifdef ESP32
#include "SPIFFS.h" // ESP32 only
#endif
#define TJPGD_LOAD_FFS
#elif defined (ARDUINO_ARCH_RP2040)
#include <FS.h>
#include <LittleFS.h>
#define SPIFFS LittleFS
#define TJPGD_LOAD_FFS
#endif
#if defined (TJPGD_LOAD_SD_LIBRARY)
#include <SD.h>
#endif
enum {
TJPG_ARRAY = 0,
TJPG_FS_FILE,
TJPG_SD_FILE
};
//------------------------------------------------------------------------------
typedef bool (*SketchCallback)(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *data);
class TJpg_Decoder {
private:
#if defined (TJPGD_LOAD_SD_LIBRARY)
File jpgSdFile;
#endif
#ifdef TJPGD_LOAD_FFS
fs::File jpgFile;
#endif
public:
TJpg_Decoder();
~TJpg_Decoder();
static int jd_output(JDEC* jdec, void* bitmap, JRECT* jrect);
static unsigned int jd_input(JDEC* jdec, uint8_t* buf, unsigned int len);
void setJpgScale(uint8_t scale);
void setCallback(SketchCallback sketchCallback);
#if defined (TJPGD_LOAD_SD_LIBRARY) || defined (TJPGD_LOAD_FFS)
JRESULT drawJpg (int32_t x, int32_t y, const char *pFilename);
JRESULT drawJpg (int32_t x, int32_t y, const String& pFilename);
JRESULT getJpgSize(uint16_t *w, uint16_t *h, const char *pFilename);
JRESULT getJpgSize(uint16_t *w, uint16_t *h, const String& pFilename);
#endif
#if defined (TJPGD_LOAD_SD_LIBRARY)
JRESULT drawSdJpg (int32_t x, int32_t y, const char *pFilename);
JRESULT drawSdJpg (int32_t x, int32_t y, const String& pFilename);
JRESULT drawSdJpg (int32_t x, int32_t y, File inFile);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, const char *pFilename);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, const String& pFilename);
JRESULT getSdJpgSize(uint16_t *w, uint16_t *h, File inFile);
#endif
#ifdef TJPGD_LOAD_FFS
JRESULT drawFsJpg (int32_t x, int32_t y, const char *pFilename, fs::FS &fs = SPIFFS);
JRESULT drawFsJpg (int32_t x, int32_t y, const String& pFilename, fs::FS &fs = SPIFFS);
JRESULT drawFsJpg (int32_t x, int32_t y, fs::File inFile);
JRESULT getFsJpgSize(uint16_t *w, uint16_t *h, const char *pFilename, fs::FS &fs = SPIFFS);
JRESULT getFsJpgSize(uint16_t *w, uint16_t *h, const String& pFilename, fs::FS &fs = SPIFFS);
JRESULT getFsJpgSize(uint16_t *w, uint16_t *h, fs::File inFile);
#endif
JRESULT drawJpg(int32_t x, int32_t y, const uint8_t array[], uint32_t array_size);
JRESULT getJpgSize(uint16_t *w, uint16_t *h, const uint8_t array[], uint32_t array_size);
void setSwapBytes(bool swap);
bool _swap = false;
const uint8_t* array_data = nullptr;
uint32_t array_index = 0;
uint32_t array_size = 0;
// Must align workspace to a 32 bit boundary
uint8_t workspace[TJPGD_WORKSPACE_SIZE] __attribute__((aligned(4)));
uint8_t jpg_source = 0;
int16_t jpeg_x = 0;
int16_t jpeg_y = 0;
uint8_t jpgScale = 0;
SketchCallback tft_output = nullptr;
TJpg_Decoder *thisPtr = nullptr;
};
extern TJpg_Decoder TJpgDec;
#endif // TJpg_Decoder_H

View File

@@ -0,0 +1,5 @@
#if defined (ESP32) || defined (ESP8266) || (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)
#define TJPGD_LOAD_FFS
#endif
#define TJPGD_LOAD_SD_LIBRARY

1166
lib/TJpg_Decoder/src/tjpgd.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/*----------------------------------------------------------------------------/
/ TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021
/----------------------------------------------------------------------------*/
#ifndef DEF_TJPGDEC
#define DEF_TJPGDEC
#ifdef __cplusplus
extern "C" {
#endif
#include "tjpgdcnf.h"
#include <string.h>
#if defined(_WIN32) /* VC++ or some compiler without stdint.h */
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef unsigned long uint32_t;
typedef long int32_t;
#else /* Embedded platform */
#include <stdint.h>
#endif
#if JD_FASTDECODE >= 1
typedef int16_t jd_yuv_t;
#else
typedef uint8_t jd_yuv_t;
#endif
/* Error code */
typedef enum {
JDR_OK = 0, /* 0: Succeeded */
JDR_INTR, /* 1: Interrupted by output function */
JDR_INP, /* 2: Device error or wrong termination of input stream */
JDR_MEM1, /* 3: Insufficient memory pool for the image */
JDR_MEM2, /* 4: Insufficient stream input buffer */
JDR_PAR, /* 5: Parameter error */
JDR_FMT1, /* 6: Data format error (may be broken data) */
JDR_FMT2, /* 7: Right format but not supported */
JDR_FMT3 /* 8: Not supported JPEG standard */
} JRESULT;
/* Rectangular region in the output image */
typedef struct {
uint16_t left; /* Left end */
uint16_t right; /* Right end */
uint16_t top; /* Top end */
uint16_t bottom; /* Bottom end */
} JRECT;
/* Decompressor object structure */
typedef struct JDEC JDEC;
struct JDEC {
size_t dctr; /* Number of bytes available in the input buffer */
uint8_t* dptr; /* Current data read ptr */
uint8_t* inbuf; /* Bit stream input buffer */
uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */
uint8_t scale; /* Output scaling ratio */
uint8_t msx, msy; /* MCU size in unit of block (width, height) */
uint8_t qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */
uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */
int16_t dcv[3]; /* Previous DC element of each component */
uint16_t nrst; /* Restart inverval */
uint16_t width, height; /* Size of the input image (pixel) */
uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */
uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */
uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */
int32_t* qttbl[4]; /* Dequantizer tables [id] */
#if JD_FASTDECODE >= 1
uint32_t wreg; /* Working shift register */
uint8_t marker; /* Detected marker (0:None) */
#if JD_FASTDECODE == 2
uint8_t longofs[2][2]; /* Table offset of long code [id][dcac] */
uint16_t* hufflut_ac[2]; /* Fast huffman decode tables for AC short code [id] */
uint8_t* hufflut_dc[2]; /* Fast huffman decode tables for DC short code [id] */
#endif
#endif
void* workbuf; /* Working buffer for IDCT and RGB output */
jd_yuv_t* mcubuf; /* Working buffer for the MCU */
void* pool; /* Pointer to available memory pool */
size_t sz_pool; /* Size of momory pool (bytes available) */
size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */
void* device; /* Pointer to I/O device identifiler for the session */
uint8_t swap; /* Added by Bodmer to control byte swapping */
};
/* TJpgDec API functions */
JRESULT jd_prepare (JDEC* jd, size_t (*infunc)(JDEC*,uint8_t*,size_t), void* pool, size_t sz_pool, void* dev);
JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale);
#ifdef __cplusplus
}
#endif
#endif /* _TJPGDEC */

View File

@@ -0,0 +1,44 @@
/*----------------------------------------------*/
/* TJpgDec System Configurations R0.03 */
/*----------------------------------------------*/
#define JD_SZBUF 512
/* Specifies size of stream input buffer */
#define JD_FORMAT 1
/* Specifies output pixel format.
/ 0: RGB888 (24-bit/pix)
/ 1: RGB565 (16-bit/pix)
/ 2: Grayscale (8-bit/pix)
*/
#define JD_USE_SCALE 1
/* Switches output descaling feature.
/ 0: Disable
/ 1: Enable
*/
#define JD_TBLCLIP 0
/* Use table conversion for saturation arithmetic. A bit faster, but increases 1 KB of code size.
/ 0: Disable
/ 1: Enable
*/
#define JD_FASTDECODE 1
/* Optimization level
/ 0: Basic optimization. Suitable for 8/16-bit MCUs.
/ Workspace of 3100 bytes needed.
/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs.
/ Workspace of 3480 bytes needed.
/ 2: + Table conversion for huffman decoding (wants 6 << HUFF_BIT bytes of RAM).
/ Workspace of 9644 bytes needed.
*/
// Do not change this, it is the minimum size in bytes of the workspace needed by the decoder
#if JD_FASTDECODE == 0
#define TJPGD_WORKSPACE_SIZE 3100
#elif JD_FASTDECODE == 1
#define TJPGD_WORKSPACE_SIZE 3500
#elif JD_FASTDECODE == 2
#define TJPGD_WORKSPACE_SIZE (3500 + 6144)
#endif