arch(img_decoder): replace read_liine_c with get_area_cb

also remove sjpeg support as get_area_cb can de quite same (some optimization is still needed to not decode the out of bounds chunks)
This commit is contained in:
Gabor Kiss-Vamosi
2023-09-18 21:19:00 +02:00
parent 6fdd585549
commit ca55b2ed8d
58 changed files with 1182 additions and 1448 deletions

View File

@@ -8,10 +8,14 @@ void lv_example_sjpg_1(void)
{ {
lv_obj_t * wp; lv_obj_t * wp;
LV_IMAGE_DECLARE(codeblocks)
wp = lv_image_create(lv_scr_act()); wp = lv_image_create(lv_scr_act());
/* Assuming a File system is attached to letter 'A' /* Assuming a File system is attached to letter 'A'
* E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */ * E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
lv_image_set_src(wp, "A:lvgl/examples/libs/sjpg/small_image.sjpg"); lv_image_set_src(wp, "A:codeblocks.jpg");
// lv_image_set_src(wp, &codeblocks);
lv_obj_center(wp);
} }
#endif #endif

2
lvgl.h
View File

@@ -95,7 +95,7 @@ extern "C" {
#include "src/libs/png/lv_png.h" #include "src/libs/png/lv_png.h"
#include "src/libs/gif/lv_gif.h" #include "src/libs/gif/lv_gif.h"
#include "src/libs/qrcode/lv_qrcode.h" #include "src/libs/qrcode/lv_qrcode.h"
#include "src/libs/sjpg/lv_sjpg.h" #include "src/libs/jpg/lv_jpg.h"
#include "src/libs/freetype/lv_freetype.h" #include "src/libs/freetype/lv_freetype.h"
#include "src/libs/rlottie/lv_rlottie.h" #include "src/libs/rlottie/lv_rlottie.h"
#include "src/libs/ffmpeg/lv_ffmpeg.h" #include "src/libs/ffmpeg/lv_ffmpeg.h"

View File

@@ -88,7 +88,6 @@ typedef lv_res_t (*lv_image_decoder_get_area_cb_t)(struct _lv_image_decoder_t *
*/ */
typedef void (*lv_image_decoder_close_f_t)(struct _lv_image_decoder_t * decoder, struct _lv_image_decoder_dsc_t * dsc); typedef void (*lv_image_decoder_close_f_t)(struct _lv_image_decoder_t * decoder, struct _lv_image_decoder_dsc_t * dsc);
typedef struct _lv_image_decoder_t { typedef struct _lv_image_decoder_t {
lv_image_decoder_info_f_t info_cb; lv_image_decoder_info_f_t info_cb;
lv_image_decoder_open_f_t open_cb; lv_image_decoder_open_f_t open_cb;
@@ -242,6 +241,9 @@ lv_res_t lv_image_decoder_built_in_info(lv_image_decoder_t * decoder, const void
lv_res_t lv_image_decoder_built_in_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_res_t lv_image_decoder_built_in_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
const lv_area_t * full_area, lv_area_t * decoded_area); const lv_area_t * full_area, lv_area_t * decoded_area);
lv_res_t lv_img_decoder_built_in_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
const lv_area_t * full_area, lv_area_t * decoded_area);
/** /**
* Open a built in image * Open a built in image
* @param decoder the decoder where this function belongs * @param decoder the decoder where this function belongs

View File

@@ -215,6 +215,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_sw_image(lv_draw_unit_t * draw_unit, const lv
lv_image_decoder_close(&decoder_dsc); lv_image_decoder_close(&decoder_dsc);
} }
static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * draw_area, static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * draw_area,
const lv_image_decoder_dsc_t * src, lv_draw_image_sup_t * sup, const lv_area_t * img_coords) const lv_image_decoder_dsc_t * src, lv_draw_image_sup_t * sup, const lv_area_t * img_coords)
{ {

290
src/libs/jpg/lv_jpg.c Normal file
View File

@@ -0,0 +1,290 @@
/**
* @file lv_sjpg.c
*
*/
/*----------------------------------------------------------------------------------------------------------------------------------
/ Added normal JPG support [7/10/2020]
/ ----------
/ SJPEG is a custom created modified JPEG file format for small embedded platforms.
/ It will contain multiple JPEG fragments all embedded into a single file with a custom header.
/ This makes JPEG decoding easier using any JPEG library. Overall file size will be almost
/ similar to the parent jpeg file. We can generate sjpeg from any jpeg using a python script
/ provided along with this project.
/ (by vinodstanur | 2020 )
/ SJPEG FILE STRUCTURE
/ --------------------------------------------------------------------------------------------------------------------------------
/ Bytes | Value |
/ --------------------------------------------------------------------------------------------------------------------------------
/
/ 0 - 7 | "_SJPG__" followed by '\0'
/
/ 8 - 13 | "V1.00" followed by '\0' [VERSION OF SJPG FILE for future compatibiliby]
/
/ 14 - 15 | X_RESOLUTION (width) [little endian]
/
/ 16 - 17 | Y_RESOLUTION (height) [little endian]
/
/ 18 - 19 | TOTAL_FRAMES inside sjpeg [little endian]
/
/ 20 - 21 | JPEG BLOCK WIDTH (16 normally) [little endian]
/
/ 22 - [(TOTAL_FRAMES*2 )] | SIZE OF EACH JPEG SPLIT FRAGMENTS (FRAME_INFO_ARRAY)
/
/ SJPEG data | Each JPEG frame can be extracted from SJPEG data by parsing the FRAME_INFO_ARRAY one time.
/
/----------------------------------------------------------------------------------------------------------------------------------
/ JPEG DECODER
/ ------------
/ We are using TJpgDec - Tiny JPEG Decompressor library from ELM-CHAN for decoding each split-jpeg fragments.
/ The tjpgd.c and tjpgd.h is not modified and those are used as it is. So if any update comes for the tiny-jpeg,
/ just replace those files with updated files.
/---------------------------------------------------------------------------------------------------------------------------------*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_SJPG
#include "tjpgd.h"
#include "lv_jpg.h"
#include "../../misc/lv_fs.h"
/*********************
* DEFINES
*********************/
#define TJPGD_WORKBUFF_SIZE 4096 //Recommended by TJPGD library
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header);
static lv_res_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static lv_res_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
const lv_area_t * full_area, lv_area_t * decoded_area);
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata);
static int is_jpg(const uint8_t * raw_data, size_t len);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_jpeg_init(void)
{
lv_image_decoder_t * dec = lv_image_decoder_create();
lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_get_area_cb(dec, decoder_get_area);
lv_image_decoder_set_close_cb(dec, decoder_close);
}
/**********************
* STATIC FUNCTIONS
**********************/
static lv_res_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header)
{
LV_UNUSED(decoder);
lv_image_src_t src_type = lv_image_src_get_type(src);
if(src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = src;
uint8_t * raw_data = (uint8_t *)img_dsc->data;
const uint32_t raw_sjpeg_data_size = img_dsc->data_size;
if(is_jpg(raw_data, raw_sjpeg_data_size) == true) {
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
header->w = img_dsc->header.w;
header->h = img_dsc->header.h;
header->stride = img_dsc->header.w * 3;
return LV_RES_OK;
}
}
else if(src_type == LV_IMAGE_SRC_FILE) {
const char * fn = src;
if((strcmp(lv_fs_get_ext(fn), "jpg") == 0) || (strcmp(lv_fs_get_ext(fn), "jpeg") == 0)) {
lv_fs_file_t f;
lv_fs_res_t res;
res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return LV_RES_INV;
uint8_t workb[TJPGD_WORKBUFF_SIZE];
JDEC jd;
JRESULT rc = jd_prepare(&jd, input_func, workb, TJPGD_WORKBUFF_SIZE, &f);
if(rc) {
LV_LOG_WARN("jd_prepare error: %d", rc);
lv_fs_close(&f);
return LV_RES_INV;
}
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
header->w = jd.width;
header->h = jd.height;
header->stride = jd.width * 3;
lv_fs_close(&f);
return LV_RES_OK;
}
}
return LV_RES_INV;
}
static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata)
{
lv_fs_file_t * f = jd->device;
if(!f) return 0;
if(buff) {
uint32_t rn = 0;
lv_fs_read(f, buff, (uint32_t)ndata, &rn);
return rn;
}
else {
uint32_t pos;
lv_fs_tell(f, &pos);
lv_fs_seek(f, (uint32_t)(ndata + pos), LV_FS_SEEK_SET);
return ndata;
}
return 0;
}
static lv_res_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
lv_fs_file_t * f = lv_malloc(sizeof(lv_fs_file_t));
if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = dsc->src;
if(is_jpg(img_dsc->data, img_dsc->data_size) == true) {
lv_fs_path_ex_t path;
lv_fs_make_path_from_buffer(&path, LV_FS_MEMFS_LETTER, img_dsc->data, img_dsc->data_size);
lv_fs_res_t res;
res = lv_fs_open(f, (const char *)&path, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
lv_free(f);
return LV_RES_INV;
}
}
}
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
const char * fn = dsc->src;
if((strcmp(lv_fs_get_ext(fn), "jpg") == 0) || (strcmp(lv_fs_get_ext(fn), "jpeg") == 0)) {
lv_fs_res_t res;
res = lv_fs_open(f, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
lv_free(f);
return LV_RES_INV;
}
}
}
uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE);
JDEC * jd = lv_malloc(sizeof(JDEC));
dsc->user_data = jd;
JRESULT rc = jd_prepare(jd, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, f);
if(rc) return rc;
dsc->header.always_zero = 0;
dsc->header.cf = LV_COLOR_FORMAT_RGB888;
dsc->header.w = jd->width;
dsc->header.h = jd->height;
dsc->header.stride = jd->width * 3;
if(rc != JDR_OK) {
lv_free(workb_temp);
lv_free(jd);
return LV_RES_INV;
}
return LV_RES_OK;
}
static lv_res_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
const lv_area_t * full_area, lv_area_t * decoded_area)
{
LV_UNUSED(decoder);
LV_UNUSED(full_area);
JDEC * jd = dsc->user_data;
uint32_t mx, my;
mx = jd->msx * 8;
my = jd->msy * 8; /* Size of the MCU (pixel) */
if(decoded_area->y1 == LV_COORD_MIN) {
decoded_area->y1 = 0;
decoded_area->y2 = 7;
decoded_area->x1 = 0 - mx;
decoded_area->x2 = 7 - mx;
jd->scale = 0;
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
dsc->img_data = jd->workbuf;
jd->rst = 0;
jd->rsc = 0;
dsc->header.stride = mx * 3;
}
decoded_area->x1 += mx;
decoded_area->x2 += mx;
if(decoded_area->x1 >= jd->width) {
decoded_area->x1 = 0;
decoded_area->x2 = 7;
decoded_area->y1 += my;
decoded_area->y2 += my;
}
JRESULT rc;
if (jd->nrst && jd->rst++ == jd->nrst) { /* Process restart interval if enabled */
rc = jd_restart(jd, jd->rsc++);
if (rc != JDR_OK) return rc;
jd->rst = 1;
}
rc = jd_mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */
if (rc != JDR_OK) return rc;
rc = jd_mcu_output(jd, NULL, decoded_area->x1, decoded_area->y1); /* Output the MCU (YCbCr to RGB, scaling and output) */
if (rc != JDR_OK) return rc;
return LV_RES_OK;
}
/**
* Free the allocated resources
* @param decoder pointer to the decoder where this function belongs
* @param dsc pointer to a descriptor which describes this decoding session
*/
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
JDEC * jd = dsc->user_data;
lv_fs_close(jd->device);
lv_free(jd->device);
lv_free(jd->pool_original);
lv_free(jd);
}
static int is_jpg(const uint8_t * raw_data, size_t len)
{
const uint8_t jpg_signature[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46};
if(len < sizeof(jpg_signature)) return false;
return memcmp(jpg_signature, raw_data, sizeof(jpg_signature)) == 0;
}
#endif /*LV_USE_SJPG*/

View File

