mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
Merge branch 'refactor/rom_tjpgd_unify' into 'master'
refactor/rom: unify tjpgd library Closes IDF-3615 See merge request espressif/esp-idf!14977
This commit is contained in:
@@ -15,7 +15,8 @@ else()
|
|||||||
list(APPEND include_dirs "${target}")
|
list(APPEND include_dirs "${target}")
|
||||||
list(APPEND sources "patches/esp_rom_crc.c"
|
list(APPEND sources "patches/esp_rom_crc.c"
|
||||||
"patches/esp_rom_sys.c"
|
"patches/esp_rom_sys.c"
|
||||||
"patches/esp_rom_uart.c")
|
"patches/esp_rom_uart.c"
|
||||||
|
"patches/esp_rom_tjpgd.c")
|
||||||
list(APPEND private_required_comp soc hal)
|
list(APPEND private_required_comp soc hal)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -2,6 +2,11 @@
|
|||||||
* ROM APIs
|
* ROM APIs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* user may provide newer version of tjpgd */
|
||||||
|
/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */
|
||||||
|
PROVIDE ( esp_rom_tjpgd_decomp = 0x400613e8 );
|
||||||
|
PROVIDE ( esp_rom_tjpgd_prepare = 0x40060fa8 );
|
||||||
|
|
||||||
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
||||||
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
||||||
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
/** ROM APIs
|
/** ROM APIs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* user may provide newer version of tjpgd */
|
||||||
|
/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */
|
||||||
|
PROVIDE ( esp_rom_tjpgd_decomp = 0x40000108 );
|
||||||
|
PROVIDE ( esp_rom_tjpgd_prepare = 0x40000104 );
|
||||||
|
|
||||||
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
||||||
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
||||||
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
||||||
|
@@ -89,8 +89,8 @@ tinfl_decompress_mem_to_mem = 0x40000100;
|
|||||||
***************************************/
|
***************************************/
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
jd_prepare = 0x40000104;
|
PROVIDE( jd_prepare = 0x40000104 );
|
||||||
jd_decomp = 0x40000108;
|
PROVIDE( jd_decomp = 0x40000108 );
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
/** ROM APIs
|
/** ROM APIs
|
||||||
*/
|
*/
|
||||||
|
PROVIDE ( esp_rom_tjpgd_decomp = 0x40000104 );
|
||||||
|
PROVIDE ( esp_rom_tjpgd_prepare = 0x40000100 );
|
||||||
|
|
||||||
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
||||||
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
||||||
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
||||||
|
@@ -88,8 +88,8 @@ tinfl_decompress_mem_to_mem = 0x400000fc;
|
|||||||
***************************************/
|
***************************************/
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
jd_prepare = 0x40000100;
|
PROVIDE( jd_prepare = 0x40000100 );
|
||||||
jd_decomp = 0x40000104;
|
PROVIDE( jd_decomp = 0x40000104 );
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
@@ -2,6 +2,11 @@
|
|||||||
* ROM APIs
|
* ROM APIs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* user may provide newer version of tjpgd */
|
||||||
|
/* so here directly assign the symbols with the ROM API address to make sure one from rom is correctly linked */
|
||||||
|
PROVIDE ( esp_rom_tjpgd_decomp = 0x40000864 );
|
||||||
|
PROVIDE ( esp_rom_tjpgd_prepare = 0x40000858 );
|
||||||
|
|
||||||
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
PROVIDE ( esp_rom_crc32_le = crc32_le );
|
||||||
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
PROVIDE ( esp_rom_crc16_le = crc16_le );
|
||||||
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
PROVIDE ( esp_rom_crc8_le = crc8_le );
|
||||||
|
@@ -91,8 +91,8 @@ tinfl_decompress_mem_to_mem = 0x4000084c;
|
|||||||
***************************************/
|
***************************************/
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
jd_prepare = 0x40000858;
|
PROVIDE( jd_prepare = 0x40000858 );
|
||||||
jd_decomp = 0x40000864;
|
PROVIDE (jd_decomp = 0x40000864 );
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
152
components/esp_rom/include/esp_rom_tjpgd.h
Normal file
152
components/esp_rom/include/esp_rom_tjpgd.h
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------/
|
||||||
|
/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012
|
||||||
|
/-----------------------------------------------------------------------------/
|
||||||
|
/ 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) 2012, 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.
|
||||||
|
/
|
||||||
|
/-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#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 damaged data) */
|
||||||
|
JDR_FMT2, /* 7: Right format but not supported */
|
||||||
|
JDR_FMT3 /* 8: Not supported JPEG standard */
|
||||||
|
} esp_rom_tjpgd_result_t;
|
||||||
|
|
||||||
|
/* Rectangular structure */
|
||||||
|
typedef struct {
|
||||||
|
uint16_t left; /* Left end */
|
||||||
|
uint16_t right; /* Right end */
|
||||||
|
uint16_t top; /* Top end */
|
||||||
|
uint16_t bottom;/* Bottom end */
|
||||||
|
} esp_rom_tjpgd_rect_t;
|
||||||
|
|
||||||
|
typedef struct JDEC_s esp_rom_tjpgd_dec_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of user defined input function to read data from input stream
|
||||||
|
* @param dec Specifies the decompression object of the decompression session
|
||||||
|
* @param buffer Specifies the pointer to the read buffer to store the read data. A NULL specifies to remove the data from input stream
|
||||||
|
* @param ndata Specifies number of bytes to read/remove from the input stream
|
||||||
|
*
|
||||||
|
* @return number of bytes read/removed. When a zero is returned, the esp_rom_tjpgd_prepare and esp_rom_tjpgd_decomp function aborts with JDR_INP
|
||||||
|
*/
|
||||||
|
typedef uint32_t (*esp_rom_tjpgd_input_function_t)(esp_rom_tjpgd_dec_t *dec, uint8_t *buffer, uint32_t ndata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief User defined output function to write decompressed pixels to the output device
|
||||||
|
*
|
||||||
|
* This function is the data output interface of the TJpgDec module.
|
||||||
|
* The corresponding decompression session can be identified by the pointer to the device identifier jdec->device passed to the 5th argument of jd_prepare function.
|
||||||
|
* The bitmap is sent to the frame buffer or display device in this function.
|
||||||
|
* The first pixel in the bitmap is the left-top of the rectangular, the second one is next right and last pixel is the bottom-right of the rectangular.
|
||||||
|
* The size of rectangular varies from 1x1 to 16x16 depends on clipping, scaling and sampling factor of the image.
|
||||||
|
* If the rectangular is out of the frame buffer, it should be clipped in this function.
|
||||||
|
*
|
||||||
|
* The pixel format is currently configured to RGB888
|
||||||
|
*
|
||||||
|
* @param dec Specifies the decompression object of the decompression session
|
||||||
|
* @param bitmap Specifies the RGB bitmap to be output
|
||||||
|
* @param rect Specifies rectangular region in the image to output the RGB bitmap
|
||||||
|
*
|
||||||
|
* @return Normally returns 1. It lets TJpgDec to continue the decompressing process.
|
||||||
|
* When a 0 is returned, the esp_rom_tjpgd_decomp function aborts with JDR_INTR.
|
||||||
|
* This is useful to interrupt the decompression process
|
||||||
|
*/
|
||||||
|
typedef uint32_t (*esp_rom_tjpgd_output_function_t)(esp_rom_tjpgd_dec_t *dec, void *bitmap, esp_rom_tjpgd_rect_t *rect);
|
||||||
|
|
||||||
|
struct JDEC_s {
|
||||||
|
uint32_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 dmsk; /* Current bit in the current read byte */
|
||||||
|
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 */
|
||||||
|
int16_t dcv[3]; /* Previous DC element of each component */
|
||||||
|
uint16_t nrst; /* Restart inverval */
|
||||||
|
uint32_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]; /* Dequaitizer tables [id] */
|
||||||
|
void *workbuf; /* Working buffer for IDCT and RGB output */
|
||||||
|
uint8_t *mcubuf; /* Working buffer for the MCU */
|
||||||
|
void *pool; /* Pointer to available memory pool */
|
||||||
|
uint32_t sz_pool; /* Size of momory pool (bytes available) */
|
||||||
|
esp_rom_tjpgd_input_function_t infunc; /* Pointer to jpeg stream input function */
|
||||||
|
void *device; /* Pointer to I/O device identifiler for the session */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TJpgDec API functions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Analyzes the JPEG data and create a decompression object for subsequent decompression process.
|
||||||
|
* @param dec Specifies the decompression object to be initialized. The decompression object is used for subsequent decompression process.
|
||||||
|
* @param infunc Specifies the user defined data input function.
|
||||||
|
* @param work Specifies pointer to the work area for this session. It should be aligned to word boundary or it can result an exception.
|
||||||
|
* @param sz_work Specifies size of the work area in unit of byte.
|
||||||
|
* TJpgDec requires upto 3092 bytes of work area depends on the built-in parameter tables of the JPEG image.
|
||||||
|
* Thus 3092 bytes of work area is sufficient for most case.
|
||||||
|
* @param dev Specifies pointer to the user defined device identifier for this session.
|
||||||
|
* It is stored to the member device in the decompression object. It can be referred by I/O functions to identify the current session.
|
||||||
|
* When I/O device is fixed in the project or this feature is not needed, set NULL and do not care about this.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - JDR_OK Function succeeded and decompression object is valid.
|
||||||
|
* - JDR_INP An error occurred in input function due to hard error or wrong stream termination.
|
||||||
|
* - JDR_MEM1 Insufficient work area for this JPEG image.
|
||||||
|
* - JDR_MEM2 Insufficient input buffer for this JPEG image. JD_SZBUF may be too small.
|
||||||
|
* - JDR_PAR Parameter error. Given pointer to the work area is NULL.
|
||||||
|
* - JDR_FMT1 Data format error. The JPEG data can be collapsed.
|
||||||
|
* - JDR_FMT2 Right format but not supported. May be a grayscale image.
|
||||||
|
* - JDR_FMT3 Not supported JPEG standard. May be a progressive JPEG image.
|
||||||
|
*/
|
||||||
|
esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_input_function_t infunc, void *work, uint32_t sz_work, void *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decompress the JPEG image and output it as RGB data.
|
||||||
|
* @param dec Specifies the valid decompressor object.
|
||||||
|
* @param outfunc Specifies the user defined data output function. The esp_rom_tjpgd_decomp function calls this function to output the decompressed JPEG image in RGB form.
|
||||||
|
* @param scale Specifies scaling factor N for output. The output image is descaled to 1 / 2 ^ N (N = 0 to 3).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - JDR_OK Function succeeded.
|
||||||
|
* - JDR_INTR The decompression process is interrupted by output function.
|
||||||
|
* - JDR_INP An error occured in input function due to hard error or wrong stream termination.
|
||||||
|
* - JDR_PAR Parameter error. Given scale factor is invalid.
|
||||||
|
* - JDR_FMT1 Data format error. The JPEG data can be collapted.
|
||||||
|
*/
|
||||||
|
esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp(esp_rom_tjpgd_dec_t *dec, esp_rom_tjpgd_output_function_t outfunc, uint8_t scale);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,11 +1,11 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ TJpgDec - Tiny JPEG Decompressor R0.01c (C)ChaN, 2019
|
/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
|
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
|
||||||
/ This is a free software that opened for education, research and commercial
|
/ This is a free software that opened for education, research and commercial
|
||||||
/ developments under license policy of following terms.
|
/ developments under license policy of following terms.
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2019, ChaN, all right reserved.
|
/ Copyright (C) 2012, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ * The TJpgDec module is a free software and there is NO WARRANTY.
|
/ * The TJpgDec module is a free software and there is NO WARRANTY.
|
||||||
/ * No restriction on use. You can use, modify and redistribute it for
|
/ * No restriction on use. You can use, modify and redistribute it for
|
||||||
@@ -13,13 +13,21 @@
|
|||||||
/ * Redistributions of source code must retain the above copyright notice.
|
/ * Redistributions of source code must retain the above copyright notice.
|
||||||
/
|
/
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/ Oct 04, 2011 R0.01 First release.
|
/ Oct 04,'11 R0.01 First release.
|
||||||
/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq.
|
/ Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq.
|
||||||
/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option.
|
/ Sep 03,'12 R0.01b Added JD_TBLCLIP option.
|
||||||
/ Mar 16, 2019 R0.01c Supprted stdint.h.
|
|
||||||
/----------------------------------------------------------------------------*/
|
/----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "tjpgd.h"
|
#include "esp_rom_caps.h"
|
||||||
|
|
||||||
|
#if !ESP_ROM_HAS_JPEG_DECODE
|
||||||
|
|
||||||
|
#include "esp_rom_tjpgd.h"
|
||||||
|
|
||||||
|
#define JD_SZBUF 512 /* Size of stream input buffer */
|
||||||
|
#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */
|
||||||
|
#define JD_USE_SCALE 1 /* Use descaling feature for output */
|
||||||
|
#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------*/
|
/*-----------------------------------------------*/
|
||||||
@@ -28,7 +36,8 @@
|
|||||||
|
|
||||||
#define ZIG(n) Zig[n]
|
#define ZIG(n) Zig[n]
|
||||||
|
|
||||||
static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */
|
static
|
||||||
|
const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion table */
|
||||||
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
|
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
|
||||||
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
|
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
|
||||||
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
|
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
|
||||||
@@ -44,7 +53,8 @@ static const uint8_t Zig[64] = { /* Zigzag-order to raster-order conversion tabl
|
|||||||
|
|
||||||
#define IPSF(n) Ipsf[n]
|
#define IPSF(n) Ipsf[n]
|
||||||
|
|
||||||
static const uint16_t Ipsf[64] = { /* See also aa_idct.png */
|
static
|
||||||
|
const uint16_t Ipsf[64] = { /* See also aa_idct.png */
|
||||||
(uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192),
|
(uint16_t)(1.00000*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.17588*8192), (uint16_t)(1.00000*8192), (uint16_t)(0.78570*8192), (uint16_t)(0.54120*8192), (uint16_t)(0.27590*8192),
|
||||||
(uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192),
|
(uint16_t)(1.38704*8192), (uint16_t)(1.92388*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.63099*8192), (uint16_t)(1.38704*8192), (uint16_t)(1.08979*8192), (uint16_t)(0.75066*8192), (uint16_t)(0.38268*8192),
|
||||||
(uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192),
|
(uint16_t)(1.30656*8192), (uint16_t)(1.81226*8192), (uint16_t)(1.70711*8192), (uint16_t)(1.53636*8192), (uint16_t)(1.30656*8192), (uint16_t)(1.02656*8192), (uint16_t)(0.70711*8192), (uint16_t)(0.36048*8192),
|
||||||
@@ -63,9 +73,10 @@ static const uint16_t Ipsf[64] = { /* See also aa_idct.png */
|
|||||||
|
|
||||||
#if JD_TBLCLIP
|
#if JD_TBLCLIP
|
||||||
|
|
||||||
#define BYTECLIP(v) Clip8[(uint16_t)(v) & 0x3FF]
|
#define BYTECLIP(v) Clip8[(uint32_t)(v) & 0x3FF]
|
||||||
|
|
||||||
static const uint8_t Clip8[1024] = {
|
static
|
||||||
|
const uint8_t Clip8[1024] = {
|
||||||
/* 0..255 */
|
/* 0..255 */
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||||
@@ -106,8 +117,9 @@ static const uint8_t Clip8[1024] = {
|
|||||||
|
|
||||||
#else /* JD_TBLCLIP */
|
#else /* JD_TBLCLIP */
|
||||||
|
|
||||||
inline uint8_t BYTECLIP (
|
inline
|
||||||
int16_t val
|
uint8_t BYTECLIP (
|
||||||
|
int32_t val
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (val < 0) val = 0;
|
if (val < 0) val = 0;
|
||||||
@@ -124,9 +136,10 @@ inline uint8_t BYTECLIP (
|
|||||||
/* Allocate a memory block from memory pool */
|
/* Allocate a memory block from memory pool */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */
|
||||||
uint16_t nd /* Number of bytes to allocate */
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
|
uint32_t nd /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
char *rp = 0;
|
char *rp = 0;
|
||||||
@@ -150,13 +163,14 @@ static void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory a
|
|||||||
/* Create de-quantization and prescaling tables with a DQT segment */
|
/* Create de-quantization and prescaling tables with a DQT segment */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int create_qt_tbl ( /* 0:OK, !0:Failed */
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
uint32_t create_qt_tbl ( /* 0:OK, !0:Failed */
|
||||||
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
const uint8_t* data, /* Pointer to the quantizer tables */
|
const uint8_t* data, /* Pointer to the quantizer tables */
|
||||||
uint16_t ndata /* Size of input data */
|
uint32_t ndata /* Size of input data */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint16_t i;
|
uint32_t i;
|
||||||
uint8_t d, z;
|
uint8_t d, z;
|
||||||
int32_t *pb;
|
int32_t *pb;
|
||||||
|
|
||||||
@@ -186,13 +200,14 @@ static int create_qt_tbl ( /* 0:OK, !0:Failed */
|
|||||||
/* Create huffman code tables with a DHT segment */
|
/* Create huffman code tables with a DHT segment */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int create_huffman_tbl ( /* 0:OK, !0:Failed */
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
uint32_t create_huffman_tbl ( /* 0:OK, !0:Failed */
|
||||||
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
const uint8_t* data, /* Pointer to the packed huffman tables */
|
const uint8_t* data, /* Pointer to the packed huffman tables */
|
||||||
uint16_t ndata /* Size of input data */
|
uint32_t ndata /* Size of input data */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint16_t i, j, b, np, cls, num;
|
uint32_t i, j, b, np, cls, num;
|
||||||
uint8_t d, *pb, *pd;
|
uint8_t d, *pb, *pd;
|
||||||
uint16_t hc, *ph;
|
uint16_t hc, *ph;
|
||||||
|
|
||||||
@@ -201,15 +216,17 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */
|
|||||||
if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */
|
if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */
|
||||||
ndata -= 17;
|
ndata -= 17;
|
||||||
d = *data++; /* Get table number and class */
|
d = *data++; /* Get table number and class */
|
||||||
|
cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */
|
||||||
if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */
|
if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */
|
||||||
cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */
|
|
||||||
pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */
|
pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */
|
||||||
if (!pb) return JDR_MEM1; /* Err: not enough memory */
|
if (!pb) return JDR_MEM1; /* Err: not enough memory */
|
||||||
jd->huffbits[num][cls] = pb;
|
jd->huffbits[num][cls] = pb;
|
||||||
for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */
|
for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */
|
||||||
np += (pb[i] = *data++); /* Get sum of code words for each code */
|
pb[i] = b = *data++;
|
||||||
|
np += b; /* Get sum of code words for each code */
|
||||||
}
|
}
|
||||||
ph = alloc_pool(jd, (uint16_t)(np * sizeof (uint16_t)));/* Allocate a memory block for the code word table */
|
|
||||||
|
ph = alloc_pool(jd, np * sizeof (uint16_t));/* Allocate a memory block for the code word table */
|
||||||
if (!ph) return JDR_MEM1; /* Err: not enough memory */
|
if (!ph) return JDR_MEM1; /* Err: not enough memory */
|
||||||
jd->huffcode[num][cls] = ph;
|
jd->huffcode[num][cls] = ph;
|
||||||
hc = 0;
|
hc = 0;
|
||||||
@@ -241,13 +258,14 @@ static int create_huffman_tbl ( /* 0:OK, !0:Failed */
|
|||||||
/* Extract N bits from input stream */
|
/* Extract N bits from input stream */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int bitext ( /* >=0: extracted data, <0: error code */
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
int32_t bitext ( /* >=0: extracted data, <0: error code */
|
||||||
int nbit /* Number of bits to extract (1 to 11) */
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
|
uint32_t nbit /* Number of bits to extract (1 to 11) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint8_t msk, s, *dp;
|
uint8_t msk, s, *dp;
|
||||||
uint16_t dc, v, f;
|
uint32_t dc, v, f;
|
||||||
|
|
||||||
|
|
||||||
msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
|
msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
|
||||||
@@ -257,14 +275,14 @@ static int bitext ( /* >=0: extracted data, <0: error code */
|
|||||||
if (!dc) { /* No input data is available, re-fill input buffer */
|
if (!dc) { /* No input data is available, re-fill input buffer */
|
||||||
dp = jd->inbuf; /* Top of input buffer */
|
dp = jd->inbuf; /* Top of input buffer */
|
||||||
dc = jd->infunc(jd, dp, JD_SZBUF);
|
dc = jd->infunc(jd, dp, JD_SZBUF);
|
||||||
if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */
|
if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */
|
||||||
} else {
|
} else {
|
||||||
dp++; /* Next data ptr */
|
dp++; /* Next data ptr */
|
||||||
}
|
}
|
||||||
dc--; /* Decrement number of available bytes */
|
dc--; /* Decrement number of available bytes */
|
||||||
if (f) { /* In flag sequence? */
|
if (f) { /* In flag sequence? */
|
||||||
f = 0; /* Exit flag sequence */
|
f = 0; /* Exit flag sequence */
|
||||||
if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
|
if (*dp != 0) return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
|
||||||
*dp = s = 0xFF; /* The flag is a data 0xFF */
|
*dp = s = 0xFF; /* The flag is a data 0xFF */
|
||||||
} else {
|
} else {
|
||||||
s = *dp; /* Get next data byte */
|
s = *dp; /* Get next data byte */
|
||||||
@@ -281,7 +299,7 @@ static int bitext ( /* >=0: extracted data, <0: error code */
|
|||||||
} while (nbit);
|
} while (nbit);
|
||||||
jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp;
|
jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp;
|
||||||
|
|
||||||
return (int)v;
|
return (int32_t)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -291,15 +309,16 @@ static int bitext ( /* >=0: extracted data, <0: error code */
|
|||||||
/* Extract a huffman decoded data from input stream */
|
/* Extract a huffman decoded data from input stream */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int16_t huffext ( /* >=0: decoded data, <0: error code */
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
int32_t huffext ( /* >=0: decoded data, <0: error code */
|
||||||
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
const uint8_t* hbits, /* Pointer to the bit distribution table */
|
const uint8_t* hbits, /* Pointer to the bit distribution table */
|
||||||
const uint16_t* hcode, /* Pointer to the code word table */
|
const uint16_t* hcode, /* Pointer to the code word table */
|
||||||
const uint8_t* hdata /* Pointer to the data table */
|
const uint8_t* hdata /* Pointer to the data table */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint8_t msk, s, *dp;
|
uint8_t msk, s, *dp;
|
||||||
uint16_t dc, v, f, bl, nd;
|
uint32_t dc, v, f, bl, nd;
|
||||||
|
|
||||||
|
|
||||||
msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
|
msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */
|
||||||
@@ -310,14 +329,15 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */
|
|||||||
if (!dc) { /* No input data is available, re-fill input buffer */
|
if (!dc) { /* No input data is available, re-fill input buffer */
|
||||||
dp = jd->inbuf; /* Top of input buffer */
|
dp = jd->inbuf; /* Top of input buffer */
|
||||||
dc = jd->infunc(jd, dp, JD_SZBUF);
|
dc = jd->infunc(jd, dp, JD_SZBUF);
|
||||||
if (!dc) return 0 - (int16_t)JDR_INP; /* Err: read error or wrong stream termination */
|
if (!dc) return 0 - (int32_t)JDR_INP; /* Err: read error or wrong stream termination */
|
||||||
} else {
|
} else {
|
||||||
dp++; /* Next data ptr */
|
dp++; /* Next data ptr */
|
||||||
}
|
}
|
||||||
dc--; /* Decrement number of available bytes */
|
dc--; /* Decrement number of available bytes */
|
||||||
if (f) { /* In flag sequence? */
|
if (f) { /* In flag sequence? */
|
||||||
f = 0; /* Exit flag sequence */
|
f = 0; /* Exit flag sequence */
|
||||||
if (*dp != 0) return 0 - (int16_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
|
if (*dp != 0)
|
||||||
|
return 0 - (int32_t)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
|
||||||
*dp = s = 0xFF; /* The flag is a data 0xFF */
|
*dp = s = 0xFF; /* The flag is a data 0xFF */
|
||||||
} else {
|
} else {
|
||||||
s = *dp; /* Get next data byte */
|
s = *dp; /* Get next data byte */
|
||||||
@@ -341,7 +361,7 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */
|
|||||||
bl--;
|
bl--;
|
||||||
} while (bl);
|
} while (bl);
|
||||||
|
|
||||||
return 0 - (int16_t)JDR_FMT1; /* Err: code not found (may be collapted data) */
|
return 0 - (int32_t)JDR_FMT1; /* Err: code not found (may be collapted data) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -351,7 +371,8 @@ static int16_t huffext ( /* >=0: decoded data, <0: error code */
|
|||||||
/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */
|
/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void block_idct (
|
static
|
||||||
|
void block_idct (
|
||||||
int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */
|
int32_t* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */
|
||||||
uint8_t* dst /* Pointer to the destination to store the block as byte array */
|
uint8_t* dst /* Pointer to the destination to store the block as byte array */
|
||||||
)
|
)
|
||||||
@@ -359,7 +380,7 @@ static void block_idct (
|
|||||||
const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096);
|
const int32_t M13 = (int32_t)(1.41421*4096), M2 = (int32_t)(1.08239*4096), M4 = (int32_t)(2.61313*4096), M5 = (int32_t)(1.84776*4096);
|
||||||
int32_t v0, v1, v2, v3, v4, v5, v6, v7;
|
int32_t v0, v1, v2, v3, v4, v5, v6, v7;
|
||||||
int32_t t10, t11, t12, t13;
|
int32_t t10, t11, t12, t13;
|
||||||
uint16_t i;
|
uint32_t i;
|
||||||
|
|
||||||
/* Process columns */
|
/* Process columns */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
@@ -463,13 +484,14 @@ static void block_idct (
|
|||||||
/* Load all blocks in the MCU into working buffer */
|
/* Load all blocks in the MCU into working buffer */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static JRESULT mcu_load (
|
static
|
||||||
JDEC* jd /* Pointer to the decompressor object */
|
esp_rom_tjpgd_result_t mcu_load (
|
||||||
|
esp_rom_tjpgd_dec_t* jd /* Pointer to the decompressor object */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */
|
int32_t *tmp = (int32_t*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */
|
||||||
int b, d, e;
|
uint32_t blk, nby, nbc, i, z, id, cmp;
|
||||||
uint16_t blk, nby, nbc, i, z, id, cmp;
|
int32_t b, d, e;
|
||||||
uint8_t *bp;
|
uint8_t *bp;
|
||||||
const uint8_t *hb, *hd;
|
const uint8_t *hb, *hd;
|
||||||
const uint16_t *hc;
|
const uint16_t *hc;
|
||||||
@@ -503,7 +525,7 @@ static JRESULT mcu_load (
|
|||||||
tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
|
tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */
|
||||||
|
|
||||||
/* Extract following 63 AC elements from input stream */
|
/* Extract following 63 AC elements from input stream */
|
||||||
for (i = 1; i < 64; tmp[i++] = 0) ; /* Clear rest of elements */
|
for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */
|
||||||
hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */
|
hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */
|
||||||
hc = jd->huffcode[id][1];
|
hc = jd->huffcode[id][1];
|
||||||
hd = jd->huffdata[id][1];
|
hd = jd->huffdata[id][1];
|
||||||
@@ -512,7 +534,7 @@ static JRESULT mcu_load (
|
|||||||
b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */
|
b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */
|
||||||
if (b == 0) break; /* EOB? */
|
if (b == 0) break; /* EOB? */
|
||||||
if (b < 0) return 0 - b; /* Err: invalid code or input error */
|
if (b < 0) return 0 - b; /* Err: invalid code or input error */
|
||||||
z = (uint16_t)b >> 4; /* Number of leading zero elements */
|
z = (uint32_t)b >> 4; /* Number of leading zero elements */
|
||||||
if (z) {
|
if (z) {
|
||||||
i += z; /* Skip zero elements */
|
i += z; /* Skip zero elements */
|
||||||
if (i >= 64) return JDR_FMT1; /* Too long zero run */
|
if (i >= 64) return JDR_FMT1; /* Too long zero run */
|
||||||
@@ -527,11 +549,10 @@ static JRESULT mcu_load (
|
|||||||
}
|
}
|
||||||
} while (++i < 64); /* Next AC element */
|
} while (++i < 64); /* Next AC element */
|
||||||
|
|
||||||
if (JD_USE_SCALE && jd->scale == 3) {
|
if (JD_USE_SCALE && jd->scale == 3)
|
||||||
*bp = (uint8_t)((*tmp / 256) + 128); /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */
|
*bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */
|
||||||
} else {
|
else
|
||||||
block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */
|
block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */
|
||||||
}
|
|
||||||
|
|
||||||
bp += 64; /* Next block */
|
bp += 64; /* Next block */
|
||||||
}
|
}
|
||||||
@@ -546,18 +567,19 @@ static JRESULT mcu_load (
|
|||||||
/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */
|
/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static JRESULT mcu_output (
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
esp_rom_tjpgd_result_t mcu_output (
|
||||||
uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
uint16_t x, /* MCU position in the image (left of the MCU) */
|
uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */
|
||||||
uint16_t y /* MCU position in the image (top of the MCU) */
|
uint32_t x, /* MCU position in the image (left of the MCU) */
|
||||||
|
uint32_t y /* MCU position in the image (top of the MCU) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const int16_t CVACC = (sizeof (int16_t) > 2) ? 1024 : 128;
|
const int32_t CVACC = (sizeof (int32_t) > 2) ? 1024 : 128;
|
||||||
uint16_t ix, iy, mx, my, rx, ry;
|
uint32_t ix, iy, mx, my, rx, ry;
|
||||||
int16_t yy, cb, cr;
|
int32_t yy, cb, cr;
|
||||||
uint8_t *py, *pc, *rgb24;
|
uint8_t *py, *pc, *rgb24;
|
||||||
JRECT rect;
|
esp_rom_tjpgd_rect_t rect;
|
||||||
|
|
||||||
|
|
||||||
mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */
|
mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */
|
||||||
@@ -597,15 +619,15 @@ static JRESULT mcu_output (
|
|||||||
yy = *py++; /* Get Y component */
|
yy = *py++; /* Get Y component */
|
||||||
|
|
||||||
/* Convert YCbCr to RGB */
|
/* Convert YCbCr to RGB */
|
||||||
*rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr) / CVACC);
|
*rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr) / CVACC);
|
||||||
*rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC);
|
*rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC);
|
||||||
*rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb) / CVACC);
|
*rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb) / CVACC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Descale the MCU rectangular if needed */
|
/* Descale the MCU rectangular if needed */
|
||||||
if (JD_USE_SCALE && jd->scale) {
|
if (JD_USE_SCALE && jd->scale) {
|
||||||
uint16_t x, y, r, g, b, s, w, a;
|
uint32_t x, y, r, g, b, s, w, a;
|
||||||
uint8_t *op;
|
uint8_t *op;
|
||||||
|
|
||||||
/* Get averaged RGB value of each square correcponds to a pixel */
|
/* Get averaged RGB value of each square correcponds to a pixel */
|
||||||
@@ -647,9 +669,9 @@ static JRESULT mcu_output (
|
|||||||
py += 64;
|
py += 64;
|
||||||
|
|
||||||
/* Convert YCbCr to RGB */
|
/* Convert YCbCr to RGB */
|
||||||
*rgb24++ = /* R */ BYTECLIP(yy + ((int16_t)(1.402 * CVACC) * cr / CVACC));
|
*rgb24++ = /* R */ BYTECLIP(yy + ((int32_t)(1.402 * CVACC) * cr / CVACC));
|
||||||
*rgb24++ = /* G */ BYTECLIP(yy - ((int16_t)(0.344 * CVACC) * cb + (int16_t)(0.714 * CVACC) * cr) / CVACC);
|
*rgb24++ = /* G */ BYTECLIP(yy - ((int32_t)(0.344 * CVACC) * cb + (int32_t)(0.714 * CVACC) * cr) / CVACC);
|
||||||
*rgb24++ = /* B */ BYTECLIP(yy + ((int16_t)(1.772 * CVACC) * cb / CVACC));
|
*rgb24++ = /* B */ BYTECLIP(yy + ((int32_t)(1.772 * CVACC) * cb / CVACC));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,7 +680,7 @@ static JRESULT mcu_output (
|
|||||||
mx >>= jd->scale;
|
mx >>= jd->scale;
|
||||||
if (rx < mx) {
|
if (rx < mx) {
|
||||||
uint8_t *s, *d;
|
uint8_t *s, *d;
|
||||||
uint16_t x, y;
|
uint32_t x, y;
|
||||||
|
|
||||||
s = d = (uint8_t*)jd->workbuf;
|
s = d = (uint8_t*)jd->workbuf;
|
||||||
for (y = 0; y < ry; y++) {
|
for (y = 0; y < ry; y++) {
|
||||||
@@ -675,7 +697,7 @@ static JRESULT mcu_output (
|
|||||||
if (JD_FORMAT == 1) {
|
if (JD_FORMAT == 1) {
|
||||||
uint8_t *s = (uint8_t*)jd->workbuf;
|
uint8_t *s = (uint8_t*)jd->workbuf;
|
||||||
uint16_t w, *d = (uint16_t*)s;
|
uint16_t w, *d = (uint16_t*)s;
|
||||||
uint16_t n = rx * ry;
|
uint32_t n = rx * ry;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
w = (*s++ & 0xF8) << 8; /* RRRRR----------- */
|
w = (*s++ & 0xF8) << 8; /* RRRRR----------- */
|
||||||
@@ -696,12 +718,13 @@ static JRESULT mcu_output (
|
|||||||
/* Process restart interval */
|
/* Process restart interval */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
static JRESULT restart (
|
static
|
||||||
JDEC* jd, /* Pointer to the decompressor object */
|
esp_rom_tjpgd_result_t restart (
|
||||||
|
esp_rom_tjpgd_dec_t* jd, /* Pointer to the decompressor object */
|
||||||
uint16_t rstn /* Expected restert sequense number */
|
uint16_t rstn /* Expected restert sequense number */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint16_t i, dc;
|
uint32_t i, dc;
|
||||||
uint16_t d;
|
uint16_t d;
|
||||||
uint8_t *dp;
|
uint8_t *dp;
|
||||||
|
|
||||||
@@ -723,9 +746,8 @@ static JRESULT restart (
|
|||||||
jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0;
|
jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0;
|
||||||
|
|
||||||
/* Check the marker */
|
/* Check the marker */
|
||||||
if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) {
|
if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7))
|
||||||
return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */
|
return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset DC offset */
|
/* Reset DC offset */
|
||||||
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0;
|
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0;
|
||||||
@@ -743,19 +765,19 @@ static JRESULT restart (
|
|||||||
#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1))
|
#define LDB_WORD(ptr) (uint16_t)(((uint16_t)*((uint8_t*)(ptr))<<8)|(uint16_t)*(uint8_t*)((ptr)+1))
|
||||||
|
|
||||||
|
|
||||||
JRESULT jd_prepare (
|
esp_rom_tjpgd_result_t esp_rom_tjpgd_prepare (
|
||||||
JDEC* jd, /* Blank decompressor object */
|
esp_rom_tjpgd_dec_t* jd, /* Blank decompressor object */
|
||||||
uint16_t (*infunc)(JDEC*, uint8_t*, uint16_t), /* JPEG strem input function */
|
uint32_t (*infunc)(esp_rom_tjpgd_dec_t*, uint8_t*, uint32_t), /* JPEG strem input function */
|
||||||
void* pool, /* Working buffer for the decompression session */
|
void* pool, /* Working buffer for the decompression session */
|
||||||
uint16_t sz_pool, /* Size of working buffer */
|
uint32_t sz_pool, /* Size of working buffer */
|
||||||
void* dev /* I/O device identifier for the session */
|
void* dev /* I/O device identifier for the session */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint8_t *seg, b;
|
uint8_t *seg, b;
|
||||||
uint16_t marker;
|
uint16_t marker;
|
||||||
uint32_t ofs;
|
uint32_t ofs;
|
||||||
uint16_t n, i, j, len;
|
uint32_t n, i, j, len;
|
||||||
JRESULT rc;
|
esp_rom_tjpgd_result_t rc;
|
||||||
|
|
||||||
|
|
||||||
if (!pool) return JDR_PAR;
|
if (!pool) return JDR_PAR;
|
||||||
@@ -773,7 +795,7 @@ JRESULT jd_prepare (
|
|||||||
jd->huffdata[i][j] = 0;
|
jd->huffdata[i][j] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < 4; jd->qttbl[i++] = 0) ;
|
for (i = 0; i < 4; i++) jd->qttbl[i] = 0;
|
||||||
|
|
||||||
jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */
|
jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */
|
||||||
if (!seg) return JDR_MEM1;
|
if (!seg) return JDR_MEM1;
|
||||||
@@ -805,9 +827,8 @@ JRESULT jd_prepare (
|
|||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
b = seg[7 + 3 * i]; /* Get sampling factor */
|
b = seg[7 + 3 * i]; /* Get sampling factor */
|
||||||
if (!i) { /* Y component */
|
if (!i) { /* Y component */
|
||||||
if (b != 0x11 && b != 0x22 && b != 0x21) { /* Check sampling factor */
|
if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */
|
||||||
return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */
|
return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */
|
||||||
}
|
|
||||||
jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */
|
jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */
|
||||||
} else { /* Cb/Cr component */
|
} else { /* Cb/Cr component */
|
||||||
if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */
|
if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */
|
||||||
@@ -861,12 +882,9 @@ JRESULT jd_prepare (
|
|||||||
b = seg[2 + 2 * i]; /* Get huffman table ID */
|
b = seg[2 + 2 * i]; /* Get huffman table ID */
|
||||||
if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */
|
if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */
|
||||||
b = i ? 1 : 0;
|
b = i ? 1 : 0;
|
||||||
if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) { /* Check dc/ac huffman table for this component */
|
if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */
|
||||||
return JDR_FMT1; /* Err: Nnot loaded */
|
return JDR_FMT1; /* Err: Huffman table not loaded */
|
||||||
}
|
if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */
|
||||||
if (!jd->qttbl[jd->qtid[i]]) { /* Check dequantizer table for this component */
|
|
||||||
return JDR_FMT1; /* Err: Not loaded */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate working buffer for MCU and RGB */
|
/* Allocate working buffer for MCU and RGB */
|
||||||
@@ -876,13 +894,13 @@ JRESULT jd_prepare (
|
|||||||
if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */
|
if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */
|
||||||
jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */
|
jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */
|
||||||
if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */
|
if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */
|
||||||
jd->mcubuf = (uint8_t*)alloc_pool(jd, (uint16_t)((n + 2) * 64)); /* Allocate MCU working buffer */
|
jd->mcubuf = alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */
|
||||||
if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */
|
if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */
|
||||||
|
|
||||||
/* Pre-load the JPEG data to extract it from the bit stream */
|
/* Pre-load the JPEG data to extract it from the bit stream */
|
||||||
jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */
|
jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */
|
||||||
if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */
|
if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */
|
||||||
jd->dctr = jd->infunc(jd, seg + ofs, (uint16_t)(JD_SZBUF - ofs));
|
jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (uint32_t)ofs);
|
||||||
jd->dptr = seg + ofs - 1;
|
jd->dptr = seg + ofs - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,12 +923,11 @@ JRESULT jd_prepare (
|
|||||||
|
|
||||||
default: /* Unknown segment (comment, exif or etc..) */
|
default: /* Unknown segment (comment, exif or etc..) */
|
||||||
/* Skip segment data */
|
/* Skip segment data */
|
||||||
if (jd->infunc(jd, 0, len) != len) { /* Null pointer specifies to skip bytes of stream */
|
if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */
|
||||||
return JDR_INP;
|
return JDR_INP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -919,15 +936,15 @@ JRESULT jd_prepare (
|
|||||||
/* Start to decompress the JPEG picture */
|
/* Start to decompress the JPEG picture */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
JRESULT jd_decomp (
|
esp_rom_tjpgd_result_t esp_rom_tjpgd_decomp (
|
||||||
JDEC* jd, /* Initialized decompression object */
|
esp_rom_tjpgd_dec_t* jd, /* Initialized decompression object */
|
||||||
uint16_t (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
|
uint32_t (*outfunc)(esp_rom_tjpgd_dec_t*, void*, esp_rom_tjpgd_rect_t*), /* RGB output function */
|
||||||
uint8_t scale /* Output de-scaling factor (0 to 3) */
|
uint8_t scale /* Output de-scaling factor (0 to 3) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint16_t x, y, mx, my;
|
uint32_t x, y, mx, my;
|
||||||
uint16_t rst, rsc;
|
uint16_t rst, rsc;
|
||||||
JRESULT rc;
|
esp_rom_tjpgd_result_t rc;
|
||||||
|
|
||||||
|
|
||||||
if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR;
|
if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR;
|
||||||
@@ -955,3 +972,5 @@ JRESULT jd_decomp (
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // ESP_ROM_HAS_JPEG_DECODE
|
@@ -2,11 +2,9 @@ idf_component_register(SRC_DIRS .
|
|||||||
PRIV_INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR}
|
PRIV_INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
PRIV_REQUIRES cmock test_utils)
|
PRIV_REQUIRES cmock test_utils)
|
||||||
|
|
||||||
if(IDF_TARGET STREQUAL "esp32")
|
|
||||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||||
COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
COMMAND xxd -i "logo.jpg" "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h"
|
||||||
WORKING_DIRECTORY ${COMPONENT_DIR}
|
WORKING_DIRECTORY ${COMPONENT_DIR}
|
||||||
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg")
|
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/logo.jpg")
|
||||||
add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h")
|
add_custom_target(test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h")
|
||||||
add_dependencies(${COMPONENT_LIB} test_logo)
|
add_dependencies(${COMPONENT_LIB} test_logo)
|
||||||
endif()
|
|
||||||
|
@@ -5,9 +5,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#include "esp_rom_tjpgd.h"
|
||||||
|
|
||||||
#include "esp32/rom/tjpgd.h"
|
|
||||||
#include "test_tjpgd_logo.h"
|
#include "test_tjpgd_logo.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -18,7 +16,7 @@ typedef struct {
|
|||||||
int outH;
|
int outH;
|
||||||
} JpegDev;
|
} JpegDev;
|
||||||
|
|
||||||
static UINT infunc(JDEC *decoder, BYTE *buf, UINT len)
|
static uint32_t infunc(esp_rom_tjpgd_dec_t *decoder, uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
JpegDev *jd = (JpegDev *)decoder->device;
|
JpegDev *jd = (JpegDev *)decoder->device;
|
||||||
printf("Reading %d bytes from pos %d\n", len, jd->inPos);
|
printf("Reading %d bytes from pos %d\n", len, jd->inPos);
|
||||||
@@ -29,7 +27,7 @@ static UINT infunc(JDEC *decoder, BYTE *buf, UINT len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect)
|
static uint32_t outfunc(esp_rom_tjpgd_dec_t *decoder, void *bitmap, esp_rom_tjpgd_rect_t *rect)
|
||||||
{
|
{
|
||||||
unsigned char *in = (unsigned char *)bitmap;
|
unsigned char *in = (unsigned char *)bitmap;
|
||||||
unsigned char *out;
|
unsigned char *out;
|
||||||
@@ -55,10 +53,10 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]")
|
|||||||
char *work;
|
char *work;
|
||||||
int r;
|
int r;
|
||||||
int x, y, v;
|
int x, y, v;
|
||||||
JDEC decoder;
|
esp_rom_tjpgd_dec_t decoder;
|
||||||
JpegDev jd;
|
JpegDev jd;
|
||||||
decoded = malloc(48 * 48 * 3);
|
decoded = malloc(TESTW * TESTH * 3);
|
||||||
for (x = 0; x < 48 * 48 * 3; x += 2) {
|
for (x = 0; x < TESTW * TESTH * 3; x += 2) {
|
||||||
decoded[x] = 0;
|
decoded[x] = 0;
|
||||||
decoded[x + 1] = 0xff;
|
decoded[x + 1] = 0xff;
|
||||||
}
|
}
|
||||||
@@ -71,9 +69,9 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]")
|
|||||||
jd.outW = TESTW;
|
jd.outW = TESTW;
|
||||||
jd.outH = TESTH;
|
jd.outH = TESTH;
|
||||||
|
|
||||||
r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
|
r = esp_rom_tjpgd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
|
||||||
TEST_ASSERT_EQUAL(r, JDR_OK);
|
TEST_ASSERT_EQUAL(r, JDR_OK);
|
||||||
r = jd_decomp(&decoder, outfunc, 0);
|
r = esp_rom_tjpgd_decomp(&decoder, outfunc, 0);
|
||||||
TEST_ASSERT_EQUAL(r, JDR_OK);
|
TEST_ASSERT_EQUAL(r, JDR_OK);
|
||||||
|
|
||||||
p = decoded + 2;
|
p = decoded + 2;
|
||||||
@@ -89,5 +87,3 @@ TEST_CASE("Test JPEG decompression library", "[rom][tjpgd]")
|
|||||||
free(work);
|
free(work);
|
||||||
free(decoded);
|
free(decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // #if CONFIG_IDF_TARGET_ESP32
|
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
set(tjpgd_srcs "src/tjpgd.c")
|
|
||||||
|
|
||||||
idf_component_register(SRCS "${tjpgd_srcs}"
|
|
||||||
INCLUDE_DIRS "include")
|
|
@@ -1,3 +0,0 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := include
|
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := src
|
|
@@ -1,88 +0,0 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
|
||||||
/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2019
|
|
||||||
/----------------------------------------------------------------------------*/
|
|
||||||
#ifndef DEF_TJPGDEC
|
|
||||||
#define DEF_TJPGDEC
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
/* System Configurations */
|
|
||||||
|
|
||||||
#define JD_SZBUF 512 /* Size of stream input buffer */
|
|
||||||
#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */
|
|
||||||
#define JD_USE_SCALE 1 /* Use descaling feature for output */
|
|
||||||
#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) /* Main development platform */
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef short int16_t;
|
|
||||||
typedef unsigned long uint32_t;
|
|
||||||
typedef long int32_t;
|
|
||||||
#else
|
|
||||||
#include "stdint.h"
|
|
||||||
#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 damaged data) */
|
|
||||||
JDR_FMT2, /* 7: Right format but not supported */
|
|
||||||
JDR_FMT3 /* 8: Not supported JPEG standard */
|
|
||||||
} JRESULT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Rectangular structure */
|
|
||||||
typedef struct {
|
|
||||||
uint16_t left, right, top, bottom;
|
|
||||||
} JRECT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Decompressor object structure */
|
|
||||||
typedef struct JDEC JDEC;
|
|
||||||
struct JDEC {
|
|
||||||
uint16_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 dmsk; /* Current bit in the current read byte */
|
|
||||||
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 */
|
|
||||||
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] */
|
|
||||||
void* workbuf; /* Working buffer for IDCT and RGB output */
|
|
||||||
uint8_t* mcubuf; /* Working buffer for the MCU */
|
|
||||||
void* pool; /* Pointer to available memory pool */
|
|
||||||
uint16_t sz_pool; /* Size of momory pool (bytes available) */
|
|
||||||
uint16_t (*infunc)(JDEC*, uint8_t*, uint16_t);/* Pointer to jpeg stream input function */
|
|
||||||
void* device; /* Pointer to I/O device identifiler for the session */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* TJpgDec API functions */
|
|
||||||
JRESULT jd_prepare (JDEC*, uint16_t(*)(JDEC*,uint8_t*,uint16_t), void*, uint16_t, void*);
|
|
||||||
JRESULT jd_decomp (JDEC*, uint16_t(*)(JDEC*,void*,JRECT*), uint8_t);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _TJPGDEC */
|
|
@@ -1,12 +1,8 @@
|
|||||||
set(srcs "pretty_effect.c"
|
set(srcs "pretty_effect.c"
|
||||||
"lcd_tjpgd_example_main.c"
|
"lcd_tjpgd_example_main.c"
|
||||||
|
"decode_image.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Only ESP32 has enough memory to do jpeg decoding
|
|
||||||
if(IDF_TARGET STREQUAL "esp32")
|
|
||||||
list(APPEND srcs "decode_image.c")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
EMBED_FILES image.jpg)
|
EMBED_FILES image.jpg)
|
||||||
|
@@ -18,7 +18,7 @@ format if you want to use a different image file.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "decode_image.h"
|
#include "decode_image.h"
|
||||||
#include "tjpgd.h"
|
#include "esp_rom_tjpgd.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ typedef struct {
|
|||||||
} JpegDev;
|
} JpegDev;
|
||||||
|
|
||||||
//Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure.
|
//Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure.
|
||||||
static uint16_t infunc(JDEC *decoder, uint8_t *buf, uint16_t len)
|
static uint32_t infunc(esp_rom_tjpgd_dec_t *decoder, uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
//Read bytes from input file
|
//Read bytes from input file
|
||||||
JpegDev *jd = (JpegDev *)decoder->device;
|
JpegDev *jd = (JpegDev *)decoder->device;
|
||||||
@@ -55,7 +55,7 @@ static uint16_t infunc(JDEC *decoder, uint8_t *buf, uint16_t len)
|
|||||||
|
|
||||||
//Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and
|
//Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and
|
||||||
//stores it in the outData array of the JpegDev structure.
|
//stores it in the outData array of the JpegDev structure.
|
||||||
static uint16_t outfunc(JDEC *decoder, void *bitmap, JRECT *rect)
|
static uint32_t outfunc(esp_rom_tjpgd_dec_t *decoder, void *bitmap, esp_rom_tjpgd_rect_t *rect)
|
||||||
{
|
{
|
||||||
JpegDev *jd = (JpegDev *)decoder->device;
|
JpegDev *jd = (JpegDev *)decoder->device;
|
||||||
uint8_t *in = (uint8_t *)bitmap;
|
uint8_t *in = (uint8_t *)bitmap;
|
||||||
@@ -83,7 +83,7 @@ esp_err_t decode_image(uint16_t ***pixels)
|
|||||||
{
|
{
|
||||||
char *work = NULL;
|
char *work = NULL;
|
||||||
int r;
|
int r;
|
||||||
JDEC decoder;
|
esp_rom_tjpgd_dec_t decoder;
|
||||||
JpegDev jd;
|
JpegDev jd;
|
||||||
*pixels = NULL;
|
*pixels = NULL;
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
@@ -120,13 +120,13 @@ esp_err_t decode_image(uint16_t ***pixels)
|
|||||||
jd.outH = IMAGE_H;
|
jd.outH = IMAGE_H;
|
||||||
|
|
||||||
//Prepare and decode the jpeg.
|
//Prepare and decode the jpeg.
|
||||||
r = jd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
|
r = esp_rom_tjpgd_prepare(&decoder, infunc, work, WORKSZ, (void *)&jd);
|
||||||
if (r != JDR_OK) {
|
if (r != JDR_OK) {
|
||||||
ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", r);
|
ESP_LOGE(TAG, "Image decoder: jd_prepare failed (%d)", r);
|
||||||
ret = ESP_ERR_NOT_SUPPORTED;
|
ret = ESP_ERR_NOT_SUPPORTED;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = jd_decomp(&decoder, outfunc, 0);
|
r = esp_rom_tjpgd_decomp(&decoder, outfunc, 0);
|
||||||
if (r != JDR_OK && r != JDR_FMT1) {
|
if (r != JDR_OK && r != JDR_FMT1) {
|
||||||
ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", r);
|
ESP_LOGE(TAG, "Image decoder: jd_decode failed (%d)", r);
|
||||||
ret = ESP_ERR_NOT_SUPPORTED;
|
ret = ESP_ERR_NOT_SUPPORTED;
|
||||||
|
@@ -12,8 +12,6 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "pretty_effect.h"
|
#include "pretty_effect.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
|
||||||
#include "decode_image.h"
|
#include "decode_image.h"
|
||||||
|
|
||||||
uint16_t **pixels;
|
uint16_t **pixels;
|
||||||
@@ -26,15 +24,6 @@ static inline uint16_t get_bgnd_pixel(int x, int y)
|
|||||||
y+=8;
|
y+=8;
|
||||||
return pixels[y][x];
|
return pixels[y][x];
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
//esp32s2/c3 doesn't have enough memory to hold the decoded image, calculate instead
|
|
||||||
//TODO: add support for esp32s3 (IDF-3615)
|
|
||||||
static inline uint16_t get_bgnd_pixel(int x, int y)
|
|
||||||
{
|
|
||||||
return ((x<<3)^(y<<3)^(x*y));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//This variable is used to detect the next frame.
|
//This variable is used to detect the next frame.
|
||||||
static int prev_frame=-1;
|
static int prev_frame=-1;
|
||||||
@@ -68,11 +57,5 @@ void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect)
|
|||||||
|
|
||||||
esp_err_t pretty_effect_init(void)
|
esp_err_t pretty_effect_init(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
|
||||||
return decode_image(&pixels);
|
return decode_image(&pixels);
|
||||||
#else
|
|
||||||
//esp32s2/c3 doesn't have enough memory to hold the decoded image, calculate instead
|
|
||||||
//TODO: add support for esp32s3 (IDF-3615)
|
|
||||||
return ESP_OK;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user