@@ -28,7 +28,7 @@ extern "C" {
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
void lv_split_jpeg_init(void); void lv_jpeg_init(void);
/********************** /**********************
* MACROS * MACROS

View File

@@ -16,16 +16,16 @@
/ Oct 04, 2011 R0.01 First release. / Oct 04, 2011 R0.01 First release.
/ Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq. / Feb 19, 2012 R0.01a Fixed decompression fails when scan starts with an escape seq.
/ Sep 03, 2012 R0.01b Added JD_TBLCLIP option. / Sep 03, 2012 R0.01b Added JD_TBLCLIP option.
/ Mar 16, 2019 R0.01c Supported stdint.h. / Mar 16, 2019 R0.01c Supprted stdint.h.
/ Jul 01, 2020 R0.01d Fixed wrong integer type usage. / Jul 01, 2020 R0.01d Fixed wrong integer type usage.
/ May 08, 2021 R0.02 Supported grayscale image. Separated configuration options. / May 08, 2021 R0.02 Supprted grayscale image. Separated configuration options.
/ Jun 11, 2021 R0.02a Some performance improvement. / Jun 11, 2021 R0.02a Some performance improvement.
/ Jul 01, 2021 R0.03 Added JD_FASTDECODE option. / Jul 01, 2021 R0.03 Added JD_FASTDECODE option.
/ Some performance improvement. / Some performance improvement.
/----------------------------------------------------------------------------*/ /----------------------------------------------------------------------------*/
#include "tjpgd.h" #include "tjpgd.h"
#if LV_USE_SJPG
#if JD_FASTDECODE == 2 #if JD_FASTDECODE == 2
#define HUFF_BIT 10 /* Bit length to apply fast huffman decode */ #define HUFF_BIT 10 /* Bit length to apply fast huffman decode */
@@ -142,7 +142,7 @@ static void * alloc_pool( /* Pointer to allocated memory block (NULL:no memory a
if (jd->sz_pool >= ndata) { if (jd->sz_pool >= ndata) {
jd->sz_pool -= ndata; jd->sz_pool -= ndata;
rp = (char*)jd->pool; /* Get start of available memory pool */ rp = (char*)jd->pool; /* Get start of available memory pool */
jd->pool = (void *)(rp + ndata); /* Allocate required bytes */ jd->pool = (void*)(rp + ndata); /* Allocate requierd bytes */
} }
return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */
@@ -208,8 +208,7 @@ static JRESULT create_huffman_tbl( /* 0:OK, !0:Failed */
ndata -= 17; ndata -= 17;
d = *data++; /* Get table number and class */ d = *data++; /* Get table number and class */
if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */
cls = d >> 4; cls = d >> 4; num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */
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;
@@ -247,8 +246,7 @@ static JRESULT create_huffman_tbl( /* 0:OK, !0:Failed */
if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */ if (!tbl_ac) return JDR_MEM1; /* Err: not enough memory */
jd->hufflut_ac[num] = tbl_ac; jd->hufflut_ac[num] = tbl_ac;
memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */ memset(tbl_ac, 0xFF, HUFF_LEN * sizeof (uint16_t)); /* Default value (0xFFFF: may be long code) */
} } else {
else {
tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */ tbl_dc = alloc_pool(jd, HUFF_LEN * sizeof (uint8_t)); /* LUT for AC elements */
if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */ if (!tbl_dc) return JDR_MEM1; /* Err: not enough memory */
jd->hufflut_dc[num] = tbl_dc; jd->hufflut_dc[num] = tbl_dc;
@@ -260,8 +258,7 @@ static JRESULT create_huffman_tbl( /* 0:OK, !0:Failed */
if (cls) { if (cls) {
td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */ td = pd[i++] | ((b + 1) << 8); /* b15..b8: code length, b7..b0: zero run and data length */
for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ; for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_ac[ti++] = (uint16_t)td) ;
} } else {
else {
td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */ td = pd[i++] | ((b + 1) << 4); /* b7..b4: code length, b3..b0: data length */
for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ; for (span = 1 << (HUFF_BIT - 1 - b); span; span--, tbl_dc[ti++] = (uint8_t)td) ;
} }
@@ -300,16 +297,14 @@ static int huffext( /* >=0: decoded data, <0: error code */
bm = jd->dbit; /* Bit mask to extract */ bm = jd->dbit; /* Bit mask to extract */
d = 0; d = 0; bl = 16; /* Max code length */
bl = 16; /* Max code length */
do { do {
if (!bm) { /* Next byte? */ if (!bm) { /* Next byte? */
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 - (int)JDR_INP; /* Err: read error or wrong stream termination */ if (!dc) return 0 - (int)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 */
@@ -317,11 +312,9 @@ static int huffext( /* >=0: decoded data, <0: error code */
flg = 0; /* Exit flag sequence */ flg = 0; /* Exit flag sequence */
if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
*dp = 0xFF; /* The flag is a data 0xFF */ *dp = 0xFF; /* The flag is a data 0xFF */
} } else {
else {
if (*dp == 0xFF) { /* Is start of flag sequence? */ if (*dp == 0xFF) { /* Is start of flag sequence? */
flg = 1; flg = 1; continue; /* Enter flag sequence, get trailing byte */
continue; /* Enter flag sequence, get trailing byte */
} }
} }
bm = 0x80; /* Read from MSB */ bm = 0x80; /* Read from MSB */
@@ -332,9 +325,7 @@ static int huffext( /* >=0: decoded data, <0: error code */
for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */ for (nd = *hb++; nd; nd--) { /* Search the code word in this bit length */
if (d == *hc++) { /* Matched? */ if (d == *hc++) { /* Matched? */
jd->dbit = bm; jd->dbit = bm; jd->dctr = dc; jd->dptr = dp;
jd->dctr = dc;
jd->dptr = dp;
return *hd; /* Return the decoded data */ return *hd; /* Return the decoded data */
} }
hd++; hd++;
@@ -352,36 +343,31 @@ static int huffext( /* >=0: decoded data, <0: error code */
while (wbit < 16) { /* Prepare 16 bits into the working register */ while (wbit < 16) { /* Prepare 16 bits into the working register */
if (jd->marker) { if (jd->marker) {
d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */ d = 0xFF; /* Input stream has stalled for a marker. Generate stuff bits */
} } else {
else {
if (!dc) { /* Buffer empty, re-fill input buffer */ if (!dc) { /* Buffer empty, 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 - (int)JDR_INP; /* Err: read error or wrong stream termination */ if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
} }
d = *dp++; d = *dp++; dc--;
dc--;
if (flg) { /* In flag sequence? */ if (flg) { /* In flag sequence? */
flg = 0; /* Exit flag sequence */ flg = 0; /* Exit flag sequence */
if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */
d = 0xFF; d = 0xFF;
} } else {
else {
if (d == 0xFF) { /* Is start of flag sequence? */ if (d == 0xFF) { /* Is start of flag sequence? */
flg = 1; flg = 1; continue; /* Enter flag sequence, get trailing byte */
continue; /* Enter flag sequence, get trailing byte */
} }
} }
} }
w = w << 8 | d; /* Shift 8 bits in the working register */ w = w << 8 | d; /* Shift 8 bits in the working register */
wbit += 8; wbit += 8;
} }
jd->dctr = dc; jd->dctr = dc; jd->dptr = dp;
jd->dptr = dp;
jd->wreg = w; jd->wreg = w;
#if JD_FASTDECODE == 2 #if JD_FASTDECODE == 2
/* Table search for the short codes */ /* Table serch for the short codes */
d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */ d = (unsigned int)(w >> (wbit - HUFF_BIT)); /* Short code as table index */
if (cls) { /* AC element */ if (cls) { /* AC element */
d = jd->hufflut_ac[id][d]; /* Table decode */ d = jd->hufflut_ac[id][d]; /* Table decode */
@@ -389,8 +375,7 @@ static int huffext( /* >=0: decoded data, <0: error code */
jd->dbit = wbit - (d >> 8); /* Snip the code length */ jd->dbit = wbit - (d >> 8); /* Snip the code length */
return d & 0xFF; /* b7..0: zero run and following data bits */ return d & 0xFF; /* b7..0: zero run and following data bits */
} }
} } else { /* DC element */
else { /* DC element */
d = jd->hufflut_dc[id][d]; /* Table decode */ d = jd->hufflut_dc[id][d]; /* Table decode */
if (d != 0xFF) { /* It is done if hit in short code */ if (d != 0xFF) { /* It is done if hit in short code */
jd->dbit = wbit - (d >> 4); /* Snip the code length */ jd->dbit = wbit - (d >> 4); /* Snip the code length */
@@ -398,13 +383,13 @@ static int huffext( /* >=0: decoded data, <0: error code */
} }
} }
/* Incremental search for the codes longer than HUFF_BIT */ /* Incremental serch for the codes longer than HUFF_BIT */
hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */ hb = jd->huffbits[id][cls] + HUFF_BIT; /* Bit distribution table */
hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */ hc = jd->huffcode[id][cls] + jd->longofs[id][cls]; /* Code word table */
hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */ hd = jd->huffdata[id][cls] + jd->longofs[id][cls]; /* Data table */
bl = HUFF_BIT + 1; bl = HUFF_BIT + 1;
#else #else
/* Incremental search for all codes */ /* Incremental serch for all codes */
hb = jd->huffbits[id][cls]; /* Bit distribution table */ hb = jd->huffbits[id][cls]; /* Bit distribution table */
hc = jd->huffcode[id][cls]; /* Code word table */ hc = jd->huffcode[id][cls]; /* Code word table */
hd = jd->huffdata[id][cls]; /* Data table */ hd = jd->huffdata[id][cls]; /* Data table */
@@ -454,8 +439,7 @@ static int bitext( /* >=0: extracted data, <0: error code */
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 - (int)JDR_INP; /* Err: read error or wrong stream termination */ if (!dc) return 0 - (int)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 */
@@ -463,11 +447,9 @@ static int bitext( /* >=0: extracted data, <0: error code */
flg = 0; /* Exit flag sequence */ flg = 0; /* Exit flag sequence */
if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ if (*dp != 0) return 0 - (int)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */
*dp = 0xFF; /* The flag is a data 0xFF */ *dp = 0xFF; /* The flag is a data 0xFF */
} } else {
else {
if (*dp == 0xFF) { /* Is start of flag sequence? */ if (*dp == 0xFF) { /* Is start of flag sequence? */
flg = 1; flg = 1; continue; /* Enter flag sequence */
continue; /* Enter flag sequence */
} }
} }
mbit = 0x80; /* Read from MSB */ mbit = 0x80; /* Read from MSB */
@@ -478,9 +460,7 @@ static int bitext( /* >=0: extracted data, <0: error code */
nbit--; nbit--;
} while (nbit); } while (nbit);
jd->dbit = mbit; jd->dbit = mbit; jd->dctr = dc; jd->dptr = dp;
jd->dctr = dc;
jd->dptr = dp;
return (int)d; return (int)d;
#else #else
@@ -491,34 +471,28 @@ static int bitext( /* >=0: extracted data, <0: error code */
while (wbit < nbit) { /* Prepare nbit bits into the working register */ while (wbit < nbit) { /* Prepare nbit bits into the working register */
if (jd->marker) { if (jd->marker) {
d = 0xFF; /* Input stream stalled, generate stuff bits */ d = 0xFF; /* Input stream stalled, generate stuff bits */
} } else {
else {
if (!dc) { /* Buffer empty, re-fill input buffer */ if (!dc) { /* Buffer empty, 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 - (int)JDR_INP; /* Err: read error or wrong stream termination */ if (!dc) return 0 - (int)JDR_INP; /* Err: read error or wrong stream termination */
} }
d = *dp++; d = *dp++; dc--;
dc--;
if (flg) { /* In flag sequence? */ if (flg) { /* In flag sequence? */
flg = 0; /* Exit flag sequence */ flg = 0; /* Exit flag sequence */
if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */ if (d != 0) jd->marker = d; /* Not an escape of 0xFF but a marker */
d = 0xFF; d = 0xFF;
} } else {
else {
if (d == 0xFF) { /* Is start of flag sequence? */ if (d == 0xFF) { /* Is start of flag sequence? */
flg = 1; flg = 1; continue; /* Enter flag sequence, get trailing byte */
continue; /* Enter flag sequence, get trailing byte */
} }
} }
} }
w = w << 8 | d; /* Get 8 bits into the working register */ w = w << 8 | d; /* Get 8 bits into the working register */
wbit += 8; wbit += 8;
} }
jd->wreg = w; jd->wreg = w; jd->dbit = wbit - nbit;
jd->dbit = wbit - nbit; jd->dctr = dc; jd->dptr = dp;
jd->dctr = dc;
jd->dptr = dp;
return (int)(w >> ((wbit - nbit) % 32)); return (int)(w >> ((wbit - nbit) % 32));
#endif #endif
@@ -531,9 +505,9 @@ static int bitext( /* >=0: extracted data, <0: error code */
/* Process restart interval */ /* Process restart interval */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static JRESULT restart( JRESULT jd_restart (
JDEC* jd, /* Pointer to the decompressor object */ JDEC* jd, /* Pointer to the decompressor object */
uint16_t rstn /* Expected restert sequence number */ uint16_t rstn /* Expected restert sequense number */
) )
{ {
unsigned int i; unsigned int i;
@@ -549,16 +523,13 @@ static JRESULT restart(
dp = jd->inbuf; dp = jd->inbuf;
dc = jd->infunc(jd, dp, JD_SZBUF); dc = jd->infunc(jd, dp, JD_SZBUF);
if (!dc) return JDR_INP; if (!dc) return JDR_INP;
} } else {
else {
dp++; dp++;
} }
dc--; dc--;
d = d << 8 | *dp; /* Get a byte */ d = d << 8 | *dp; /* Get a byte */
} }
jd->dptr = dp; jd->dptr = dp; jd->dctr = dc; jd->dbit = 0;
jd->dctr = dc;
jd->dbit = 0;
/* Check the marker */ /* Check the marker */
if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) { if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) {
@@ -572,8 +543,7 @@ static JRESULT restart(
if (jd->marker) { /* Generate a maker if it has been detected */ if (jd->marker) { /* Generate a maker if it has been detected */
marker = 0xFF00 | jd->marker; marker = 0xFF00 | jd->marker;
jd->marker = 0; jd->marker = 0;
} } else {
else {
marker = 0; marker = 0;
for (i = 0; i < 2; i++) { /* Get a restart marker */ for (i = 0; i < 2; i++) { /* Get a restart marker */
if (!dc) { /* No input data is available, re-fill input buffer */ if (!dc) { /* No input data is available, re-fill input buffer */
@@ -584,8 +554,7 @@ static JRESULT restart(
marker = (marker << 8) | *dp++; /* Get a byte */ marker = (marker << 8) | *dp++; /* Get a byte */
dc--; dc--;
} }
jd->dptr = dp; jd->dptr = dp; jd->dctr = dc;
jd->dctr = dc;
} }
/* Check the marker */ /* Check the marker */
@@ -612,8 +581,7 @@ static void block_idct(
jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */ jd_yuv_t* dst /* Pointer to the destination to store the block as byte array */
) )
{ {
const int32_t M13 = (int32_t)(1.41421 * 4096), M2 = (int32_t)(1.08239 * 4096), M4 = (int32_t)(2.61313 * 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);
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;
int i; int i;
@@ -720,8 +688,7 @@ static void block_idct(
dst[4] = BYTECLIP((v3 - v4) >> 8); dst[4] = BYTECLIP((v3 - v4) >> 8);
#endif #endif
dst += 8; dst += 8; src += 8; /* Next row */
src += 8; /* Next row */
} }
} }
@@ -732,7 +699,7 @@ static void block_idct(
/* Load all blocks in an MCU into working buffer */ /* Load all blocks in an MCU into working buffer */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
static JRESULT mcu_load( JRESULT jd_mcu_load (
JDEC* jd /* Pointer to the decompressor object */ JDEC* jd /* Pointer to the decompressor object */
) )
{ {
@@ -752,8 +719,7 @@ static JRESULT mcu_load(
if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */ if (cmp && jd->ncomp != 3) { /* Clear C blocks if not exist (monochrome image) */
for (i = 0; i < 64; bp[i++] = 128) ; for (i = 0; i < 64; bp[i++] = 128) ;
} } else { /* Load Y/C blocks from input stream */
else { /* Load Y/C blocks from input stream */
id = cmp ? 1 : 0; /* Huffman table ID of this component */ id = cmp ? 1 : 0; /* Huffman table ID of this component */
/* Extract a DC element from input stream */ /* Extract a DC element from input stream */
@@ -793,18 +759,14 @@ static JRESULT mcu_load(
} while (++z < 64); /* Next AC element */ } while (++z < 64); /* Next AC element */
if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */ if (JD_FORMAT != 2 || !cmp) { /* C components may not be processed if in grayscale output */
if(z == 1 || (JD_USE_SCALE && if (z == 1 || (JD_USE_SCALE && jd->scale == 3)) { /* If no AC element or scale ratio is 1/8, IDCT can be ommited and the block is filled with DC value */
jd->scale ==
3)) { /* If no AC element or scale ratio is 1/8, IDCT can be omitted and the block is filled with DC value */
d = (jd_yuv_t)((*tmp / 256) + 128); d = (jd_yuv_t)((*tmp / 256) + 128);
if (JD_FASTDECODE >= 1) { if (JD_FASTDECODE >= 1) {
for (i = 0; i < 64; bp[i++] = d) ; for (i = 0; i < 64; bp[i++] = d) ;
} } else {
else {
memset(bp, d, 64); memset(bp, d, 64);
} }
} } 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 */
} }
} }
@@ -823,11 +785,11 @@ 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( JRESULT jd_mcu_output (
JDEC* jd, /* Pointer to the decompressor object */ JDEC* jd, /* Pointer to the decompressor object */
int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ int (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */
unsigned int img_x, /* MCU location in the image */ unsigned int x, /* MCU location in the image */
unsigned int img_y /* MCU location in the image */ unsigned int y /* MCU location in the image */
) )
{ {
const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */ const int CVACC = (sizeof (int) > 2) ? 1024 : 128; /* Adaptive accuracy for both 16-/32-bit systems */
@@ -838,22 +800,16 @@ static JRESULT mcu_output(
JRECT rect; JRECT rect;
mx = jd->msx * 8; mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */
my = jd->msy * 8; /* MCU size (pixel) */ rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end of image) */
rx = (img_x + mx <= jd->width) ? mx : jd->width - ry = (y + my <= jd->height) ? my : jd->height - y;
img_x; /* Output rectangular size (it may be clipped at right/bottom end of image) */
ry = (img_y + my <= jd->height) ? my : jd->height - img_y;
if (JD_USE_SCALE) { if (JD_USE_SCALE) {
rx >>= jd->scale; rx >>= jd->scale; ry >>= jd->scale;
ry >>= jd->scale;
if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */
img_x >>= jd->scale; x >>= jd->scale; y >>= jd->scale;
img_y >>= jd->scale;
} }
rect.left = img_x; rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */
rect.right = img_x + rx - 1; /* Rectangular area in the frame buffer */ rect.top = y; rect.bottom = y + ry - 1;
rect.top = img_y;
rect.bottom = img_y + ry - 1;
if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */
@@ -865,8 +821,7 @@ static JRESULT mcu_output(
if (my == 16) { /* Double block height? */ if (my == 16) { /* Double block height? */
pc += 64 * 4 + (iy >> 1) * 8; pc += 64 * 4 + (iy >> 1) * 8;
if (iy >= 8) py += 64; if (iy >= 8) py += 64;
} } else { /* Single block height */
else { /* Single block height */
pc += mx * 8 + iy * 8; pc += mx * 8 + iy * 8;
} }
py += iy * 8; py += iy * 8;
@@ -874,88 +829,15 @@ static JRESULT mcu_output(
cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */ cb = pc[0] - 128; /* Get Cb/Cr component and remove offset */
cr = pc[64] - 128; cr = pc[64] - 128;
if (mx == 16) { /* Double block width? */ if (mx == 16) { /* Double block width? */
if(ix == 8) py += 64 - 8; /* Jump to next block if double block height */ if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */
pc += ix & 1; /* Step forward chroma pointer every two pixels */ pc += ix & 1; /* Step forward chroma pointer every two pixels */
} } else { /* Single block width */
else { /* Single block width */
pc++; /* Step forward chroma pointer every pixel */ pc++; /* Step forward chroma pointer every pixel */
} }
yy = *py++; /* Get Y component */ yy = *py++; /* Get Y component */
*pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC);
*pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC);
*pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC); *pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb) / CVACC);
}
}
}
else { /* Monochrome output (build a grayscale MCU from Y comopnent) */
for(iy = 0; iy < my; iy++) {
py = jd->mcubuf + iy * 8;
if(my == 16) { /* Double block height? */
if(iy >= 8) py += 64;
}
for(ix = 0; ix < mx; ix++) {
if(mx == 16) { /* Double block width? */
if(ix == 8) py += 64 - 8; /* Jump to next block if double block height */
}
*pix++ = (uint8_t) * py++; /* Get and store a Y value as grayscale */
}
}
}
/* Descale the MCU rectangular if needed */
if(JD_USE_SCALE && jd->scale) {
unsigned int x, y, r, g, b, s, w, a;
uint8_t * op;
/* Get averaged RGB value of each square corresponds to a pixel */
s = jd->scale * 2; /* Number of shifts for averaging */
w = 1 << jd->scale; /* Width of square */
a = (mx - w) * (JD_FORMAT != 2 ? 3 : 1); /* Bytes to skip for next line in the square */
op = (uint8_t *)jd->workbuf;
for(iy = 0; iy < my; iy += w) {
for(ix = 0; ix < mx; ix += w) {
pix = (uint8_t *)jd->workbuf + (iy * mx + ix) * (JD_FORMAT != 2 ? 3 : 1);
r = g = b = 0;
for(y = 0; y < w; y++) { /* Accumulate RGB value in the square */
for(x = 0; x < w; x++) {
r += *pix++; /* Accumulate R or Y (monochrome output) */
if(JD_FORMAT != 2) { /* RGB output? */
g += *pix++; /* Accumulate G */
b += *pix++; /* Accumulate B */
}
}
pix += a;
} /* Put the averaged pixel value */
*op++ = (uint8_t)(r >> s); /* Put R or Y (monochrome output) */
if(JD_FORMAT != 2) { /* RGB output? */
*op++ = (uint8_t)(g >> s); /* Put G */
*op++ = (uint8_t)(b >> s); /* Put B */
}
}
}
}
}
else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */
/* Build a 1/8 descaled RGB MCU from discrete comopnents */
pix = (uint8_t *)jd->workbuf;
pc = jd->mcubuf + mx * my;
cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */
cr = pc[64] - 128;
for(iy = 0; iy < my; iy += 8) {
py = jd->mcubuf;
if(iy == 8) py += 64 * 2;
for(ix = 0; ix < mx; ix += 8) {
yy = *py; /* Get Y component */
py += 64;
if(JD_FORMAT != 2) {
*pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr / CVACC));
*pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC); *pix++ = /*G*/ BYTECLIP(yy - ((int)(0.344 * CVACC) * cb + (int)(0.714 * CVACC) * cr) / CVACC);
*pix++ = /*B*/ BYTECLIP(yy + ((int)(1.772 * CVACC) * cb / CVACC)); *pix++ = /*R*/ BYTECLIP(yy + ((int)(1.402 * CVACC) * cr) / CVACC);
}
else {
*pix++ = yy;
} }
} }
} }
@@ -965,11 +847,11 @@ static JRESULT mcu_output(
mx >>= jd->scale; mx >>= jd->scale;
if (rx < mx) { /* Is the MCU spans rigit edge? */ if (rx < mx) { /* Is the MCU spans rigit edge? */
uint8_t *s, *d; uint8_t *s, *d;
unsigned int x, y; unsigned int xi, yi;
s = d = (uint8_t*)jd->workbuf; s = d = (uint8_t*)jd->workbuf;
for(y = 0; y < ry; y++) { for (yi = 0; yi < ry; yi++) {
for(x = 0; x < rx; x++) { /* Copy effective pixels */ for (xi = 0; xi < rx; xi++) { /* Copy effective pixels */
*d++ = *s++; *d++ = *s++;
if (JD_FORMAT != 2) { if (JD_FORMAT != 2) {
*d++ = *s++; *d++ = *s++;
@@ -995,7 +877,8 @@ static JRESULT mcu_output(
} }
/* Output the rectangular */ /* Output the rectangular */
return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; if(outfunc) return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR;
return 0;
} }
@@ -1010,7 +893,7 @@ static JRESULT mcu_output(
JRESULT jd_prepare ( JRESULT jd_prepare (
JDEC* jd, /* Blank decompressor object */ JDEC* jd, /* Blank decompressor object */
size_t (*infunc)(JDEC *, uint8_t *, size_t), /* JPEG stream input function */ size_t (*infunc)(JDEC*, uint8_t*, size_t), /* JPEG strem input function */
void* pool, /* Working buffer for the decompression session */ void* pool, /* Working buffer for the decompression session */
size_t sz_pool, /* Size of working buffer */ size_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 */
@@ -1023,9 +906,9 @@ JRESULT jd_prepare(
JRESULT rc; JRESULT rc;
memset(jd, 0, sizeof( memset(jd, 0, sizeof (JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */
JDEC)); /* Clear decompression object (this might be a problem if machine's null pointer is not all bits zero) */ jd->pool = pool; /* Work memroy */
jd->pool = pool; /* Work memory */ jd->pool_original = pool;
jd->sz_pool = sz_pool; /* Size of given work memory */ jd->sz_pool = sz_pool; /* Size of given work memory */
jd->infunc = infunc; /* Stream input function */ jd->infunc = infunc; /* Stream input function */
jd->device = dev; /* I/O device identifier */ jd->device = dev; /* I/O device identifier */
@@ -1066,10 +949,8 @@ JRESULT jd_prepare(
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->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */
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 Cb/Cr must be 1 */ if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cb/Cr must be 1 */
} }
jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ jd->qtid[i] = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */
@@ -1125,8 +1006,7 @@ JRESULT jd_prepare(
if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */
len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */
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, jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */
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 = alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t)); /* Allocate MCU working buffer */ jd->mcubuf = alloc_pool(jd, (n + 2) * 64 * sizeof (jd_yuv_t)); /* Allocate MCU working buffer */
if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */
@@ -1182,8 +1062,7 @@ JRESULT jd_decomp(
if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR;
jd->scale = scale; jd->scale = scale;
mx = jd->msx * 8; mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */
my = jd->msy * 8; /* Size of the MCU (pixel) */
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
rst = rsc = 0; rst = rsc = 0;
@@ -1192,18 +1071,16 @@ JRESULT jd_decomp(
for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */
for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */
if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */
rc = restart(jd, rsc++); rc = jd_restart(jd, rsc++);
if (rc != JDR_OK) return rc; if (rc != JDR_OK) return rc;
rst = 1; rst = 1;
} }
rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */ rc = jd_mcu_load(jd); /* Load an MCU (decompress huffman coded stream, dequantize and apply IDCT) */
if (rc != JDR_OK) return rc; if (rc != JDR_OK) return rc;
rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */ rc = jd_mcu_output(jd, outfunc, x, y); /* Output the MCU (YCbCr to RGB, scaling and output) */
if (rc != JDR_OK) return rc; if (rc != JDR_OK) return rc;
} }
} }
return rc; return rc;
} }
#endif /*LV_USE_SJPG*/

View File

@@ -8,12 +8,18 @@
extern "C" { extern "C" {
#endif #endif
#include "../../lv_conf_internal.h"
#if LV_USE_SJPG
#include "tjpgdcnf.h" #include "tjpgdcnf.h"
#include <string.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> #include <stdint.h>
#endif
#if JD_FASTDECODE >= 1 #if JD_FASTDECODE >= 1
typedef int16_t jd_yuv_t; typedef int16_t jd_yuv_t;
@@ -35,6 +41,8 @@ typedef enum {
JDR_FMT3 /* 8: Not supported JPEG standard */ JDR_FMT3 /* 8: Not supported JPEG standard */
} JRESULT; } JRESULT;
/* Rectangular region in the output image */ /* Rectangular region in the output image */
typedef struct { typedef struct {
uint16_t left; /* Left end */ uint16_t left; /* Left end */
@@ -43,19 +51,23 @@ typedef struct {
uint16_t bottom; /* Bottom end */ uint16_t bottom; /* Bottom end */
} JRECT; } JRECT;
/* Decompressor object structure */ /* Decompressor object structure */
typedef struct _JDEC JDEC; typedef struct JDEC JDEC;
struct _JDEC { struct JDEC {
size_t dctr; /* Number of bytes available in the input buffer */ size_t dctr; /* Number of bytes available in the input buffer */
uint8_t* dptr; /* Current data read ptr */ uint8_t* dptr; /* Current data read ptr */
uint8_t* inbuf; /* Bit stream input buffer */ uint8_t* inbuf; /* Bit stream input buffer */
uint8_t dbit; /* Number of bits available in wreg or reading bit mask */ uint8_t dbit; /* Number of bits availavble in wreg or reading bit mask */
uint8_t scale; /* Output scaling ratio */ uint8_t scale; /* Output scaling ratio */
uint8_t msx, msy; /* MCU size in unit of block (width, height) */ 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 qtid[3]; /* Quantization table ID of each component, Y, Cb, Cr */
uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */ uint8_t ncomp; /* Number of color components 1:grayscale, 3:color */
int16_t dcv[3]; /* Previous DC element of each component */ int16_t dcv[3]; /* Previous DC element of each component */
uint16_t nrst; /* Restart interval */ uint16_t nrst; /* Restart inverval */
uint16_t rst; /* Restart count*/
uint16_t rsc; /* Expected restart sequence ID*/
uint16_t width, height; /* Size of the input image (pixel) */ uint16_t width, height; /* Size of the input image (pixel) */
uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */
uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */
@@ -73,18 +85,25 @@ struct _JDEC {
void* workbuf; /* Working buffer for IDCT and RGB output */ void* workbuf; /* Working buffer for IDCT and RGB output */
jd_yuv_t* mcubuf; /* Working buffer for the MCU */ jd_yuv_t* mcubuf; /* Working buffer for the MCU */
void* pool; /* Pointer to available memory pool */ void* pool; /* Pointer to available memory pool */
size_t sz_pool; /* Size of memory pool (bytes available) */ void* pool_original; /* Pointer to original 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 */ size_t (*infunc)(JDEC*, uint8_t*, size_t); /* Pointer to jpeg stream input function */
void * device; /* Pointer to I/O device identifier for the session */ void* device; /* Pointer to I/O device identifiler for the session */
}; };
/* TJpgDec API functions */ /* 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_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); JRESULT jd_decomp (JDEC* jd, int (*outfunc)(JDEC*,void*,JRECT*), uint8_t scale);
#endif /*LV_USE_SJPG*/ JRESULT jd_mcu_load (JDEC* jd);
JRESULT jd_mcu_output(JDEC* jd, int (*outfunc)(JDEC*, void*, JRECT*), unsigned int x, unsigned int y);
JRESULT jd_restart(JDEC* jd, uint16_t rstn);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -12,7 +12,7 @@
/ 2: Grayscale (8-bit/pix) / 2: Grayscale (8-bit/pix)
*/ */
#define JD_USE_SCALE 1 #define JD_USE_SCALE 0
/* Switches output descaling feature. /* Switches output descaling feature.
/ 0: Disable / 0: Disable
/ 1: Enable / 1: Enable
@@ -24,7 +24,7 @@
/ 1: Enable / 1: Enable
*/ */
#define JD_FASTDECODE 0 #define JD_FASTDECODE 1
/* Optimization level /* Optimization level
/ 0: Basic optimization. Suitable for 8/16-bit MCUs. / 0: Basic optimization. Suitable for 8/16-bit MCUs.
/ 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs. / 1: + 32-bit barrel shifter. Suitable for 32-bit MCUs.

View File

@@ -1,931 +0,0 @@
/**
* @file lv_sjpg.c
*
*/
/*----------------------------------------------------------------------------------------------------------------------------------
/ Added normal JPG support [7/10/2020]
/ ----------
/ SJPEG is a custom created modified JPEG file format for small embedded platforms.
/ It will contain multiple JPEG fragments all embedded into a single file with a custom header.
/ This makes JPEG decoding easier using any JPEG library. Overall file size will be almost
/ similar to the parent jpeg file. We can generate sjpeg from any jpeg using a python script
/ provided along with this project.
/ (by vinodstanur | 2020 )
/ SJPEG FILE STRUCTURE
/ --------------------------------------------------------------------------------------------------------------------------------
/ Bytes | Value |
/ --------------------------------------------------------------------------------------------------------------------------------
/
/ 0 - 7 | "_SJPG__" followed by '\0'
/
/ 8 - 13 | "V1.00" followed by '\0' [VERSION OF SJPG FILE for future compatibiliby]
/
/ 14 - 15 | X_RESOLUTION (width) [little endian]
/
/ 16 - 17 | Y_RESOLUTION (height) [little endian]
/
/ 18 - 19 | TOTAL_FRAMES inside sjpeg [little endian]
/
/ 20 - 21 | JPEG BLOCK WIDTH (16 normally) [little endian]
/
/ 22 - [(TOTAL_FRAMES*2 )] | SIZE OF EACH JPEG SPLIT FRAGMENTS (FRAME_INFO_ARRAY)
/
/ SJPEG data | Each JPEG frame can be extracted from SJPEG data by parsing the FRAME_INFO_ARRAY one time.
/
/----------------------------------------------------------------------------------------------------------------------------------
/ JPEG DECODER
/ ------------
/ We are using TJpgDec - Tiny JPEG Decompressor library from ELM-CHAN for decoding each split-jpeg fragments.
/ The tjpgd.c and tjpgd.h is not modified and those are used as it is. So if any update comes for the tiny-jpeg,
/ just replace those files with updated files.
/---------------------------------------------------------------------------------------------------------------------------------*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_SJPG
#include "tjpgd.h"
#include "lv_sjpg.h"
#include "../../misc/lv_fs.h"
/*********************
* DEFINES
*********************/
#define TJPGD_WORKBUFF_SIZE 4096 //Recommended by TJPGD library
//NEVER EDIT THESE OFFSET VALUES
#define SJPEG_VERSION_OFFSET 8
#define SJPEG_X_RES_OFFSET 14
#define SJPEG_y_RES_OFFSET 16
#define SJPEG_TOTAL_FRAMES_OFFSET 18
#define SJPEG_BLOCK_WIDTH_OFFSET 20
#define SJPEG_FRAME_INFO_ARRAY_OFFSET 22
/**********************
* TYPEDEFS
**********************/
enum io_source_type {
SJPEG_IO_SOURCE_C_ARRAY,
SJPEG_IO_SOURCE_DISK,
};
typedef struct {
enum io_source_type type;
lv_fs_file_t lv_file;
uint8_t * img_cache_buff;
int img_cache_x_res;
int img_cache_y_res;
uint8_t * raw_sjpg_data; //Used when type==SJPEG_IO_SOURCE_C_ARRAY.
uint32_t raw_sjpg_data_size; //Num bytes pointed to by raw_sjpg_data.
uint32_t raw_sjpg_data_next_read_pos; //Used for all types.
} io_source_t;
typedef struct {
uint8_t * sjpeg_data;
uint32_t sjpeg_data_size;
int sjpeg_x_res;
int sjpeg_y_res;
int sjpeg_total_frames;
int sjpeg_single_frame_height;
int sjpeg_cache_frame_index;
uint8_t ** frame_base_array; //to save base address of each split frames upto sjpeg_total_frames.
int * frame_base_offset; //to save base offset for fseek
uint8_t * frame_cache;
uint8_t * workb; //JPG work buffer for jpeg library
JDEC * tjpeg_jd;
io_source_t io;
} SJPEG;
/**********************
* STATIC PROTOTYPES
**********************/
static lv_res_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header);
static lv_res_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static lv_res_t decoder_read_line(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_coord_t x,
lv_coord_t y,
lv_coord_t len, uint8_t * buf);
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata);
static int is_jpg(const uint8_t * raw_data, size_t len);
static void lv_sjpg_cleanup(SJPEG * sjpeg);
static void lv_sjpg_free(SJPEG * sjpeg);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_split_jpeg_init(void)
{
lv_image_decoder_t * dec = lv_image_decoder_create();
lv_image_decoder_set_info_cb(dec, decoder_info);
lv_image_decoder_set_open_cb(dec, decoder_open);
lv_image_decoder_set_close_cb(dec, decoder_close);
/*
Disabled for now
lv_image_decoder_set_read_line_cb(dec, decoder_read_line);
*/
LV_UNUSED(decoder_read_line);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* Get info about an SJPG / JPG image
* @param decoder pointer to the decoder where this function belongs
* @param src can be file name or pointer to a C array
* @param header store the info here
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header)
{
LV_UNUSED(decoder);
/*Check whether the type `src` is known by the decoder*/
/* Read the SJPG/JPG header and find `width` and `height` */
lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/
lv_res_t ret = LV_RES_OK;
if(src_type == LV_IMAGE_SRC_VARIABLE) {
const lv_image_dsc_t * img_dsc = src;
uint8_t * raw_sjpeg_data = (uint8_t *)img_dsc->data;
const uint32_t raw_sjpeg_data_size = img_dsc->data_size;
if(!strncmp((char *)raw_sjpeg_data, "_SJPG__", strlen("_SJPG__"))) {
raw_sjpeg_data += 14; //seek to res info ... refer sjpeg format
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
header->w = *raw_sjpeg_data++;
header->w |= *raw_sjpeg_data++ << 8;
header->h = *raw_sjpeg_data++;
header->h |= *raw_sjpeg_data++ << 8;
return ret;
}
else if(is_jpg(raw_sjpeg_data, raw_sjpeg_data_size) == true) {
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(!workb_temp) return LV_RES_INV;
io_source_t io_source_temp;
io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY;
io_source_temp.raw_sjpg_data = raw_sjpeg_data;
io_source_temp.raw_sjpg_data_size = raw_sjpeg_data_size;
io_source_temp.raw_sjpg_data_next_read_pos = 0;
JDEC jd_tmp;
JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp);
if(rc == JDR_OK) {
header->w = jd_tmp.width;
header->h = jd_tmp.height;
}
else {
ret = LV_RES_INV;
goto end;
}
end:
lv_free(workb_temp);
return ret;
}
}
else if(src_type == LV_IMAGE_SRC_FILE) {
const char * fn = src;
if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) {
uint8_t buff[22];
memset(buff, 0, sizeof(buff));
lv_fs_file_t file;
lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return 78;
uint32_t rn;
res = lv_fs_read(&file, buff, 8, &rn);
if(res != LV_FS_RES_OK || rn != 8) {
lv_fs_close(&file);
return LV_RES_INV;
}
if(strcmp((char *)buff, "_SJPG__") == 0) {
lv_fs_seek(&file, 14, LV_FS_SEEK_SET);
res = lv_fs_read(&file, buff, 4, &rn);
if(res != LV_FS_RES_OK || rn != 4) {
lv_fs_close(&file);
return LV_RES_INV;
}
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
uint8_t * raw_sjpeg_data = buff;
header->w = *raw_sjpeg_data++;
header->w |= *raw_sjpeg_data++ << 8;
header->h = *raw_sjpeg_data++;
header->h |= *raw_sjpeg_data++ << 8;
lv_fs_close(&file);
return LV_RES_OK;
}
}
else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) {
lv_fs_file_t file;
lv_fs_res_t res = lv_fs_open(&file, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return 78;
uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(!workb_temp) {
lv_fs_close(&file);
return LV_RES_INV;
}
io_source_t io_source_temp;
io_source_temp.type = SJPEG_IO_SOURCE_DISK;
io_source_temp.raw_sjpg_data_next_read_pos = 0;
io_source_temp.img_cache_buff = NULL;
io_source_temp.lv_file = file;
JDEC jd_tmp;
JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp);
lv_free(workb_temp);
lv_fs_close(&file);
if(rc == JDR_OK) {
header->always_zero = 0;
header->cf = LV_COLOR_FORMAT_RAW;
header->w = jd_tmp.width;
header->h = jd_tmp.height;
return LV_RES_OK;
}
}
}
return LV_RES_INV;
}
static int img_data_cb(JDEC * jd, void * data, JRECT * rect)
{
io_source_t * io = jd->device;
uint8_t * cache = io->img_cache_buff;
const int xres = io->img_cache_x_res;
uint8_t * buf = data;
const int INPUT_PIXEL_SIZE = 3;
const int row_width = rect->right - rect->left + 1; // Row width in pixels.
const int row_size = row_width * INPUT_PIXEL_SIZE; // Row size (bytes).
for(int y = rect->top; y <= rect->bottom; y++) {
int row_offset = y * xres * INPUT_PIXEL_SIZE + rect->left * INPUT_PIXEL_SIZE;
memcpy(cache + row_offset, buf, row_size);
buf += row_size;
}
return 1;
}
static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata)
{
io_source_t * io = jd->device;
if(!io) return 0;
if(io->type == SJPEG_IO_SOURCE_C_ARRAY) {
const uint32_t bytes_left = io->raw_sjpg_data_size - io->raw_sjpg_data_next_read_pos;
const uint32_t to_read = ndata <= bytes_left ? (uint32_t)ndata : bytes_left;
if(to_read == 0)
return 0;
if(buff) {
memcpy(buff, io->raw_sjpg_data + io->raw_sjpg_data_next_read_pos, to_read);
}
io->raw_sjpg_data_next_read_pos += to_read;
return to_read;
}
else if(io->type == SJPEG_IO_SOURCE_DISK) {
lv_fs_file_t * lv_file_p = &(io->lv_file);
if(buff) {
uint32_t rn = 0;
lv_fs_read(lv_file_p, buff, (uint32_t)ndata, &rn);
return rn;
}
else {
uint32_t pos;
lv_fs_tell(lv_file_p, &pos);
lv_fs_seek(lv_file_p, (uint32_t)(ndata + pos), LV_FS_SEEK_SET);
return ndata;
}
}
return 0;
}
/**
* Open SJPG image and return the decided image
* @param decoder pointer to the decoder where this function belongs
* @param dsc pointer to a descriptor which describes this decoding session
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info
*/
static lv_res_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
lv_res_t lv_ret = LV_RES_OK;
if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
uint8_t * data;
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
const uint32_t raw_sjpeg_data_size = ((lv_image_dsc_t *)dsc->src)->data_size;
if(sjpeg == NULL) {
sjpeg = lv_malloc(sizeof(SJPEG));
if(!sjpeg) return LV_RES_INV;
memset(sjpeg, 0, sizeof(SJPEG));
dsc->user_data = sjpeg;
sjpeg->sjpeg_data = (uint8_t *)((lv_image_dsc_t *)(dsc->src))->data;
sjpeg->sjpeg_data_size = ((lv_image_dsc_t *)(dsc->src))->data_size;
}
if(!strncmp((char *) sjpeg->sjpeg_data, "_SJPG__", strlen("_SJPG__"))) {
data = sjpeg->sjpeg_data;
data += 14;
sjpeg->sjpeg_x_res = *data++;
sjpeg->sjpeg_x_res |= *data++ << 8;
sjpeg->sjpeg_y_res = *data++;
sjpeg->sjpeg_y_res |= *data++ << 8;
sjpeg->sjpeg_total_frames = *data++;
sjpeg->sjpeg_total_frames |= *data++ << 8;
sjpeg->sjpeg_single_frame_height = *data++;
sjpeg->sjpeg_single_frame_height |= *data++ << 8;
sjpeg->frame_base_array = lv_malloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames);
if(! sjpeg->frame_base_array) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->frame_base_offset = NULL;
uint8_t * img_frame_base = data + sjpeg->sjpeg_total_frames * 2;
sjpeg->frame_base_array[0] = img_frame_base;
for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) {
int offset = *data++;
offset |= *data++ << 8;
sjpeg->frame_base_array[i] = sjpeg->frame_base_array[i - 1] + offset;
}
sjpeg->sjpeg_cache_frame_index = -1;
sjpeg->frame_cache = (void *)lv_malloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3/*2*/);
if(! sjpeg->frame_cache) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->io.img_cache_buff = sjpeg->frame_cache;
sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res;
sjpeg->workb = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! sjpeg->workb) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->tjpeg_jd = lv_malloc(sizeof(JDEC));
if(! sjpeg->tjpeg_jd) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY;
sjpeg->io.lv_file.file_d = NULL;
dsc->img_data = NULL;
return lv_ret;
}
else if(is_jpg(sjpeg->sjpeg_data, raw_sjpeg_data_size) == true) {
uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! workb_temp) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
io_source_t io_source_temp;
io_source_temp.type = SJPEG_IO_SOURCE_C_ARRAY;
io_source_temp.raw_sjpg_data = sjpeg->sjpeg_data;
io_source_temp.raw_sjpg_data_size = sjpeg->sjpeg_data_size;
io_source_temp.raw_sjpg_data_next_read_pos = 0;
JDEC jd_tmp;
JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp);
lv_free(workb_temp);
if(rc == JDR_OK) {
sjpeg->sjpeg_x_res = jd_tmp.width;
sjpeg->sjpeg_y_res = jd_tmp.height;
sjpeg->sjpeg_total_frames = 1;
sjpeg->sjpeg_single_frame_height = jd_tmp.height;
sjpeg->frame_base_array = lv_malloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames);
if(! sjpeg->frame_base_array) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->frame_base_offset = NULL;
uint8_t * img_frame_base = sjpeg->sjpeg_data;
sjpeg->frame_base_array[0] = img_frame_base;
sjpeg->sjpeg_cache_frame_index = -1;
sjpeg->frame_cache = (void *)lv_malloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3);
if(! sjpeg->frame_cache) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->io.img_cache_buff = sjpeg->frame_cache;
sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res;
sjpeg->workb = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! sjpeg->workb) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->tjpeg_jd = lv_malloc(sizeof(JDEC));
if(! sjpeg->tjpeg_jd) {
lv_sjpg_cleanup(sjpeg);
sjpeg = NULL;
return LV_RES_INV;
}
sjpeg->io.type = SJPEG_IO_SOURCE_C_ARRAY;
sjpeg->io.lv_file.file_d = NULL;
dsc->img_data = NULL;
return lv_ret;
}
else {
lv_ret = LV_RES_INV;
goto end;
}
end:
lv_free(workb_temp);
return lv_ret;
}
}
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
/* If all fine, then the file will be kept open */
const char * fn = dsc->src;
uint8_t * data;
if(strcmp(lv_fs_get_ext(fn), "sjpg") == 0) {
uint8_t buff[22];
memset(buff, 0, sizeof(buff));
lv_fs_file_t lv_file;
lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
return 78;
}
uint32_t rn;
res = lv_fs_read(&lv_file, buff, 22, &rn);
if(res != LV_FS_RES_OK || rn != 22) {
lv_fs_close(&lv_file);
return LV_RES_INV;
}
if(strcmp((char *)buff, "_SJPG__") == 0) {
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
if(sjpeg == NULL) {
sjpeg = lv_malloc(sizeof(SJPEG));
if(! sjpeg) {
lv_fs_close(&lv_file);
return LV_RES_INV;
}
memset(sjpeg, 0, sizeof(SJPEG));
dsc->user_data = sjpeg;
sjpeg->sjpeg_data = (uint8_t *)((lv_image_dsc_t *)(dsc->src))->data;
sjpeg->sjpeg_data_size = ((lv_image_dsc_t *)(dsc->src))->data_size;
}
data = buff;
data += 14;
sjpeg->sjpeg_x_res = *data++;
sjpeg->sjpeg_x_res |= *data++ << 8;
sjpeg->sjpeg_y_res = *data++;
sjpeg->sjpeg_y_res |= *data++ << 8;
sjpeg->sjpeg_total_frames = *data++;
sjpeg->sjpeg_total_frames |= *data++ << 8;
sjpeg->sjpeg_single_frame_height = *data++;
sjpeg->sjpeg_single_frame_height |= *data++ << 8;
sjpeg->frame_base_array = NULL;//lv_malloc( sizeof(uint8_t *) * sjpeg->sjpeg_total_frames );
sjpeg->frame_base_offset = lv_malloc(sizeof(int) * sjpeg->sjpeg_total_frames);
if(! sjpeg->frame_base_offset) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
int img_frame_start_offset = (SJPEG_FRAME_INFO_ARRAY_OFFSET + sjpeg->sjpeg_total_frames * 2);
sjpeg->frame_base_offset[0] = img_frame_start_offset; //pointer used to save integer for now...
for(int i = 1; i < sjpeg->sjpeg_total_frames; i++) {
res = lv_fs_read(&lv_file, buff, 2, &rn);
if(res != LV_FS_RES_OK || rn != 2) {
lv_fs_close(&lv_file);
return LV_RES_INV;
}
data = buff;
int offset = *data++;
offset |= *data++ << 8;
sjpeg->frame_base_offset[i] = sjpeg->frame_base_offset[i - 1] + offset;
}
sjpeg->sjpeg_cache_frame_index = -1; //INVALID AT BEGINNING for a forced compare mismatch at first time.
sjpeg->frame_cache = (void *)lv_malloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3);
if(! sjpeg->frame_cache) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->io.img_cache_buff = sjpeg->frame_cache;
sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res;
sjpeg->workb = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! sjpeg->workb) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->tjpeg_jd = lv_malloc(sizeof(JDEC));
if(! sjpeg->tjpeg_jd) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->io.type = SJPEG_IO_SOURCE_DISK;
sjpeg->io.lv_file = lv_file;
dsc->img_data = NULL;
return LV_RES_OK;
}
}
else if(strcmp(lv_fs_get_ext(fn), "jpg") == 0) {
lv_fs_file_t lv_file;
lv_fs_res_t res = lv_fs_open(&lv_file, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
return LV_RES_INV;
}
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
if(sjpeg == NULL) {
sjpeg = lv_malloc(sizeof(SJPEG));
if(! sjpeg) {
lv_fs_close(&lv_file);
return LV_RES_INV;
}
memset(sjpeg, 0, sizeof(SJPEG));
dsc->user_data = sjpeg;
sjpeg->sjpeg_data = (uint8_t *)((lv_image_dsc_t *)(dsc->src))->data;
sjpeg->sjpeg_data_size = ((lv_image_dsc_t *)(dsc->src))->data_size;
}
uint8_t * workb_temp = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! workb_temp) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
io_source_t io_source_temp;
io_source_temp.type = SJPEG_IO_SOURCE_DISK;
io_source_temp.raw_sjpg_data_next_read_pos = 0;
io_source_temp.img_cache_buff = NULL;
io_source_temp.lv_file = lv_file;
JDEC jd_tmp;
JRESULT rc = jd_prepare(&jd_tmp, input_func, workb_temp, (size_t)TJPGD_WORKBUFF_SIZE, &io_source_temp);
lv_free(workb_temp);
if(rc == JDR_OK) {
sjpeg->sjpeg_x_res = jd_tmp.width;
sjpeg->sjpeg_y_res = jd_tmp.height;
sjpeg->sjpeg_total_frames = 1;
sjpeg->sjpeg_single_frame_height = jd_tmp.height;
sjpeg->frame_base_array = NULL;
sjpeg->frame_base_offset = lv_malloc(sizeof(uint8_t *) * sjpeg->sjpeg_total_frames);
if(! sjpeg->frame_base_offset) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
int img_frame_start_offset = 0;
sjpeg->frame_base_offset[0] = img_frame_start_offset;
sjpeg->sjpeg_cache_frame_index = -1;
sjpeg->frame_cache = (void *)lv_malloc(sjpeg->sjpeg_x_res * sjpeg->sjpeg_single_frame_height * 3);
if(! sjpeg->frame_cache) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->io.img_cache_buff = sjpeg->frame_cache;
sjpeg->io.img_cache_x_res = sjpeg->sjpeg_x_res;
sjpeg->workb = lv_malloc(TJPGD_WORKBUFF_SIZE);
if(! sjpeg->workb) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->tjpeg_jd = lv_malloc(sizeof(JDEC));
if(! sjpeg->tjpeg_jd) {
lv_fs_close(&lv_file);
lv_sjpg_cleanup(sjpeg);
return LV_RES_INV;
}
sjpeg->io.type = SJPEG_IO_SOURCE_DISK;
sjpeg->io.lv_file = lv_file;
dsc->img_data = NULL;
return LV_RES_OK;
}
else {
if(dsc->user_data) lv_free(dsc->user_data);
lv_fs_close(&lv_file);
return LV_RES_INV;
}
}
}
return LV_RES_INV;
}
/**
* Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
* Required only if the "open" function can't open the whole decoded pixel array. (dsc->img_data == NULL)
* @param decoder pointer to the decoder the function associated with
* @param dsc pointer to decoder descriptor
* @param x start x coordinate
* @param y start y coordinate
* @param len number of pixels to decode
* @param buf a buffer to store the decoded pixels
* @return LV_RES_OK: ok; LV_RES_INV: failed
*/
static lv_res_t decoder_read_line(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_coord_t x,
lv_coord_t y,
lv_coord_t len, uint8_t * buf)
{
LV_UNUSED(decoder);
if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
JRESULT rc;
int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height;
/*If line not from cache, refresh cache */
if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) {
sjpeg->io.raw_sjpg_data = sjpeg->frame_base_array[ sjpeg_req_frame_index ];
if(sjpeg_req_frame_index == (sjpeg->sjpeg_total_frames - 1)) {
/*This is the last frame. */
const uint32_t frame_offset = (uint32_t)(sjpeg->io.raw_sjpg_data - sjpeg->sjpeg_data);
sjpeg->io.raw_sjpg_data_size = sjpeg->sjpeg_data_size - frame_offset;
}
else {
sjpeg->io.raw_sjpg_data_size =
(uint32_t)(sjpeg->frame_base_array[sjpeg_req_frame_index + 1] - sjpeg->io.raw_sjpg_data);
}
sjpeg->io.raw_sjpg_data_next_read_pos = 0;
rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io));
if(rc != JDR_OK) return LV_RES_INV;
rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0);
if(rc != JDR_OK) return LV_RES_INV;
sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index;
}
int offset = 0;
uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res *
3;
#if LV_COLOR_DEPTH == 32
for(int i = 0; i < len; i++) {
buf[offset + 3] = 0xff;
buf[offset + 2] = *cache++;
buf[offset + 1] = *cache++;
buf[offset + 0] = *cache++;
offset += 4;
}
#elif LV_COLOR_DEPTH == 24
for(int i = 0; i < len; i++) {
buf[offset + 2] = *cache++;
buf[offset + 1] = *cache++;
buf[offset + 0] = *cache++;
offset += 3;
}
#elif LV_COLOR_DEPTH == 16
for(int i = 0; i < len; i++) {
uint16_t col_16bit = (*cache++ & 0xf8) << 8;
col_16bit |= (*cache++ & 0xFC) << 3;
col_16bit |= (*cache++ >> 3);
#if LV_BIG_ENDIAN_SYSTEM == 1
buf[offset++] = col_16bit >> 8;
buf[offset++] = col_16bit & 0xff;
#else
buf[offset++] = col_16bit & 0xff;
buf[offset++] = col_16bit >> 8;
#endif // LV_BIG_ENDIAN_SYSTEM
}
#elif LV_COLOR_DEPTH == 8
for(int i = 0; i < len; i++) {
uint8_t col_8bit = (*cache++ & 0xC0);
col_8bit |= (*cache++ & 0xe0) >> 2;
col_8bit |= (*cache++ & 0xe0) >> 5;
buf[offset++] = col_8bit;
}
#else
#error Unsupported LV_COLOR_DEPTH
#endif // LV_COLOR_DEPTH
return LV_RES_OK;
}
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
JRESULT rc;
int sjpeg_req_frame_index = y / sjpeg->sjpeg_single_frame_height;
lv_fs_file_t * lv_file_p = &(sjpeg->io.lv_file);
if(!lv_file_p) goto end;
/*If line not from cache, refresh cache */
if(sjpeg_req_frame_index != sjpeg->sjpeg_cache_frame_index) {
sjpeg->io.raw_sjpg_data_next_read_pos = (int)(sjpeg->frame_base_offset [ sjpeg_req_frame_index ]);
lv_fs_seek(&(sjpeg->io.lv_file), sjpeg->io.raw_sjpg_data_next_read_pos, LV_FS_SEEK_SET);
rc = jd_prepare(sjpeg->tjpeg_jd, input_func, sjpeg->workb, (size_t)TJPGD_WORKBUFF_SIZE, &(sjpeg->io));
if(rc != JDR_OK) return LV_RES_INV;
rc = jd_decomp(sjpeg->tjpeg_jd, img_data_cb, 0);
if(rc != JDR_OK) return LV_RES_INV;
sjpeg->sjpeg_cache_frame_index = sjpeg_req_frame_index;
}
int offset = 0;
uint8_t * cache = (uint8_t *)sjpeg->frame_cache + x * 3 + (y % sjpeg->sjpeg_single_frame_height) * sjpeg->sjpeg_x_res *
3;
#if LV_COLOR_DEPTH == 32
for(int i = 0; i < len; i++) {
buf[offset + 3] = 0xff;
buf[offset + 2] = *cache++;
buf[offset + 1] = *cache++;
buf[offset + 0] = *cache++;
offset += 4;
}
#elif LV_COLOR_DEPTH == 24
for(int i = 0; i < len; i++) {
buf[offset + 2] = *cache++;
buf[offset + 1] = *cache++;
buf[offset + 0] = *cache++;
offset += 3;
}
#elif LV_COLOR_DEPTH == 16
for(int i = 0; i < len; i++) {
uint16_t col_8bit = (*cache++ & 0xf8) << 8;
col_8bit |= (*cache++ & 0xFC) << 3;
col_8bit |= (*cache++ >> 3);
#if LV_BIG_ENDIAN_SYSTEM == 1
buf[offset++] = col_8bit >> 8;
buf[offset++] = col_8bit & 0xff;
#else
buf[offset++] = col_8bit & 0xff;
buf[offset++] = col_8bit >> 8;
#endif // LV_BIG_ENDIAN_SYSTEM
}
#elif LV_COLOR_DEPTH == 8
for(int i = 0; i < len; i++) {
uint8_t col_8bit = (*cache++ & 0xC0);
col_8bit |= (*cache++ & 0xe0) >> 2;
col_8bit |= (*cache++ & 0xe0) >> 5;
buf[offset++] = col_8bit;
}
#else
#error Unsupported LV_COLOR_DEPTH
#endif // LV_COLOR_DEPTH
return LV_RES_OK;
}
end:
return LV_RES_INV;
}
/**
* Free the allocated resources
* @param decoder pointer to the decoder where this function belongs
* @param dsc pointer to a descriptor which describes this decoding session
*/
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
LV_UNUSED(decoder);
/*Free all allocated data*/
SJPEG * sjpeg = (SJPEG *) dsc->user_data;
if(!sjpeg) return;
switch(dsc->src_type) {
case LV_IMAGE_SRC_FILE:
if(sjpeg->io.lv_file.file_d) {
lv_fs_close(&(sjpeg->io.lv_file));
}
lv_sjpg_cleanup(sjpeg);
break;
case LV_IMAGE_SRC_VARIABLE:
lv_sjpg_cleanup(sjpeg);
break;
default:
;
}
}
static int is_jpg(const uint8_t * raw_data, size_t len)
{
const uint8_t jpg_signature[] = {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46};
if(len < sizeof(jpg_signature)) return false;
return memcmp(jpg_signature, raw_data, sizeof(jpg_signature)) == 0;
}
static void lv_sjpg_free(SJPEG * sjpeg)
{
if(sjpeg->frame_cache) lv_free(sjpeg->frame_cache);
if(sjpeg->frame_base_array) lv_free(sjpeg->frame_base_array);
if(sjpeg->frame_base_offset) lv_free(sjpeg->frame_base_offset);
if(sjpeg->tjpeg_jd) lv_free(sjpeg->tjpeg_jd);
if(sjpeg->workb) lv_free(sjpeg->workb);
}
static void lv_sjpg_cleanup(SJPEG * sjpeg)
{
if(! sjpeg) return;
lv_sjpg_free(sjpeg);
lv_free(sjpeg);
}
#endif /*LV_USE_SJPG*/

View File

@@ -17,7 +17,7 @@
#include "libs/fsdrv/lv_fsdrv.h" #include "libs/fsdrv/lv_fsdrv.h"
#include "libs/gif/lv_gif.h" #include "libs/gif/lv_gif.h"
#include "libs/png/lv_png.h" #include "libs/png/lv_png.h"
#include "libs/sjpg/lv_sjpg.h" #include "libs/jpg/lv_jpg.h"
#include "draw/lv_draw.h" #include "draw/lv_draw.h"
#include "misc/lv_cache.h" #include "misc/lv_cache.h"
#include "misc/lv_cache_builtin.h" #include "misc/lv_cache_builtin.h"
@@ -220,7 +220,7 @@ void lv_init(void)
#endif #endif
#if LV_USE_SJPG #if LV_USE_SJPG
lv_split_jpeg_init(); lv_jpeg_init();
#endif #endif
#if LV_USE_BMP #if LV_USE_BMP

View File

@@ -167,14 +167,14 @@ typedef uint8_t lv_color_format_t;
/** /**
* Get the pixel size of a color format in bytes * Get the pixel size of a color format in bytes
* @param src_cf a color format (`LV_IMAGE_CF_...`) * @param src_cf a color format (`LV_COLOR_FORMAT_...`)
* @return the pixel size in bytes * @return the pixel size in bytes
*/ */
uint8_t lv_color_format_get_size(lv_color_format_t src_cf); uint8_t lv_color_format_get_size(lv_color_format_t src_cf);
/** /**
* Get the pixel size of a color format in bits, bpp * Get the pixel size of a color format in bits, bpp
* @param src_cf a color format (`LV_IMAGE_CF_...`) * @param src_cf a color format (`LV_COLOR_FORMAT_...`)
* @return the pixel size in bits * @return the pixel size in bits
*/ */
uint8_t lv_color_format_get_bpp(lv_color_format_t cf); uint8_t lv_color_format_get_bpp(lv_color_format_t cf);

View File

@@ -106,7 +106,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
/* If this is a memory-mapped file, then set "cache" to the memory buffer */ /* If this is a memory-mapped file, then set "cache" to the memory buffer */
if(drv->cache_size == LV_FS_CACHE_FROM_BUFFER) { if(drv->cache_size == LV_FS_CACHE_FROM_BUFFER) {
lv_fs_path_ex_t * path_ex = (lv_fs_path_ex_t *)path; lv_fs_path_ex_t * path_ex = (lv_fs_path_ex_t *)path;
file_p->cache->buffer = path_ex->buffer; file_p->cache->buffer = (void *)path_ex->buffer;
file_p->cache->start = 0; file_p->cache->start = 0;
file_p->cache->file_position = 0; file_p->cache->file_position = 0;
file_p->cache->end = path_ex->size; file_p->cache->end = path_ex->size;
@@ -121,7 +121,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
return LV_FS_RES_OK; return LV_FS_RES_OK;
} }
void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, void * buf, uint32_t size) void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, const void * buf, uint32_t size)
{ {
path->path[0] = letter; path->path[0] = letter;
path->path[1] = ':'; path->path[1] = ':';
@@ -175,7 +175,7 @@ static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t
/* Do not allow reading beyond the actual memory block for memory-mapped files */ /* Do not allow reading beyond the actual memory block for memory-mapped files */
if(file_p->drv->cache_size == LV_FS_CACHE_FROM_BUFFER) { if(file_p->drv->cache_size == LV_FS_CACHE_FROM_BUFFER) {
if(btr > buffer_remaining_length) if(btr > buffer_remaining_length)
btr = buffer_remaining_length; btr = buffer_remaining_length - 1;
} }
if(btr <= buffer_remaining_length) { if(btr <= buffer_remaining_length) {

View File

@@ -115,7 +115,7 @@ typedef struct {
/* Extended path object to specify the buffer for memory-mapped files */ /* Extended path object to specify the buffer for memory-mapped files */
typedef struct { typedef struct {
char path[4]; /* This is needed to make it compatible with a normal path */ char path[4]; /* This is needed to make it compatible with a normal path */
void * buffer; const void * buffer;
uint32_t size; uint32_t size;
} lv_fs_path_ex_t; } lv_fs_path_ex_t;
@@ -180,7 +180,7 @@ lv_fs_res_t lv_fs_open(lv_fs_file_t * file_p, const char * path, lv_fs_mode_t mo
* @param buf address of the memory buffer * @param buf address of the memory buffer
* @param size size of the memory buffer in bytes * @param size size of the memory buffer in bytes
*/ */
void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, void * buf, uint32_t size); void lv_fs_make_path_from_buffer(lv_fs_path_ex_t * path, char letter, const void * buf, uint32_t size);
/** /**
* Close an already opened file * Close an already opened file

View File

@@ -159,6 +159,8 @@ add_library(test_common
src/test_assets/font_3_bin.c src/test_assets/font_3_bin.c
src/test_assets/test_img_caret_down.c src/test_assets/test_img_caret_down.c
src/test_assets/test_arc_bg.c src/test_assets/test_arc_bg.c
src/test_assets/test_img_lvgl_logo_png.c
src/test_assets/test_img_lvgl_logo_jpg.c
src/test_assets/ubuntu_font.c src/test_assets/ubuntu_font.c
unity/unity_support.c unity/unity_support.c
unity/unity.c unity/unity.c
@@ -176,7 +178,7 @@ set(generate_test_runner_config ${CMAKE_CURRENT_SOURCE_DIR}/config.yml)
# disable test targets for build only tests # disable test targets for build only tests
if (ENABLE_TESTS) if (ENABLE_TESTS)
file( GLOB TEST_CASE_FILES src/test_cases/*.c ) file( GLOB_RECURSE TEST_CASE_FILES src/test_cases/*.c )
else() else()
set(TEST_CASE_FILES) set(TEST_CASE_FILES)
endif() endif()

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,174 @@
#include "../../../lvgl.h"
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_JPG
#define LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_JPG
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_JPG uint8_t
test_img_lvgl_logo_jpg_map[] = {
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01,
0x01, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x13, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49,
0x4d, 0x50, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x08, 0x06, 0x06, 0x07, 0x06, 0x05,
0x08, 0x07, 0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x15, 0x0e, 0x0c, 0x0b,
0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f, 0x15, 0x1e, 0x1b, 0x20, 0x1f, 0x1e, 0x1b,
0x1d, 0x1d, 0x21, 0x25, 0x30, 0x29, 0x21, 0x23, 0x2d, 0x24, 0x1d, 0x1d, 0x2a,
0x39, 0x2a, 0x2d, 0x31, 0x33, 0x36, 0x36, 0x36, 0x20, 0x28, 0x3b, 0x3f, 0x3a,
0x34, 0x3e, 0x30, 0x35, 0x36, 0x33, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x09, 0x09,
0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0e, 0x0e, 0x18, 0x33, 0x22, 0x1d, 0x22, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xff, 0xc0, 0x00,
0x11, 0x08, 0x00, 0x21, 0x00, 0x69, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01,
0x03, 0x11, 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 0xc4, 0x00,
0xb5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33,
0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc4,
0x00, 0x1f, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, 0x02, 0x01,
0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00,
0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x4f, 0x11, 0xfc, 0x6b, 0xf1, 0x25,
0x8f, 0x89, 0x35, 0x2b, 0x2b, 0x2b, 0x7b, 0x04, 0xb7, 0xb6, 0xb9, 0x78, 0x50,
0x49, 0x13, 0x33, 0x10, 0xac, 0x57, 0x24, 0xee, 0x1d, 0x71, 0x9a, 0x00, 0xcb,
0xff, 0x00, 0x85, 0xeb, 0xe2, 0xef, 0xf9, 0xe7, 0xa6, 0xff, 0x00, 0xdf, 0x86,
0xff, 0x00, 0xe2, 0xa9, 0x88, 0xd7, 0xf0, 0xe7, 0xc5, 0x5f, 0x1b, 0xf8, 0x9b,
0x57, 0x5d, 0x36, 0xd6, 0x4d, 0x0e, 0x09, 0x59, 0x19, 0xc3, 0xdc, 0xc6, 0xc8,
0xb8, 0x03, 0x3d, 0x77, 0x1e, 0x69, 0x0c, 0xf5, 0x4f, 0x87, 0xfe, 0x25, 0xbb,
0xf1, 0x4f, 0x84, 0xe3, 0xd4, 0x6f, 0xa3, 0x85, 0x2e, 0x44, 0xaf, 0x14, 0x9e,
0x47, 0xdc, 0x62, 0xa7, 0x19, 0x1c, 0x9a, 0x00, 0xd7, 0xd0, 0xb5, 0xbb, 0x5f,
0x11, 0x69, 0x11, 0x6a, 0x56, 0x42, 0x41, 0x04, 0x8c, 0xca, 0xa2, 0x45, 0xc3,
0x65, 0x58, 0xa9, 0xe3, 0xea, 0x0d, 0x00, 0x26, 0xb9, 0xae, 0xda, 0x78, 0x7a,
0xce, 0x2b, 0xbb, 0xe1, 0x20, 0xb7, 0x79, 0xd2, 0x16, 0x91, 0x14, 0x11, 0x19,
0x63, 0x80, 0xcd, 0xcf, 0x0b, 0x9c, 0x73, 0xef, 0x40, 0x1a, 0x74, 0x01, 0x43,
0x5a, 0xd6, 0x2d, 0x34, 0x0d, 0x22, 0xe3, 0x53, 0xbe, 0x66, 0x10, 0x42, 0x01,
0x21, 0x46, 0x59, 0x89, 0x38, 0x00, 0x0e, 0xe4, 0x92, 0x00, 0x14, 0x00, 0xeb,
0xcd, 0x56, 0xcf, 0x4d, 0xd3, 0x0e, 0xa3, 0xa8, 0xce, 0xb6, 0x76, 0xea, 0xa1,
0x9d, 0xa7, 0x21, 0x76, 0xe7, 0xb1, 0xf7, 0xf6, 0x14, 0x01, 0xce, 0xaf, 0xc4,
0x0b, 0x69, 0xd7, 0xcd, 0xb4, 0xd0, 0x7c, 0x43, 0x75, 0x6d, 0xd4, 0x5c, 0x45,
0xa7, 0xb6, 0xc2, 0x3d, 0x40, 0x24, 0x12, 0x3e, 0x82, 0x80, 0x36, 0xb4, 0x4f,
0x11, 0xe9, 0x7e, 0x21, 0x8a, 0x47, 0xd3, 0xee, 0x0b, 0x3c, 0x27, 0x6c, 0xd0,
0xc8, 0x86, 0x39, 0x62, 0x3e, 0x8c, 0x8d, 0x82, 0x28, 0x01, 0xe9, 0xad, 0xda,
0xc9, 0xe2, 0x29, 0xb4, 0x35, 0x12, 0x7d, 0xae, 0x2b, 0x65, 0xb9, 0x63, 0xb7,
0xe5, 0xd8, 0x58, 0xa8, 0xe7, 0xd7, 0x20, 0xd0, 0x06, 0x95, 0x00, 0x14, 0x01,
0xf3, 0x87, 0x88, 0x6f, 0x3c, 0x26, 0x3c, 0x49, 0xaa, 0x09, 0xfc, 0x20, 0x25,
0x98, 0x5d, 0xca, 0x1e, 0x4f, 0xed, 0x29, 0x57, 0x7b, 0x6f, 0x39, 0x38, 0x1c,
0x0c, 0x9e, 0x71, 0x5c, 0x13, 0xc6, 0xb8, 0xc9, 0xab, 0x6c, 0x7d, 0x66, 0x1f,
0x86, 0x63, 0x56, 0x94, 0x6a, 0x7b, 0x4b, 0x5d, 0x27, 0xb7, 0x75, 0xea, 0x72,
0x3e, 0x3c, 0xd2, 0xac, 0xb4, 0x5f, 0x18, 0xde, 0xd8, 0xe9, 0xd1, 0x34, 0x56,
0x88, 0x23, 0x68, 0xe3, 0x67, 0x2d, 0xb7, 0x74, 0x6a, 0xc4, 0x64, 0xf2, 0x79,
0x26, 0xbb, 0xd3, 0xba, 0x3e, 0x52, 0x4b, 0x96, 0x4d, 0x1c, 0xe5, 0x32, 0x4f,
0xa6, 0x7e, 0x09, 0x7f, 0xc9, 0x37, 0x8f, 0xfe, 0xbe, 0x65, 0xfe, 0x62, 0x90,
0xcd, 0x4f, 0x85, 0x5f, 0xf2, 0x4f, 0x6c, 0x7f, 0xeb, 0xb4, 0xff, 0x00, 0xfa,
0x39, 0xe8, 0x03, 0xa4, 0xd6, 0xb4, 0xab, 0x7d, 0x73, 0x44, 0xbc, 0xd2, 0xee,
0x86, 0x61, 0xba, 0x89, 0xa3, 0x6f, 0x6c, 0xf4, 0x23, 0xdc, 0x1c, 0x1f, 0xc2,
0x80, 0x31, 0xbc, 0x05, 0xaa, 0xdc, 0x6a, 0x1e, 0x1c, 0x16, 0x97, 0xe7, 0xfe,
0x26, 0x7a, 0x64, 0x8d, 0x65, 0x76, 0x0f, 0x52, 0xe9, 0xc0, 0x6f, 0xf8, 0x12,
0xe0, 0xfe, 0x34, 0x01, 0x4f, 0x5c, 0xff, 0x00, 0x8a, 0x8b, 0xc7, 0x3a, 0x66,
0x82, 0xbf, 0x35, 0x9e, 0x98, 0x06, 0xa1, 0x7d, 0xe8, 0x5f, 0xa4, 0x28, 0x7f,
0x1c, 0xb6, 0x3d, 0x85, 0x00, 0x45, 0x35, 0xb4, 0x7e, 0x27, 0xf8, 0x9f, 0x3d,
0xb5, 0xe8, 0x12, 0xd8, 0xe8, 0x16, 0xf1, 0x49, 0x1d, 0xbb, 0x0c, 0xab, 0x5c,
0x49, 0x92, 0x1c, 0x8e, 0xfb, 0x54, 0x71, 0xe8, 0x4d, 0x00, 0x77, 0x34, 0x01,
0x02, 0x2d, 0xaa, 0xde, 0x4a, 0xd1, 0xac, 0x22, 0xe5, 0x95, 0x7c, 0xd2, 0xb8,
0xde, 0x40, 0xe9, 0x9e, 0xf8, 0xe4, 0xe2, 0x80, 0x39, 0x3b, 0x5f, 0xf9, 0x2c,
0x7a, 0x87, 0xfd, 0x81, 0x61, 0xff, 0x00, 0xd1, 0xad, 0x40, 0x1d, 0x9d, 0x00,
0x14, 0x01, 0xf3, 0xc6, 0xbd, 0xff, 0x00, 0x08, 0x5f, 0xfc, 0x24, 0x5a, 0x9f,
0xda, 0x06, 0xbf, 0xe7, 0xfd, 0xae, 0x5f, 0x33, 0xcb, 0x30, 0xed, 0xdd, 0xbc,
0xe7, 0x19, 0xe7, 0x19, 0xaf, 0x26, 0xa7, 0xb1, 0xe7, 0x77, 0xbf, 0xe0, 0x7e,
0x87, 0x83, 0xfe, 0xd2, 0xfa, 0xbd, 0x3e, 0x4e, 0x4b, 0x59, 0x5a, 0xfc, 0xd7,
0xb5, 0x89, 0xbc, 0x79, 0x61, 0xe0, 0xc9, 0xbc, 0x5d, 0x73, 0x26, 0xa0, 0x75,
0xe1, 0x72, 0x63, 0x8b, 0x7f, 0xd9, 0xcc, 0x3b, 0x31, 0xe5, 0xae, 0x31, 0xbb,
0x9e, 0x98, 0xcf, 0xbd, 0x76, 0x4f, 0x15, 0x0a, 0x6f, 0x95, 0xa3, 0xe6, 0xb0,
0xd9, 0x0e, 0x23, 0x17, 0x4f, 0xdb, 0x46, 0x49, 0x27, 0x7e, 0xfd, 0xfd, 0x0e,
0x1b, 0xc6, 0x7a, 0x06, 0x9d, 0xa1, 0x5d, 0x69, 0xad, 0xa5, 0xcd, 0x75, 0x25,
0xa5, 0xf5, 0x92, 0xdc, 0xa8, 0xba, 0xdb, 0xbd, 0x72, 0xcc, 0x30, 0x76, 0xf1,
0xfc, 0x35, 0xd3, 0x09, 0x29, 0xc5, 0x49, 0x1e, 0x3e, 0x26, 0x84, 0xb0, 0xf5,
0x65, 0x4a, 0x5b, 0xa7, 0x63, 0xdc, 0xfe, 0x09, 0x7f, 0xc9, 0x37, 0x8f, 0xfe,
0xbe, 0x65, 0xfe, 0x62, 0x99, 0x89, 0xa1, 0xf0, 0xb2, 0x68, 0x93, 0xe1, 0xfd,
0x92, 0xb4, 0xa8, 0x0f, 0x9d, 0x3f, 0x05, 0x87, 0xfc, 0xf6, 0x7a, 0x00, 0xed,
0x16, 0x68, 0x9d, 0xb6, 0xac, 0x88, 0xc7, 0xd0, 0x30, 0x34, 0x01, 0xc2, 0x6b,
0x97, 0x90, 0x78, 0x27, 0xc7, 0x2b, 0xae, 0x5c, 0x37, 0x95, 0xa4, 0xeb, 0x10,
0x18, 0x6e, 0xdb, 0xb2, 0x4f, 0x1a, 0x96, 0x46, 0xfa, 0xb2, 0x82, 0xbf, 0x80,
0xa0, 0x0d, 0x3f, 0x00, 0xd9, 0x4e, 0x34, 0x79, 0xb5, 0xbb, 0xf4, 0x2b, 0xa8,
0x6b, 0x33, 0x1b, 0xb9, 0x41, 0xea, 0x88, 0x78, 0x8d, 0x3f, 0xe0, 0x29, 0x8f,
0xcc, 0xd0, 0x05, 0x1d, 0x66, 0x56, 0xf0, 0x87, 0x8d, 0x9b, 0xc4, 0x73, 0x46,
0xcd, 0xa3, 0x6a, 0x50, 0x25, 0xbd, 0xf4, 0xa8, 0xa5, 0x8d, 0xbc, 0x88, 0x4e,
0xc9, 0x1b, 0x1f, 0xc2, 0x41, 0x20, 0x9e, 0xd4, 0x01, 0xd8, 0x5b, 0x6a, 0x36,
0x37, 0x96, 0xcb, 0x73, 0x6d, 0x79, 0x04, 0xd0, 0x30, 0xc8, 0x92, 0x39, 0x03,
0x29, 0x1f, 0x51, 0x40, 0x1c, 0x96, 0x83, 0x79, 0x6d, 0xa8, 0x7c, 0x4d, 0xf1,
0x0d, 0xc5, 0x9c, 0xf1, 0xdc, 0x40, 0x96, 0x56, 0xd1, 0x34, 0x91, 0x36, 0xe5,
0x0e, 0x0b, 0xe5, 0x72, 0x38, 0xc8, 0xc8, 0xe2, 0x80, 0x16, 0x09, 0x12, 0x3f,
0x8c, 0x5a, 0x81, 0x77, 0x55, 0x1f, 0xd8, 0xb0, 0xf5, 0x38, 0xff, 0x00, 0x96,
0xad, 0x40, 0x1d, 0x8f, 0xda, 0x20, 0xff, 0x00, 0x9e, 0xd1, 0xff, 0x00, 0xdf,
0x42, 0x80, 0x1d, 0xbd, 0x3f, 0xbe, 0xbf, 0x9d, 0x00, 0x79, 0x46, 0xa9, 0xf0,
0x6a, 0x6d, 0x47, 0x56, 0xbc, 0xbd, 0x1a, 0xda, 0x20, 0xb8, 0x9d, 0xe5, 0x08,
0x6d, 0x89, 0xdb, 0xb9, 0x89, 0xc6, 0x77, 0x7b, 0xd7, 0x04, 0xf0, 0x5c, 0xd2,
0x6f, 0x98, 0xfa, 0xcc, 0x3f, 0x13, 0x46, 0x95, 0x28, 0xd3, 0xf6, 0x57, 0xb2,
0x4b, 0x7e, 0xcb, 0xd0, 0xb7, 0xe2, 0x3f, 0x84, 0xd2, 0xeb, 0xda, 0xdc, 0xba,
0x82, 0xeb, 0x09, 0x08, 0x91, 0x11, 0x76, 0x1b, 0x72, 0xd8, 0xda, 0x81, 0x7a,
0xee, 0xf6, 0xaa, 0xab, 0x84, 0xe7, 0x97, 0x35, 0xcc, 0x70, 0x3c, 0x42, 0xb0,
0xb4, 0x15, 0x2f, 0x67, 0x7b, 0x5f, 0xaf, 0x77, 0x7e, 0xc5, 0x4f, 0x12, 0x7c,
0x1a, 0x97, 0x5e, 0x8f, 0x49, 0x55, 0xd6, 0xd2, 0x13, 0x61, 0x64, 0xb6, 0xa4,
0x9b, 0x62, 0xdb, 0xf0, 0xcc, 0x77, 0x7d, 0xee, 0x3e, 0xf7, 0x4a, 0xea, 0xa7,
0x1e, 0x48, 0xa8, 0xf6, 0x3c, 0x1c, 0x5d, 0x7f, 0xac, 0x57, 0x9d, 0x5b, 0x5b,
0x99, 0xdc, 0xee, 0x3c, 0x15, 0xe1, 0x64, 0xf0, 0x7f, 0x86, 0x61, 0xd2, 0x16,
0xe4, 0xdc, 0x95, 0x66, 0x77, 0x94, 0xae, 0xdd, 0xc5, 0x8f, 0x61, 0x93, 0x81,
0x56, 0x73, 0x91, 0x37, 0xc3, 0xcf, 0x08, 0x33, 0x16, 0x6f, 0x0f, 0x58, 0x12,
0x4e, 0x49, 0x31, 0x75, 0xa0, 0x0b, 0x7a, 0x6f, 0x83, 0xfc, 0x3b, 0xa3, 0xde,
0xad, 0xe6, 0x9d, 0xa3, 0xda, 0x5a, 0xdc, 0xa8, 0x20, 0x49, 0x12, 0x60, 0x80,
0x7a, 0xd0, 0x05, 0xfd, 0x4f, 0x4a, 0xb0, 0xd6, 0x6c, 0xcd, 0xa6, 0xa5, 0x69,
0x15, 0xd5, 0xb9, 0x60, 0xc6, 0x39, 0x57, 0x23, 0x23, 0xa1, 0xa0, 0x0b, 0x6a,
0xa1, 0x54, 0x2a, 0x80, 0x00, 0x18, 0x00, 0x76, 0xa0, 0x01, 0x95, 0x5d, 0x4a,
0xb2, 0x86, 0x52, 0x30, 0x41, 0x19, 0x06, 0x80, 0x39, 0xb9, 0xbe, 0x1e, 0xf8,
0x42, 0x79, 0xcc, 0xd2, 0x78, 0x7a, 0xc3, 0x79, 0x39, 0x38, 0x88, 0x00, 0x4f,
0xd0, 0x71, 0x40, 0x1b, 0xb6, 0x56, 0x16, 0x9a, 0x6d, 0xaa, 0xdb, 0x58, 0xda,
0xc3, 0x6d, 0x02, 0x7d, 0xd8, 0xe1, 0x40, 0x8a, 0x3f, 0x01, 0x40, 0x19, 0xda,
0xa7, 0x84, 0xbc, 0x3f, 0xad, 0xdd, 0x8b, 0xbd, 0x4f, 0x49, 0xb5, 0xbb, 0xb8,
0x0a, 0x10, 0x49, 0x2a, 0x64, 0xed, 0x1d, 0x07, 0xea, 0x68, 0x02, 0x8f, 0xfc,
0x2b, 0xbf, 0x07, 0xff, 0x00, 0xd0, 0xbb, 0x61, 0xff, 0x00, 0x7e, 0xa8, 0x03,
0x73, 0xfb, 0x32, 0xcb, 0xfe, 0x7d, 0xd2, 0x80, 0x2d, 0xd0, 0x01, 0x40, 0x05,
0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40,
0x05, 0x00, 0x14, 0x00, 0x50, 0x01, 0x40, 0x1f, 0xff, 0xd9
};
const lv_img_dsc_t test_img_lvgl_logo_jpg = {
.header.cf = LV_COLOR_FORMAT_RAW,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 105,
.header.h = 33,
.data_size = 1947,
.data = test_img_lvgl_logo_jpg_map,
};

View File

@@ -0,0 +1,169 @@
#include "../../..//lvgl.h"
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_PNG
#define LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_PNG
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_TEST_IMG_LVGL_LOGO_PNG uint8_t
test_img_lvgl_logo_png_map[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49,
0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x21, 0x08, 0x06,
0x00, 0x00, 0x00, 0xda, 0x89, 0x85, 0x3b, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b,
0x47, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x43, 0xbb, 0x7f, 0x00,
0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2e, 0x23, 0x00, 0x00,
0x2e, 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49,
0x4d, 0x45, 0x07, 0xe7, 0x09, 0x12, 0x12, 0x25, 0x07, 0x59, 0xa0, 0x4e, 0xa5,
0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69,
0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, 0x81, 0x0e, 0x17, 0x00, 0x00,
0x06, 0xb9, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0x9a, 0x7f, 0x8c, 0x5d,
0x45, 0x15, 0xc7, 0x3f, 0xe7, 0xbe, 0xf7, 0x76, 0xa9, 0x20, 0x18, 0x03, 0x9a,
0x6a, 0x77, 0xe6, 0xdd, 0xb7, 0x6b, 0x8a, 0x49, 0xc3, 0x1a, 0xb5, 0x25, 0x80,
0xb5, 0xe2, 0x6a, 0x2b, 0x0d, 0x46, 0x71, 0x89, 0x8a, 0xbf, 0x48, 0x4c, 0xd5,
0xd4, 0x46, 0x08, 0x58, 0x48, 0x10, 0xc5, 0xe8, 0x3f, 0xa6, 0x68, 0x6b, 0xe4,
0x0f, 0x85, 0x22, 0x68, 0x53, 0x6d, 0x9a, 0x40, 0x31, 0x40, 0xc0, 0x92, 0xb6,
0xd0, 0x62, 0x53, 0x4a, 0xac, 0x44, 0xa2, 0xad, 0xa4, 0x76, 0xf7, 0xde, 0xb9,
0xaf, 0x3f, 0x0c, 0x0a, 0xd2, 0x96, 0x6d, 0xd9, 0xdd, 0xb7, 0xf7, 0xf8, 0xc7,
0x9b, 0xca, 0x76, 0xf7, 0xfd, 0x5c, 0x77, 0xdd, 0xd7, 0xe4, 0x7d, 0x93, 0x97,
0x97, 0xb9, 0x33, 0x77, 0x66, 0xce, 0xf9, 0xce, 0x39, 0x73, 0xe6, 0xcc, 0x85,
0x36, 0xda, 0x68, 0xe3, 0x7f, 0x87, 0x00, 0x98, 0x7c, 0xbe, 0x13, 0x95, 0xe5,
0x40, 0x0f, 0x5a, 0x7e, 0x36, 0x8d, 0x23, 0x0c, 0xa1, 0x6c, 0x4d, 0x92, 0x68,
0xa0, 0xad, 0xee, 0x29, 0xaa, 0xd0, 0x5a, 0x13, 0x28, 0x99, 0xcd, 0xc0, 0xf5,
0x67, 0x48, 0x9b, 0x01, 0x9c, 0x00, 0x96, 0x26, 0x2e, 0x7a, 0xbe, 0xad, 0xf2,
0xe6, 0x91, 0x85, 0xcc, 0x42, 0xa0, 0x7f, 0x06, 0x08, 0x2a, 0x01, 0x81, 0xff,
0x5d, 0x08, 0xdc, 0x02, 0x7c, 0x7e, 0x7c, 0x83, 0xae, 0xae, 0x82, 0x48, 0xa0,
0x9d, 0x80, 0x04, 0xa2, 0xc3, 0x71, 0x1c, 0xa7, 0xf5, 0x3a, 0x35, 0xb6, 0x90,
0x45, 0x35, 0x07, 0x68, 0x92, 0x44, 0x6f, 0x4c, 0x75, 0x72, 0xf3, 0xc2, 0x30,
0x08, 0x52, 0x3a, 0x01, 0x4d, 0x5c, 0xfd, 0x7e, 0xac, 0x0d, 0x73, 0xaa, 0xbc,
0x05, 0xd1, 0x9c, 0x57, 0xd5, 0x88, 0xa2, 0xa7, 0x8b, 0x2e, 0x1e, 0x6d, 0x64,
0x3c, 0x6b, 0x0b, 0x19, 0x55, 0xed, 0x40, 0x34, 0x4d, 0x5c, 0x3c, 0xdc, 0xcc,
0x5c, 0x03, 0x85, 0x8b, 0xbd, 0x22, 0xa7, 0x13, 0x03, 0xc0, 0xe5, 0xc0, 0xa7,
0x80, 0xd3, 0xfe, 0xd9, 0x3b, 0x27, 0x99, 0xb1, 0xf0, 0x56, 0xe0, 0x79, 0xe0,
0x40, 0xaa, 0xd2, 0xdb, 0x58, 0xd7, 0xda, 0x8b, 0xb0, 0x1f, 0xe1, 0xaf, 0xc6,
0x86, 0xf3, 0xa7, 0xec, 0x42, 0x52, 0xbe, 0x08, 0xbc, 0x04, 0x3c, 0x62, 0xf2,
0x85, 0x6c, 0x45, 0x22, 0x4d, 0x3e, 0x6b, 0x6c, 0xf8, 0x31, 0x63, 0xc3, 0x5f,
0x2b, 0xbc, 0x88, 0x30, 0x08, 0x52, 0x04, 0x8a, 0xc0, 0xa0, 0x20, 0x7f, 0x36,
0x36, 0x7c, 0xc0, 0xd8, 0x70, 0x89, 0xc9, 0x87, 0x99, 0x9a, 0xb3, 0x46, 0xaf,
0x43, 0x78, 0x09, 0xe4, 0x31, 0x63, 0xc3, 0x6c, 0x53, 0x24, 0xcd, 0x90, 0x85,
0x3e, 0x9b, 0xb8, 0xe8, 0x05, 0xa1, 0xf4, 0x24, 0x70, 0xac, 0xce, 0xf8, 0xef,
0x06, 0x8c, 0x22, 0xb9, 0x86, 0x28, 0x4a, 0xf5, 0x45, 0xe0, 0x35, 0xa0, 0x1b,
0x58, 0x31, 0x95, 0xc9, 0x19, 0x53, 0xc8, 0x08, 0x7c, 0x0b, 0x30, 0xc0, 0x13,
0x49, 0x3c, 0x58, 0x9a, 0x68, 0xe1, 0xc6, 0x86, 0x57, 0x07, 0x22, 0x7b, 0x80,
0x6d, 0xc0, 0x8d, 0xc0, 0x7c, 0x20, 0x07, 0xfc, 0xc3, 0xcb, 0x94, 0xf5, 0xcf,
0xbe, 0x0a, 0xec, 0x44, 0x79, 0xda, 0xd8, 0xb0, 0xd6, 0x42, 0x9b, 0xe3, 0xc7,
0x9b, 0xab, 0xa2, 0xb4, 0x02, 0x49, 0xfd, 0xc6, 0x86, 0xb7, 0x2b, 0xd9, 0xb5,
0x80, 0x9d, 0xce, 0x8e, 0x8b, 0xc5, 0xb8, 0x04, 0xfc, 0xd8, 0x17, 0x57, 0xd8,
0x7c, 0x78, 0x49, 0xb3, 0x7d, 0xa8, 0x68, 0x1f, 0xb0, 0x10, 0x38, 0x26, 0xe8,
0x86, 0xb3, 0x09, 0xcc, 0x8b, 0x04, 0x7a, 0x07, 0xf0, 0xd4, 0x99, 0x36, 0xc0,
0xf7, 0x80, 0x45, 0x88, 0xbe, 0x23, 0x71, 0x51, 0x98, 0xb8, 0xa8, 0xa0, 0xa2,
0x97, 0x80, 0xf6, 0x02, 0xb7, 0x01, 0x09, 0xf0, 0x61, 0xe0, 0x59, 0x63, 0xc3,
0x65, 0x33, 0xb0, 0x27, 0xcd, 0x08, 0x2e, 0x04, 0xd6, 0xcc, 0xd8, 0x4e, 0xaa,
0x3c, 0x86, 0x10, 0x03, 0x79, 0x55, 0xbe, 0x0c, 0xac, 0x6b, 0xf4, 0x55, 0x6b,
0xc3, 0x40, 0xe1, 0x26, 0x5f, 0x7c, 0xd0, 0xb9, 0xf8, 0xf5, 0x71, 0xfb, 0x94,
0x90, 0xf2, 0x5d, 0xe0, 0x87, 0x80, 0x02, 0xbf, 0x50, 0xe1, 0x8e, 0x62, 0x1c,
0x1d, 0x9f, 0xb4, 0x58, 0xe2, 0x78, 0x14, 0xd8, 0x0f, 0xec, 0x37, 0xa6, 0x70,
0x1f, 0xa2, 0x6b, 0x80, 0x65, 0x40, 0x34, 0xdd, 0xe2, 0x06, 0xc0, 0xcb, 0x40,
0xca, 0x39, 0x84, 0x24, 0x89, 0x86, 0x80, 0xfb, 0x7d, 0x71, 0xa5, 0xb5, 0xb6,
0xa3, 0x71, 0x7e, 0xb9, 0xd4, 0x2b, 0xf3, 0x34, 0x70, 0xef, 0x59, 0xca, 0x48,
0xe9, 0x03, 0xee, 0xf2, 0xc5, 0xef, 0xa8, 0xe8, 0xaa, 0x4a, 0x04, 0x4d, 0x9e,
0xcf, 0xe0, 0x49, 0x90, 0x55, 0x22, 0xb2, 0x30, 0x71, 0xd1, 0xc1, 0x69, 0xb7,
0xa4, 0x4c, 0x90, 0xee, 0x2b, 0x8d, 0x05, 0xbd, 0x12, 0xc8, 0xdc, 0x2a, 0x62,
0x65, 0x51, 0xbe, 0x06, 0x5c, 0xd7, 0x4a, 0x44, 0xa9, 0x72, 0x9f, 0x08, 0xab,
0x81, 0x1e, 0x25, 0xb8, 0x1e, 0xd8, 0xd4, 0xe0, 0xab, 0xab, 0xbd, 0x07, 0xd9,
0x90, 0xb8, 0xe8, 0xf0, 0x9b, 0x51, 0xa3, 0xed, 0x04, 0xd6, 0xfa, 0xba, 0x8d,
0x28, 0x6b, 0x8a, 0x2e, 0x6e, 0x78, 0xf3, 0x48, 0xdc, 0xa0, 0x02, 0xaf, 0xce,
0x48, 0x08, 0xbe, 0x35, 0x72, 0x73, 0xb4, 0x1c, 0x89, 0x9d, 0x57, 0x79, 0xe1,
0xf1, 0xf8, 0x52, 0x1b, 0xfe, 0xc0, 0x47, 0x6a, 0x41, 0xab, 0x90, 0x54, 0x4c,
0xa2, 0x57, 0x8c, 0x0d, 0x37, 0x03, 0x2b, 0x81, 0x6f, 0x74, 0xf7, 0xbc, 0x67,
0xf3, 0xc0, 0xa1, 0xbf, 0xa7, 0xb5, 0xc3, 0xf7, 0xf0, 0x5d, 0xfe, 0xb8, 0x51,
0x9a, 0x68, 0x45, 0x10, 0x7c, 0x04, 0xb8, 0x0c, 0x18, 0x42, 0xb9, 0x33, 0x49,
0x22, 0x6d, 0x15, 0x59, 0xb3, 0x0a, 0x4b, 0x80, 0x5f, 0xd6, 0x68, 0x93, 0x57,
0xd8, 0x20, 0x65, 0xc2, 0x5a, 0x0d, 0x3f, 0xf5, 0x11, 0xde, 0xe2, 0xd1, 0x91,
0xd2, 0x95, 0xc0, 0xee, 0x3a, 0xed, 0xbf, 0xee, 0xf7, 0xcb, 0xa7, 0x12, 0x17,
0xed, 0x9b, 0x50, 0xf7, 0x05, 0xff, 0xff, 0x50, 0x92, 0x44, 0xc5, 0x56, 0x12,
0x32, 0x68, 0xc0, 0x3a, 0x02, 0x5a, 0x15, 0x2a, 0x87, 0x80, 0x47, 0x01, 0x41,
0xb8, 0x79, 0x5e, 0x97, 0x91, 0x1a, 0x01, 0xc3, 0x45, 0x9e, 0xa4, 0x14, 0xf8,
0xd9, 0xf8, 0xba, 0x8b, 0xbb, 0x17, 0x08, 0xb0, 0xc8, 0x17, 0x9f, 0x6e, 0x35,
0x31, 0x5b, 0x97, 0x80, 0x86, 0x02, 0x88, 0x41, 0x05, 0x7e, 0xee, 0xdd, 0xf2,
0xb5, 0x22, 0xd9, 0x7c, 0x8d, 0x80, 0xa1, 0x1f, 0x98, 0x0b, 0xfc, 0x2d, 0x95,
0x74, 0xfb, 0xf8, 0xba, 0xf3, 0x4b, 0xa7, 0x2e, 0xa0, 0x7c, 0xa8, 0x4f, 0x81,
0x43, 0x6d, 0x92, 0xa6, 0x19, 0x63, 0xa3, 0x23, 0x3b, 0x81, 0xe7, 0x80, 0xf3,
0x44, 0xf4, 0x96, 0x4a, 0x6d, 0xba, 0x0a, 0x61, 0xce, 0x07, 0x0c, 0x00, 0x6b,
0x0f, 0xc7, 0xee, 0xac, 0x54, 0x4e, 0x0a, 0x19, 0xaf, 0x0b, 0x05, 0x86, 0xa7,
0x32, 0x0f, 0x63, 0xc3, 0x15, 0xc6, 0x86, 0x1b, 0x8d, 0x0d, 0xfb, 0xdb, 0x24,
0x4d, 0xc0, 0x91, 0xa3, 0x47, 0xc6, 0x5b, 0xd3, 0x0d, 0xc6, 0x16, 0xde, 0x3e,
0x29, 0x05, 0x34, 0xc6, 0x32, 0x9f, 0x1d, 0x38, 0x2a, 0x2a, 0x5b, 0x26, 0xd6,
0x67, 0x44, 0x87, 0x81, 0x51, 0xaf, 0x8f, 0x8b, 0xa6, 0x38, 0x95, 0xcb, 0x81,
0x2f, 0xf9, 0xe0, 0xa3, 0x4d, 0xd2, 0x24, 0x12, 0x08, 0xb6, 0x00, 0xae, 0xec,
0xb2, 0xf4, 0xc6, 0x0a, 0x4d, 0x6e, 0xf2, 0xb2, 0xae, 0x77, 0xc9, 0xe0, 0x89,
0x89, 0x95, 0x71, 0x1c, 0x9d, 0xf6, 0xef, 0x0b, 0xb0, 0xa0, 0x15, 0xdd, 0x5d,
0xbd, 0x2c, 0xee, 0x28, 0xc2, 0x49, 0x60, 0xa4, 0x55, 0x49, 0x72, 0x6e, 0xe0,
0x8d, 0x71, 0xc1, 0xc0, 0x2a, 0x6b, 0xed, 0x9c, 0x71, 0x6e, 0x68, 0x11, 0xf0,
0x51, 0xe0, 0x84, 0x0a, 0xeb, 0x6b, 0x74, 0xf3, 0x8c, 0xff, 0xff, 0x4c, 0xab,
0xc9, 0x97, 0x55, 0x78, 0x46, 0xe0, 0x9a, 0x2a, 0xe7, 0xa4, 0x14, 0xf8, 0x83,
0xa0, 0xaf, 0x81, 0x5c, 0xa1, 0x10, 0x56, 0x5e, 0xc9, 0x04, 0x94, 0xef, 0xa3,
0x6e, 0x98, 0xc5, 0x48, 0x6f, 0x13, 0xa2, 0xdf, 0x07, 0x0a, 0x4a, 0x70, 0x0d,
0xf0, 0xc8, 0x99, 0x8c, 0x04, 0xe5, 0x3d, 0x67, 0x4b, 0x31, 0x8e, 0x8e, 0xd5,
0x48, 0x45, 0xfc, 0x06, 0xe1, 0x56, 0x60, 0xb1, 0xb1, 0xe1, 0x92, 0xc4, 0x45,
0xbb, 0x5a, 0x86, 0xa4, 0x71, 0x7e, 0x78, 0x4e, 0x25, 0x92, 0x14, 0x3a, 0xb6,
0xc7, 0x71, 0x90, 0x96, 0x09, 0x7a, 0x5b, 0x95, 0x03, 0xef, 0xae, 0x3e, 0xd3,
0xbd, 0x2b, 0x23, 0x69, 0x3f, 0xd0, 0x31, 0x1b, 0x82, 0x24, 0xc9, 0xe0, 0xcb,
0xc6, 0x86, 0x0f, 0x00, 0xdf, 0x06, 0x6e, 0xeb, 0xe9, 0x9e, 0xff, 0xbb, 0xe1,
0xd2, 0x48, 0x17, 0xe5, 0x3b, 0xac, 0x12, 0xf0, 0x93, 0x9a, 0x2e, 0x25, 0xe0,
0x40, 0xaa, 0x3c, 0x01, 0x7c, 0x1a, 0xb8, 0xa7, 0xcb, 0x14, 0x16, 0x17, 0x2b,
0xb8, 0xc6, 0x59, 0x21, 0x49, 0xe0, 0x6a, 0x60, 0x73, 0x75, 0x7f, 0xcf, 0xdd,
0x29, 0xfc, 0x0a, 0x78, 0xd8, 0xaf, 0xc8, 0x4a, 0xd8, 0x74, 0xa4, 0x23, 0xb3,
0xd2, 0x8c, 0xa6, 0xb3, 0x9b, 0x03, 0x54, 0xd6, 0x23, 0x7c, 0x13, 0x58, 0x38,
0x52, 0x1a, 0xb9, 0x4a, 0xe0, 0x5a, 0xef, 0x21, 0x9e, 0x94, 0xf2, 0xdd, 0x51,
0x55, 0xc4, 0x71, 0x94, 0x5a, 0x1b, 0xde, 0xac, 0x70, 0x25, 0x70, 0x99, 0x88,
0x3e, 0x64, 0x6c, 0xfe, 0xb3, 0x89, 0x8b, 0x8f, 0xcf, 0x36, 0x49, 0x41, 0x0d,
0xc5, 0xbf, 0x19, 0xfc, 0xd4, 0x6f, 0x93, 0x6d, 0x85, 0x15, 0x97, 0x24, 0xd1,
0x41, 0x60, 0xab, 0x97, 0xe9, 0x76, 0xe0, 0x2b, 0xbe, 0xea, 0x1e, 0xe7, 0xa2,
0xba, 0x0b, 0xc8, 0xb9, 0x28, 0x01, 0x3e, 0x07, 0x9c, 0x04, 0x96, 0x82, 0x3c,
0x67, 0x6c, 0xd8, 0x67, 0x4c, 0x4f, 0xa6, 0x7a, 0xe8, 0x5d, 0x08, 0x8c, 0x0d,
0xdf, 0x0f, 0x7c, 0x68, 0x26, 0xdd, 0x5d, 0x4b, 0x04, 0x68, 0x82, 0x5e, 0x65,
0x6c, 0xbe, 0xd1, 0xbb, 0xa1, 0xe3, 0x89, 0x8b, 0x77, 0x57, 0xb1, 0xfc, 0x35,
0x5a, 0xce, 0x33, 0x7e, 0xd2, 0x3f, 0xda, 0x97, 0xcb, 0xe5, 0xb6, 0x37, 0x4c,
0xb4, 0x8b, 0x76, 0x1a, 0x1b, 0x2e, 0x05, 0x7e, 0x0b, 0xbc, 0x17, 0xd8, 0x86,
0x8c, 0xed, 0x35, 0x36, 0xfc, 0x3d, 0xc8, 0x1f, 0x11, 0x2d, 0xa2, 0xaa, 0xa8,
0xcc, 0x45, 0x78, 0x1f, 0xe8, 0xc7, 0x81, 0x3e, 0xaf, 0xcb, 0x18, 0x78, 0xbc,
0xce, 0x10, 0x17, 0x88, 0xb2, 0xdc, 0xd8, 0xfc, 0x58, 0x63, 0xce, 0x41, 0x0e,
0xb4, 0x0c, 0x49, 0xc0, 0xba, 0x26, 0x3e, 0xb3, 0x78, 0x01, 0xf8, 0x40, 0x15,
0xa9, 0xfe, 0x84, 0xb0, 0x97, 0xb2, 0xdb, 0x02, 0xb8, 0x77, 0xe0, 0xd0, 0xc1,
0xb1, 0xa6, 0x2c, 0xd2, 0x45, 0x7b, 0x4d, 0x3e, 0xfc, 0x20, 0xca, 0x6a, 0x9f,
0x4a, 0xba, 0xa2, 0xfc, 0x53, 0x9f, 0xc1, 0x94, 0x89, 0x53, 0xfd, 0x27, 0x70,
0xbf, 0x90, 0xae, 0x73, 0xce, 0xbd, 0x52, 0xa7, 0xfb, 0x10, 0xe4, 0xd1, 0x26,
0x14, 0x73, 0x6b, 0x76, 0x76, 0xcd, 0x27, 0x1d, 0x51, 0x64, 0x23, 0x70, 0x7e,
0x93, 0xaf, 0x56, 0x4d, 0x80, 0xba, 0x24, 0x2a, 0x19, 0x1b, 0xde, 0xe5, 0xdd,
0x56, 0x49, 0x48, 0x37, 0x4d, 0xc9, 0x75, 0xc6, 0xd1, 0xbf, 0x81, 0x3b, 0x8d,
0xc9, 0xff, 0x08, 0x91, 0x4f, 0x78, 0xa2, 0x7a, 0x7c, 0x90, 0x75, 0xe6, 0x5a,
0x62, 0x00, 0xd8, 0x13, 0x08, 0xdb, 0xe2, 0x38, 0x1a, 0xaa, 0x63, 0x12, 0x03,
0xc8, 0x7f, 0xef, 0xc0, 0x9a, 0x59, 0xbd, 0x7f, 0xf9, 0x7f, 0x92, 0x94, 0x4c,
0xde, 0x03, 0xe2, 0x53, 0x94, 0xbf, 0x22, 0x9a, 0xde, 0x81, 0x5c, 0xb4, 0x03,
0xd8, 0x31, 0x3d, 0xfb, 0x5c, 0xfc, 0xba, 0x0f, 0x9a, 0x1e, 0x9e, 0x37, 0x2f,
0x94, 0x20, 0x53, 0x3e, 0x99, 0x24, 0xce, 0x69, 0x73, 0xfd, 0x44, 0x7b, 0x80,
0x3d, 0x53, 0xdd, 0x93, 0x4a, 0xf5, 0xd2, 0x63, 0x0a, 0xf5, 0xdc, 0x45, 0x89,
0x52, 0xa9, 0x04, 0x0c, 0x55, 0x39, 0x6f, 0x1d, 0x05, 0xee, 0x3e, 0xd7, 0x33,
0x1b, 0x87, 0x0f, 0xcf, 0xce, 0x1d, 0x93, 0x1c, 0x84, 0xce, 0xb4, 0xbc, 0xc9,
0x76, 0x56, 0x39, 0x03, 0xed, 0x50, 0xf8, 0x97, 0xc0, 0x72, 0xca, 0x77, 0x31,
0x95, 0xb0, 0xfb, 0x52, 0x70, 0xc6, 0xe4, 0x7b, 0x09, 0x64, 0xc1, 0x84, 0x1e,
0x4e, 0x29, 0xec, 0x2a, 0xba, 0xe8, 0x55, 0xda, 0x68, 0xa3, 0x8d, 0x36, 0xda,
0x68, 0xa3, 0x8d, 0x73, 0x1a, 0xff, 0x01, 0xc1, 0xba, 0x4f, 0x53, 0x6b, 0xda,
0x6f, 0x58, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60,
0x82
};
const lv_img_dsc_t test_img_lvgl_logo_png = {
.header.cf = LV_COLOR_FORMAT_RAW_ALPHA,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 105,
.header.h = 33,
.data_size = 1873,
.data = test_img_lvgl_logo_png_map,
};

View File

@@ -128,7 +128,7 @@ static void canvas_draw(const char * name, lv_color_format_t large_render_cf)
lv_canvas_set_buffer(canvas2, canvas2_buf, 770, 390, large_render_cf); lv_canvas_set_buffer(canvas2, canvas2_buf, 770, 390, large_render_cf);
lv_canvas_fill_bg(canvas2, lv_palette_lighten(LV_PALETTE_BLUE_GREY, 2), LV_OPA_COVER); lv_canvas_fill_bg(canvas2, lv_palette_lighten(LV_PALETTE_BLUE_GREY, 2), LV_OPA_COVER);
lv_image_dsc_t img = { 0 }; lv_img_dsc_t img = { 0 };
img.header.w = 180; img.header.w = 180;
img.header.h = 180; img.header.h = 180;
img.header.stride = 0; img.header.stride = 0;

View File

@@ -118,6 +118,7 @@ void test_image_built_in_decode_recolor(void)
img_create("binXRGB8888", "A:src/test_files/binimages/cogwheel.XRGB8888.bin", false, true); img_create("binXRGB8888", "A:src/test_files/binimages/cogwheel.XRGB8888.bin", false, true);
img_create("binARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.bin", false, true); img_create("binARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.bin", false, true);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_recolor.png"); TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_recolor.png");
} }

View File

@@ -0,0 +1,63 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#include "lv_test_helpers.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void create_images(void)
{
lv_obj_clean(lv_scr_act());
lv_obj_t * img;
lv_obj_t * label;
LV_IMG_DECLARE(test_img_lvgl_logo_jpg);
img = lv_img_create(lv_scr_act());
lv_img_set_src(img, &test_img_lvgl_logo_jpg);
lv_obj_align(img, LV_ALIGN_CENTER, -100, -20);
label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Array");
lv_obj_align(label, LV_ALIGN_CENTER, -100, 20);
img = lv_img_create(lv_scr_act());
lv_img_set_src(img, "A:src/test_assets/test_img_lvgl_logo.jpg");
lv_obj_align(img, LV_ALIGN_CENTER, 100, -20);
label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "File");
lv_obj_align(label, LV_ALIGN_CENTER, 100, 20);
}
void test_jpg_1(void)
{
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_1.png");
uint32_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_scr_act());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/jpg_1.png");
TEST_ASSERT_EQUAL(mem_before, lv_test_get_free_mem());
}
#endif

View File

@@ -0,0 +1,63 @@
#if LV_BUILD_TEST
#include "../lvgl.h"
#include "unity/unity.h"
#include "lv_test_helpers.h"
void setUp(void)
{
/* Function run before every test */
}
void tearDown(void)
{
/* Function run after every test */
}
static void create_images(void)
{
lv_obj_clean(lv_scr_act());
lv_obj_t * img;
lv_obj_t * label;
LV_IMG_DECLARE(test_img_lvgl_logo_png);
img = lv_img_create(lv_scr_act());
lv_img_set_src(img, &test_img_lvgl_logo_png);
lv_obj_align(img, LV_ALIGN_CENTER, -100, -20);
label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Array");
lv_obj_align(label, LV_ALIGN_CENTER, -100, 20);
img = lv_img_create(lv_scr_act());
lv_img_set_src(img, "A:src/test_assets/test_img_lvgl_logo.png");
lv_obj_align(img, LV_ALIGN_CENTER, 100, -20);
label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "File");
lv_obj_align(label, LV_ALIGN_CENTER, 100, 20);
}
void test_png_1(void)
{
create_images();
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
uint32_t mem_before = lv_test_get_free_mem();
for(uint32_t i = 0; i < 20; i++) {
create_images();
lv_obj_invalidate(lv_scr_act());
lv_refr_now(NULL);
}
TEST_ASSERT_EQUAL_SCREENSHOT("libs/png_1.png");
TEST_ASSERT_EQUAL(mem_before, lv_test_get_free_mem());
}
#endif