snapshot
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
//
|
||||
// PNG Display helper class
|
||||
//
|
||||
// written by Larry Bank
|
||||
// bitbank@pobox.com
|
||||
//
|
||||
// Copyright 2025 BitBank Software, Inc. All Rights Reserved.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===========================================================================
|
||||
//
|
||||
#ifndef __PNGDISPLAY__
|
||||
#define __PNGDISPLAY__
|
||||
#include <PNGdec.h>
|
||||
#include <SD.h>
|
||||
#ifndef ARDUINO_ARCH_NRF52
|
||||
#include "FS.h"
|
||||
#include <LittleFS.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__BB_EPAPER__) && !defined(SPI_LCD_H) && !defined(__FASTEPD_H__)
|
||||
#error "One of the following display libraries must be included BEFORE PNGDisplay: bb_spi_lcd, bb_epaper, FastEPD"
|
||||
#endif
|
||||
|
||||
// To center one or both coordinates for the drawing position
|
||||
// use this constant value
|
||||
#define PNGDISPLAY_CENTER -2
|
||||
|
||||
class PNGDisplay
|
||||
{
|
||||
public:
|
||||
#ifdef SPI_LCD_H
|
||||
int loadPNG(BB_SPI_LCD *pLCD, int x, int y, const void *pData, int iDataSize, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG(BB_SPI_LCD *pLCD, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG_LFS(BB_SPI_LCD *pLCD, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
#endif // SPI_LCD_H
|
||||
|
||||
#ifdef __FASTEPD_H__
|
||||
int loadPNG(FASTEPD *pDisplay, int x, int y, const void *pData, int iDataSize, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG(FASTEPD *pDisplay, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG_LFS(FASTEPD *pDisplay, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
#endif // __FASTEPD_H__
|
||||
|
||||
#ifdef __BB_EPAPER__
|
||||
int loadPNG(BBEPAPER *pDisplay, int x, int y, const void *pData, int iDataSize, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG(BBEPAPER *pDisplay, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
int loadPNG_LFS(BBEPAPER *pDisplay, int x, int y, const char *fname, uint32_t bgColor = 0xffffffff);
|
||||
#endif // __BB_EPAPER__
|
||||
|
||||
int getPNGInfo(int *width, int *height, int *bpp, const void *pData, int iDataSize);
|
||||
int getPNGInfo(int *width, int *height, int *bpp, const char *fname);
|
||||
int getPNGInfo_LFS(int *width, int *height, int *bpp, const char *fname);
|
||||
int getLastError() {return _iLastError;}
|
||||
private:
|
||||
int _iLastError;
|
||||
};
|
||||
|
||||
#endif // __PNGDISPLAY__
|
||||
@@ -1,465 +0,0 @@
|
||||
//
|
||||
// PNG Display helper class
|
||||
//
|
||||
// written by Larry Bank
|
||||
// bitbank@pobox.com
|
||||
//
|
||||
// Copyright 2025 BitBank Software, Inc. All Rights Reserved.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===========================================================================
|
||||
//
|
||||
#ifndef __PNGDISPLAY_IMPL__
|
||||
#define __PNGDISPLAY_IMPL__
|
||||
#include "PNGDisplay.h"
|
||||
|
||||
static int PNGDraw(PNGDRAW *pDraw)
|
||||
{
|
||||
int *pInfo = (int *)pDraw->pUser;
|
||||
uint16_t *p16;
|
||||
PNG *pPNG;
|
||||
#ifdef SPI_LCD_H
|
||||
BB_SPI_LCD *pLCD;
|
||||
|
||||
pLCD = (BB_SPI_LCD *)pInfo[0]; // pointer to LCD class pointer
|
||||
pPNG = (PNG *)pInfo[1]; // pointer to PNG class pointer
|
||||
p16 = (uint16_t *)&pInfo[3]; // start of temporary pixel space
|
||||
pPNG->getLineAsRGB565(pDraw, p16, PNG_RGB565_BIG_ENDIAN, (uint32_t)pInfo[2]);
|
||||
pLCD->pushPixels(p16, pDraw->iWidth);
|
||||
#endif // SPI_LCD_H
|
||||
|
||||
#ifdef __BB_EPAPER__
|
||||
BBEPAPER *pEPD;
|
||||
int w, iLen, iPitch; // bits per pixel mode of the EPD
|
||||
uint8_t uc_s, uc_d, srcMask, destMask, *s, *d;
|
||||
int32_t iWidth, i, x, y;
|
||||
|
||||
pEPD = (BBEPAPER *)pInfo[0]; // pointer to display class object
|
||||
pPNG = (PNG *)pInfo[1]; // pointer to PNG class pointer
|
||||
if (pPNG->getBpp() != 1) {
|
||||
return 0; // mismatch, don't try to convert the bit depth
|
||||
}
|
||||
d = (uint8_t *)pEPD->getBuffer();
|
||||
x = pInfo[3]; y = pInfo[4]; // display offset to draw the image
|
||||
if (pDraw->y + y > pEPD->height()) return 0; // off bottom edge
|
||||
w = pPNG->getWidth();
|
||||
if (w + x > pEPD->width()) w = pEPD->width() - x; // clip to right edge
|
||||
iPitch = (pEPD->width()+7)/8;
|
||||
d += (x/8) + ((pDraw->y + y) * iPitch);
|
||||
srcMask = 0x80;
|
||||
destMask = 0x80 >> (x & 7);
|
||||
s = pDraw->pPixels;
|
||||
i = 0;
|
||||
if ((x & 7) == 0) { // take advantage of src/dest bit alignment
|
||||
while (i < w-7) {
|
||||
*d++ = *s++;
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
uc_s = *s++;
|
||||
uc_d = d[0];
|
||||
for (; i<w; i++) { // do it pixel-by-pixel
|
||||
if (uc_s & srcMask) {
|
||||
uc_d |= destMask; // use the same pixel color polarity
|
||||
} else {
|
||||
uc_d &= ~destMask;
|
||||
}
|
||||
srcMask >>= 1;
|
||||
if (srcMask == 0) {
|
||||
srcMask = 0x80;
|
||||
uc_s = *s++;
|
||||
}
|
||||
destMask >>= 1;
|
||||
if (destMask == 0) {
|
||||
destMask = 0x80;
|
||||
*d++ = uc_d;
|
||||
uc_d = d[0];
|
||||
}
|
||||
} // for i
|
||||
if (destMask != 0x80) { // store the last partial byte
|
||||
d[0] = uc_d;
|
||||
}
|
||||
#endif // __BB_EPAPER__
|
||||
|
||||
#ifdef __FASTEPD_H__
|
||||
FASTEPD *pEPD;
|
||||
int i, iLen, iPitch, iBpp; // bits per pixel mode of the EPD
|
||||
uint8_t srcMask, destMask, uc_s, uc_d, *s, *d;
|
||||
int32_t iWidth, w, x, y;
|
||||
|
||||
pEPD = (FASTEPD *)pInfo[0]; // pointer to display class object
|
||||
pPNG = (PNG *)pInfo[1]; // pointer to PNG class pointer
|
||||
iBpp = (pEPD->getMode() == BB_MODE_1BPP) ? 1:4;
|
||||
if (pPNG->getBpp() != iBpp) return 0; // mismatch, don't try to convert the bit depth
|
||||
d = (uint8_t *)pEPD->currentBuffer();
|
||||
x = pInfo[3]; y = pInfo[4]; // display offset to draw the image
|
||||
if (pDraw->y + y > pEPD->height()) return 0; // off bottom edge
|
||||
w = pPNG->getWidth();
|
||||
if (w + x > pEPD->width()) w = pEPD->width() - x; // clip to right edge
|
||||
iPitch = (pEPD->width()*iBpp)/8;
|
||||
d += ((x * iBpp)/8) + ((pDraw->y + y) * iPitch);
|
||||
if (iBpp == 4) {
|
||||
memcpy(d, pDraw->pPixels, (w*iBpp)/8);
|
||||
} else { // 1 bpp
|
||||
srcMask = 0x80;
|
||||
destMask = 0x80 >> (x & 7);
|
||||
s = pDraw->pPixels;
|
||||
if ((x & 7) == 0) { // take advantage of src/dest bit alignment
|
||||
while (i <= w-7) {
|
||||
*d++ = *s++;
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
uc_s = *s++;
|
||||
uc_d = d[0];
|
||||
for (; i<w; i++) { // do it pixel-by-pixel
|
||||
if (uc_s & srcMask) {
|
||||
uc_d |= destMask; // use the same pixel color polarity
|
||||
} else {
|
||||
uc_d &= ~destMask;
|
||||
}
|
||||
srcMask >>= 1;
|
||||
if (srcMask == 0) {
|
||||
srcMask = 0x80;
|
||||
uc_s = *s++;
|
||||
}
|
||||
destMask >>= 1;
|
||||
if (destMask == 0) {
|
||||
destMask = 0x80;
|
||||
*d++ = uc_d;
|
||||
uc_d = d[0];
|
||||
}
|
||||
} // for i
|
||||
if (destMask != 0) { // store the last partial byte
|
||||
d[0] = uc_d;
|
||||
}
|
||||
} // 1-bpp
|
||||
#endif // __FASTEPD_H__
|
||||
|
||||
return 1; // continue decoding
|
||||
} /* PNGDraw() */
|
||||
|
||||
// Functions to access a file on the SD card
|
||||
|
||||
static void * pngOpen(const char *filename, int32_t *size) {
|
||||
static File myfile;
|
||||
myfile = SD.open(filename);
|
||||
*size = myfile.size();
|
||||
return &myfile;
|
||||
}
|
||||
#ifndef ARDUINO_ARCH_NRF52
|
||||
static void * pngOpenLFS(const char *filename, int32_t *size) {
|
||||
static File myfile;
|
||||
myfile = LittleFS.open(filename, FILE_READ);
|
||||
if (myfile) {
|
||||
*size = myfile.size();
|
||||
return &myfile;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif // !nRF52
|
||||
|
||||
static void pngClose(void *handle) {
|
||||
File *pFile = (File *)handle;
|
||||
if (pFile) pFile->close();
|
||||
}
|
||||
static int32_t pngRead(PNGFILE *handle, uint8_t *buffer, int32_t length) {
|
||||
File *pFile = (File *)handle->fHandle;
|
||||
if (!pFile) return 0;
|
||||
return pFile->read(buffer, length);
|
||||
}
|
||||
static int32_t pngSeek(PNGFILE *handle, int32_t position) {
|
||||
File *pFile = (File *)handle->fHandle;
|
||||
if (!pFile) return 0;
|
||||
return pFile->seek(position);
|
||||
}
|
||||
|
||||
#ifdef SPI_LCD_H
|
||||
int PNGDisplay::loadPNG(BB_SPI_LCD *pDisplay, int x, int y, const void *pData, int iDataSize, uint32_t bgColor)
|
||||
#endif // SPI_LCD_H
|
||||
|
||||
#ifdef __FASTEPD_H__
|
||||
int PNGDisplay::loadPNG(FASTEPD *pDisplay, int x, int y, const void *pData, int iDataSize, uint32_t bgColor)
|
||||
#endif // __FASTEPD_H__
|
||||
|
||||
#ifdef __BB_EPAPER__
|
||||
int PNGDisplay::loadPNG(BBEPAPER *pDisplay, int x, int y, const void *pData, int iDataSize, uint32_t bgColor)
|
||||
#endif // __BB_EPAPER__
|
||||
|
||||
{
|
||||
PNG *png;
|
||||
int w, h, rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->openRAM((uint8_t *)pData, iDataSize, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
w = png->getWidth();
|
||||
h = png->getHeight();
|
||||
if (x == PNGDISPLAY_CENTER) {
|
||||
x = (pDisplay->width() - w)/2;
|
||||
if (x < 0) x = 0;
|
||||
} else if (x < 0 || w + x > pDisplay->width()) {
|
||||
// clipping is not supported
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
free(png);
|
||||
return 0;
|
||||
}
|
||||
if (y == PNGDISPLAY_CENTER) {
|
||||
y = (pDisplay->height() - h)/2;
|
||||
if (y < 0) y = 0;
|
||||
} else if (y < 0 || y + h > pDisplay->height()) {
|
||||
// clipping is not supported
|
||||
free(png);
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
png_info = (uint32_t *)malloc((w * sizeof(uint16_t)) + 3 * sizeof(int)); // enough for pixels and 3 32-bit values
|
||||
png_info[0] = (uint32_t)pDisplay;
|
||||
png_info[1] = (uint32_t)png;
|
||||
png_info[2] = bgColor;
|
||||
png_info[3] = x;
|
||||
png_info[4] = y;
|
||||
#ifdef SPI_LCD_H
|
||||
pDisplay->setAddrWindow(x, y, w, h);
|
||||
#endif
|
||||
png->decode((void *)png_info, 0); // simple decode, no options
|
||||
png->close();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* loadPNG() */
|
||||
|
||||
#ifdef SPI_LCD_H
|
||||
int PNGDisplay::loadPNG(BB_SPI_LCD *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
#ifdef __FASTEPD_H__
|
||||
int PNGDisplay::loadPNG(FASTEPD *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
#ifdef __BB_EPAPER__
|
||||
int PNGDisplay::loadPNG(BBEPAPER *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
{
|
||||
PNG *png;
|
||||
int w, h, rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->open(fname, pngOpen, pngClose, pngRead, pngSeek, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
w = png->getWidth();
|
||||
h = png->getHeight();
|
||||
if (x == PNGDISPLAY_CENTER) {
|
||||
x = (pDisplay->width() - w)/2;
|
||||
if (x < 0) x = 0;
|
||||
} else if (x < 0 || w + x > pDisplay->width()) {
|
||||
// clipping is not supported
|
||||
free(png);
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
if (y == PNGDISPLAY_CENTER) {
|
||||
y = (pDisplay->height() - h)/2;
|
||||
if (y < 0) y = 0;
|
||||
} else if (y < 0 || y + h > pDisplay->height()) {
|
||||
free(png);
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
png_info = (uint32_t *)malloc((w * sizeof(uint16_t)) + 3 * sizeof(int)); // enough for pixels and 3 32-bit values
|
||||
png_info[0] = (uint32_t)pDisplay;
|
||||
png_info[1] = (uint32_t)png;
|
||||
png_info[2] = bgColor;
|
||||
png_info[3] = x;
|
||||
png_info[4] = y;
|
||||
#ifdef SPI_LCD_H
|
||||
pDisplay->setAddrWindow(x, y, w, h);
|
||||
#endif
|
||||
png->decode((void *)png_info, 0); // simple decode, no options
|
||||
png->close();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* loadPNG() */
|
||||
|
||||
#ifndef ARDUINO_ARCH_NRF52
|
||||
#ifdef SPI_LCD_H
|
||||
int PNGDisplay::loadPNG_LFS(BB_SPI_LCD *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
#ifdef __FASTEPD_H__
|
||||
int PNGDisplay::loadPNG_LFS(FASTEPD *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
#ifdef __BB_EPAPER__
|
||||
int PNGDisplay::loadPNG_LFS(BBEPAPER *pDisplay, int x, int y, const char *fname, uint32_t bgColor)
|
||||
#endif
|
||||
|
||||
{
|
||||
PNG *png;
|
||||
int w, h, rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
if (!LittleFS.begin(false)) {
|
||||
return 0;
|
||||
}
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->open(fname, pngOpenLFS, pngClose, pngRead, pngSeek, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
w = png->getWidth();
|
||||
h = png->getHeight();
|
||||
if (x == PNGDISPLAY_CENTER) {
|
||||
x = (pDisplay->width() - w)/2;
|
||||
if (x < 0) x = 0;
|
||||
} else if (x < 0 || w + x > pDisplay->width()) {
|
||||
// clipping is not supported
|
||||
free(png);
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
if (y == PNGDISPLAY_CENTER) {
|
||||
y = (pDisplay->height() - h)/2;
|
||||
if (y < 0) y = 0;
|
||||
} else if (y < 0 || y + h > pDisplay->height()) {
|
||||
free(png);
|
||||
_iLastError = PNG_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
png_info = (uint32_t *)malloc((w * sizeof(uint16_t)) + 3 * sizeof(int)); // enough for pixels and 3 32-bit values
|
||||
png_info[0] = (uint32_t)pDisplay;
|
||||
png_info[1] = (uint32_t)png;
|
||||
png_info[2] = bgColor;
|
||||
png_info[3] = x;
|
||||
png_info[4] = y;
|
||||
#ifdef SPI_LCD_H
|
||||
pDisplay->setAddrWindow(x, y, w, h);
|
||||
#endif
|
||||
png->decode((void *)png_info, 0); // simple decode, no options
|
||||
png->close();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* loadPNG_LFS() */
|
||||
#endif // !nRF52
|
||||
|
||||
int PNGDisplay::getPNGInfo(int *width, int *height, int *bpp, const void *pData, int iDataSize)
|
||||
{
|
||||
PNG *png;
|
||||
int rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
if (!width || !height || !bpp || !pData || iDataSize < 32) return 0;
|
||||
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->openRAM((uint8_t *)pData, iDataSize, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
*width = png->getWidth();
|
||||
*height = png->getHeight();
|
||||
*bpp = png->getBpp();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* getPNGInfo() */
|
||||
|
||||
int PNGDisplay::getPNGInfo(int *width, int *height, int *bpp, const char *fname)
|
||||
{
|
||||
PNG *png;
|
||||
int rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
if (!width || !height || !bpp || !fname) return 0;
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->open(fname, pngOpen, pngClose, pngRead, pngSeek, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
*width = png->getWidth();
|
||||
*height = png->getHeight();
|
||||
*bpp = png->getBpp();
|
||||
png->close();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* getPNGInfo() */
|
||||
|
||||
#ifndef ARDUINO_ARCH_NRF52
|
||||
int PNGDisplay::getPNGInfo_LFS(int *width, int *height, int *bpp, const char *fname)
|
||||
{
|
||||
PNG *png;
|
||||
int rc;
|
||||
uint32_t *png_info;
|
||||
|
||||
if (!LittleFS.begin(false)) {
|
||||
return 0;
|
||||
}
|
||||
if (!width || !height || !bpp || !fname) return 0;
|
||||
png = (PNG *)malloc(sizeof(PNG));
|
||||
if (!png) {
|
||||
_iLastError = PNG_MEM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
rc = png->open(fname, pngOpenLFS, pngClose, pngRead, pngSeek, PNGDraw);
|
||||
if (rc == PNG_SUCCESS) {
|
||||
*width = png->getWidth();
|
||||
*height = png->getHeight();
|
||||
*bpp = png->getBpp();
|
||||
png->close();
|
||||
free(png);
|
||||
_iLastError = PNG_SUCCESS;
|
||||
return 1;
|
||||
}
|
||||
_iLastError = png->getLastError();
|
||||
free(png);
|
||||
return 0;
|
||||
} /* getPNGInfo_LFS() */
|
||||
#endif // !nRF52
|
||||
#endif // __PNGDISPLAY_IMPL__
|
||||
@@ -49,13 +49,8 @@
|
||||
/* Defines and variables */
|
||||
#define PNG_FILE_BUF_SIZE 2048
|
||||
// Number of bytes to reserve for current and previous lines
|
||||
// Defaults to 320 32-bit pixels max width
|
||||
// but can be overidden with a macro defined at compile time
|
||||
#ifndef PNG_MAX_BUFFERED_PIXELS
|
||||
#define PNG_MAX_BUFFERED_PIXELS ((320*4 + 1)*2)
|
||||
#endif
|
||||
|
||||
#ifndef __PNGENC__
|
||||
// Defaults to 640 32-bit pixels max width
|
||||
#define PNG_MAX_BUFFERED_PIXELS (640*4 + 1)
|
||||
// PNG filter type
|
||||
enum {
|
||||
PNG_FILTER_NONE=0,
|
||||
@@ -80,6 +75,16 @@ enum {
|
||||
PNG_PIXEL_GRAY_ALPHA=4,
|
||||
PNG_PIXEL_TRUECOLOR_ALPHA=6
|
||||
};
|
||||
// RGB565 endianness
|
||||
enum {
|
||||
PNG_RGB565_LITTLE_ENDIAN = 0,
|
||||
PNG_RGB565_BIG_ENDIAN
|
||||
};
|
||||
|
||||
enum {
|
||||
PNG_MEM_RAM=0,
|
||||
PNG_MEM_FLASH
|
||||
};
|
||||
|
||||
// Error codes returned by getLastError()
|
||||
enum {
|
||||
@@ -90,29 +95,7 @@ enum {
|
||||
PNG_NO_BUFFER,
|
||||
PNG_UNSUPPORTED_FEATURE,
|
||||
PNG_INVALID_FILE,
|
||||
PNG_TOO_BIG,
|
||||
PNG_QUIT_EARLY
|
||||
};
|
||||
|
||||
typedef struct png_file_tag
|
||||
{
|
||||
int32_t iPos; // current file position
|
||||
int32_t iSize; // file size
|
||||
uint8_t *pData; // memory file pointer
|
||||
void * fHandle; // class pointer to File/SdFat or whatever you want
|
||||
} PNGFILE;
|
||||
|
||||
#endif // !__PNGENC__
|
||||
|
||||
// RGB565 endianness
|
||||
enum {
|
||||
PNG_RGB565_LITTLE_ENDIAN = 0,
|
||||
PNG_RGB565_BIG_ENDIAN
|
||||
};
|
||||
|
||||
enum {
|
||||
PNG_MEM_RAM=0,
|
||||
PNG_MEM_FLASH
|
||||
PNG_TOO_BIG
|
||||
};
|
||||
|
||||
typedef struct png_draw_tag
|
||||
@@ -129,11 +112,19 @@ typedef struct png_draw_tag
|
||||
uint8_t *pPixels;
|
||||
} PNGDRAW;
|
||||
|
||||
typedef struct png_file_tag
|
||||
{
|
||||
int32_t iPos; // current file position
|
||||
int32_t iSize; // file size
|
||||
uint8_t *pData; // memory file pointer
|
||||
void * fHandle; // class pointer to File/SdFat or whatever you want
|
||||
} PNGFILE;
|
||||
|
||||
// Callback function prototypes
|
||||
typedef int32_t (PNG_READ_CALLBACK)(PNGFILE *pFile, uint8_t *pBuf, int32_t iLen);
|
||||
typedef int32_t (PNG_SEEK_CALLBACK)(PNGFILE *pFile, int32_t iPosition);
|
||||
typedef void * (PNG_OPEN_CALLBACK)(const char *szFilename, int32_t *pFileSize);
|
||||
typedef int (PNG_DRAW_CALLBACK)(PNGDRAW *);
|
||||
typedef void (PNG_DRAW_CALLBACK)(PNGDRAW *);
|
||||
typedef void (PNG_CLOSE_CALLBACK)(void *pHandle);
|
||||
|
||||
//
|
||||
@@ -156,9 +147,9 @@ typedef struct png_image_tag
|
||||
PNG_DRAW_CALLBACK *pfnDraw;
|
||||
PNG_CLOSE_CALLBACK *pfnClose;
|
||||
PNGFILE PNGFile;
|
||||
uint8_t ucZLIB[32768 + sizeof(struct inflate_state)]; // put this here to avoid needing malloc/free
|
||||
uint8_t ucZLIB[32768 + sizeof(inflate_state)]; // put this here to avoid needing malloc/free
|
||||
uint8_t ucPalette[1024];
|
||||
uint8_t ucPixels[PNG_MAX_BUFFERED_PIXELS];
|
||||
uint8_t ucPixels[PNG_MAX_BUFFERED_PIXELS * 2];
|
||||
uint8_t ucFileBuf[PNG_FILE_BUF_SIZE]; // holds temp file data
|
||||
} PNGIMAGE;
|
||||
|
||||
@@ -195,8 +186,8 @@ class PNG
|
||||
};
|
||||
#else
|
||||
#define PNG_STATIC
|
||||
int PNG_openRAM(PNGIMAGE *pPNG, uint8_t *pData, int iDataSize, PNG_DRAW_CALLBACK *pfnDraw);
|
||||
int PNG_openFile(PNGIMAGE *pPNG, const char *szFilename, PNG_DRAW_CALLBACK *pfnDraw);
|
||||
int PNG_openRAM(PNGIMAGE *pPNG, uint8_t *pData, int iDataSize);
|
||||
int PNG_openFile(PNGIMAGE *pPNG, const char *szFilename);
|
||||
int PNG_getWidth(PNGIMAGE *pPNG);
|
||||
int PNG_getHeight(PNGIMAGE *pPNG);
|
||||
int PNG_decode(PNGIMAGE *pPNG, void *pUser, int iOptions);
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#ifndef __ADLER32_C__
|
||||
#define __ADLER32_C__
|
||||
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521U /* largest prime smaller than 65536 */
|
||||
@@ -63,7 +60,10 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len)
|
||||
uLong ZEXPORT adler32_z(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
@@ -131,13 +131,19 @@ uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len)
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
return adler32_z(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2)
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
@@ -163,14 +169,18 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2)
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2)
|
||||
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
#endif // __ADLER32_C__
|
||||
|
||||
@@ -185,7 +185,7 @@ local void write_table(out, table)
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table(void)
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
@@ -199,7 +199,10 @@ const z_crc_t FAR * ZEXPORT get_crc_table(void)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, z_size_t len)
|
||||
unsigned long ZEXPORT crc32_z(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
@@ -231,7 +234,10 @@ unsigned long ZEXPORT crc32_z(unsigned long crc, const unsigned char FAR *buf, z
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
{
|
||||
return crc32_z(crc, buf, len);
|
||||
}
|
||||
@@ -257,7 +263,10 @@ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uIn
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, z_size_t len)
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
@@ -294,7 +303,10 @@ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, z_size_t len)
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
@@ -329,7 +341,9 @@ local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, z
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec)
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
@@ -344,7 +358,9 @@ local unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec)
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
@@ -353,7 +369,10 @@ local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2)
|
||||
local uLong crc32_combine_(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
@@ -406,12 +425,18 @@ local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2)
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2)
|
||||
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables (struct inflate_state FAR *state);
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
@@ -25,7 +25,12 @@ local void fixedtables (struct inflate_state FAR *state);
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
@@ -74,7 +79,8 @@ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(struct inflate_state FAR *state)
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
@@ -241,7 +247,12 @@ local void fixedtables(struct inflate_state FAR *state)
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
@@ -617,7 +628,8 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(z_streamp strm)
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
@@ -8,13 +8,24 @@
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#if (INTPTR_MAX == INT64_MAX) || defined(HAL_ESP32_HAL_H_) || defined(TEENSYDUINO) || defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7)
|
||||
#define ALLOWS_UNALIGNED
|
||||
#endif
|
||||
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
#define REGISTER_WIDTH 64
|
||||
typedef uint64_t BIGUINT;
|
||||
typedef uint32_t SMALLUINT;
|
||||
#else
|
||||
#define REGISTER_WIDTH 32
|
||||
typedef uint32_t BIGUINT;
|
||||
typedef uint16_t SMALLUINT;
|
||||
#endif // native register size
|
||||
|
||||
#ifdef ASMINF
|
||||
# pragma message("Assembler code may have bugs -- use at your own risk")
|
||||
#else
|
||||
|
||||
#if ((INTPTR_MAX == INT64_MAX) || defined(HAL_ESP32_HAL_H_) || defined(TEENSYDUINO) || defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7)) && !defined(ARDUINO_ARCH_RP2040)
|
||||
#define ALLOWS_UNALIGNED
|
||||
#endif
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
literal and match bytes until either not enough input or output is
|
||||
@@ -50,7 +61,10 @@
|
||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||
output space.
|
||||
*/
|
||||
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
void ZLIB_INTERNAL inflate_fast(strm, start)
|
||||
z_streamp strm;
|
||||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *in; /* local strm->next_in */
|
||||
z_const unsigned char FAR *last; /* have enough input while in < last */
|
||||
@@ -64,13 +78,14 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||
unsigned long hold; /* local strm->hold */
|
||||
BIGUINT hold, tmpbits; /* local strm->hold */
|
||||
// unsigned long hold; /* local strm->hold */
|
||||
unsigned bits; /* local strm->bits */
|
||||
code const FAR *lcode; /* local strm->lencode */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code const *here; /* retrieved table entry */
|
||||
code here; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
@@ -101,60 +116,84 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
/* decode literals and length/distances until end-of-block or not enough
|
||||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
if (bits < (REGISTER_WIDTH/2)) { // helps on 32 and 64-bit CPUs
|
||||
#ifdef ALLOWS_UNALIGNED
|
||||
tmpbits = *(SMALLUINT *)in;
|
||||
hold |= (BIGUINT)(tmpbits << bits);
|
||||
in += sizeof(SMALLUINT);
|
||||
bits += (REGISTER_WIDTH / 2);
|
||||
#else
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
#endif
|
||||
}
|
||||
here = lcode + (hold & lmask);
|
||||
here = lcode[hold & lmask];
|
||||
dolen:
|
||||
op = (unsigned)(here->bits);
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here->op);
|
||||
op = (unsigned)(here.op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here->val));
|
||||
*out++ = (unsigned char)(here->val);
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
*out++ = (unsigned char)(here.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here->val);
|
||||
len = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
#if REGISTER_WIDTH == 32
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
hold += (uint32_t)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
#endif
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
if (bits < (REGISTER_WIDTH/2)) { // helps on 32 and 64-bit CPUs
|
||||
#ifdef UNALIGNED_OK
|
||||
tmpbits = *(SMALLUINT *)in;
|
||||
hold |= (BIGUINT)(tmpbits << bits);
|
||||
in += sizeof(SMALLUINT);
|
||||
bits += (REGISTER_WIDTH / 2);
|
||||
#else
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
#endif
|
||||
}
|
||||
here = dcode + (hold & dmask);
|
||||
here = dcode[hold & dmask];
|
||||
dodist:
|
||||
op = (unsigned)(here->bits);
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here->op);
|
||||
op = (unsigned)(here.op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(here->val);
|
||||
dist = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
#if REGISTER_WIDTH == 32
|
||||
if (bits < op) {
|
||||
#ifdef ALLOWS_UNALIGNED
|
||||
hold |= (*(uint16_t *)in << bits);
|
||||
bits += 16;
|
||||
in += 2;
|
||||
#else
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
if (bits < op) { // this is NEVER true
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
#endif // ALLOWS_UNALIGNED
|
||||
}
|
||||
#endif // 32-bit CPU
|
||||
dist += (unsigned)hold & ((1U << op) - 1);
|
||||
#ifdef INFLATE_STRICT
|
||||
if (dist > dmax) {
|
||||
@@ -267,7 +306,7 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
{
|
||||
uint8_t *pEnd = out+len;
|
||||
int overlap = (int)(intptr_t)(out-from);
|
||||
if (overlap > 4) { // overlap of source/dest won't impede normal copy
|
||||
if (overlap >= 4) { // overlap of source/dest won't impede normal copy
|
||||
while (out < pEnd) {
|
||||
*(uint32_t *)out = *(uint32_t *)from;
|
||||
out += 4;
|
||||
@@ -275,15 +314,10 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
}
|
||||
// correct for possible overshoot of destination ptr
|
||||
out = pEnd;
|
||||
} else if (overlap == 1 || overlap == 4) { // copy 1/4-byte patterns
|
||||
uint32_t pattern;
|
||||
if (overlap == 1) {
|
||||
pattern = *from;
|
||||
pattern = pattern | (pattern << 8);
|
||||
pattern = pattern | (pattern << 16);
|
||||
} else {
|
||||
pattern = *(uint32_t *)from;
|
||||
}
|
||||
} else if (overlap == 1) { // copy 1-byte pattern
|
||||
uint32_t pattern = *from;
|
||||
pattern = pattern | (pattern << 8);
|
||||
pattern = pattern | (pattern << 16);
|
||||
while (out < pEnd) {
|
||||
*(uint32_t *)out = pattern;
|
||||
out += 4;
|
||||
@@ -311,7 +345,7 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
here = dcode + here->val + (hold & ((1U << op) - 1));
|
||||
here = dcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
@@ -321,7 +355,7 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
here = lcode + here->val + (hold & ((1U << op) - 1));
|
||||
here = lcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
@@ -337,10 +371,10 @@ void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
|
||||
} while (in < last && out < end);
|
||||
|
||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||
len = bits >> 3;
|
||||
in -= len;
|
||||
bits -= len << 3;
|
||||
hold &= (1U << bits) - 1;
|
||||
// len = bits >> 3;
|
||||
// in -= len;
|
||||
// bits -= len << 3;
|
||||
// hold &= (1 << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,47 +13,43 @@
|
||||
the crc code when it is not needed. For shared libraries, gzip decoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
#define GUNZIP
|
||||
# define GUNZIP
|
||||
#endif
|
||||
|
||||
#ifndef __INFLATE_H__
|
||||
#define __INFLATE_H__
|
||||
|
||||
/* Possible inflate modes between inflate() calls */
|
||||
typedef enum
|
||||
{
|
||||
PNG_HEADER = 16180, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
EXLEN, /* i: waiting for extra length (gzip) */
|
||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||
NAME, /* i: waiting for end of file name (gzip) */
|
||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||
HCRC, /* i: waiting for header crc (gzip) */
|
||||
DICTID, /* i: waiting for dictionary check value */
|
||||
DICT, /* waiting for inflateSetDictionary() call */
|
||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||
STORED, /* i: waiting for stored size (length and complement) */
|
||||
COPY_, /* i/o: same as COPY below, but only first time in */
|
||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||
TABLE, /* i: waiting for dynamic block table lengths */
|
||||
LENLENS, /* i: waiting for code length code lengths */
|
||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||
LEN_, /* i: same as LEN below, but only first time in */
|
||||
LEN, /* i: waiting for length/lit/eob code */
|
||||
LENEXT, /* i: waiting for length extra bits */
|
||||
DIST, /* i: waiting for distance code */
|
||||
DISTEXT, /* i: waiting for distance extra bits */
|
||||
MATCH, /* o: waiting for output space to copy string */
|
||||
LIT, /* o: waiting for output space to write literal */
|
||||
CHECK, /* i: waiting for 32-bit check value */
|
||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||
DONE, /* finished check, done -- remain here until reset */
|
||||
BAD, /* got a data error -- remain here until reset */
|
||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||
typedef enum {
|
||||
HEAD = 16180, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
EXLEN, /* i: waiting for extra length (gzip) */
|
||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||
NAME, /* i: waiting for end of file name (gzip) */
|
||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||
HCRC, /* i: waiting for header crc (gzip) */
|
||||
DICTID, /* i: waiting for dictionary check value */
|
||||
DICT, /* waiting for inflateSetDictionary() call */
|
||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||
STORED, /* i: waiting for stored size (length and complement) */
|
||||
COPY_, /* i/o: same as COPY below, but only first time in */
|
||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||
TABLE, /* i: waiting for dynamic block table lengths */
|
||||
LENLENS, /* i: waiting for code length code lengths */
|
||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||
LEN_, /* i: same as LEN below, but only first time in */
|
||||
LEN, /* i: waiting for length/lit/eob code */
|
||||
LENEXT, /* i: waiting for length extra bits */
|
||||
DIST, /* i: waiting for distance code */
|
||||
DISTEXT, /* i: waiting for distance extra bits */
|
||||
MATCH, /* o: waiting for output space to copy string */
|
||||
LIT, /* o: waiting for output space to write literal */
|
||||
CHECK, /* i: waiting for 32-bit check value */
|
||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||
DONE, /* finished check, done -- remain here until reset */
|
||||
BAD, /* got a data error -- remain here until reset */
|
||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||
} inflate_mode;
|
||||
|
||||
/*
|
||||
@@ -62,7 +58,7 @@ typedef enum
|
||||
(most modes can go to BAD or MEM on error -- not shown for clarity)
|
||||
|
||||
Process header:
|
||||
PNG_HEADER -> (gzip) or (zlib) or (raw)
|
||||
HEAD -> (gzip) or (zlib) or (raw)
|
||||
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
|
||||
HCRC -> TYPE
|
||||
(zlib) -> DICTID or TYPE
|
||||
@@ -83,50 +79,48 @@ typedef enum
|
||||
|
||||
/* State maintained between inflate() calls -- approximately 7K bytes, not
|
||||
including the allocated sliding window, which is up to 32K bytes. */
|
||||
struct inflate_state
|
||||
{
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
gz_headerp head; /* where to save gzip header information */
|
||||
/* sliding window */
|
||||
unsigned wbits; /* log base 2 of requested window size */
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if needed */
|
||||
/* bit accumulator */
|
||||
uint64_t hold; /* input bit accumulator */
|
||||
// unsigned long hold; /* input bit accumulator */
|
||||
unsigned bits; /* number of bits in "in" */
|
||||
/* for string and stored block copying */
|
||||
unsigned length; /* literal or length of data to copy */
|
||||
unsigned offset; /* distance back to copy string from */
|
||||
/* for table and code decoding */
|
||||
unsigned extra; /* extra bits needed */
|
||||
/* fixed and dynamic code tables */
|
||||
code const FAR *lencode; /* starting table for length/literal codes */
|
||||
code const FAR *distcode; /* starting table for distance codes */
|
||||
unsigned lenbits; /* index bits for lencode */
|
||||
unsigned distbits; /* index bits for distcode */
|
||||
/* dynamic table building */
|
||||
unsigned ncode; /* number of code length code lengths */
|
||||
unsigned nlen; /* number of length code lengths */
|
||||
unsigned ndist; /* number of distance code lengths */
|
||||
unsigned have; /* number of code lengths in lens[] */
|
||||
code FAR *next; /* next available space in codes[] */
|
||||
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||
unsigned short work[288]; /* work area for code table building */
|
||||
code codes[ENOUGH]; /* space for code tables */
|
||||
int sane; /* if false, allow invalid distance too far */
|
||||
int back; /* bits back of last unprocessed length/lit */
|
||||
unsigned was; /* initial length of match */
|
||||
struct inflate_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
gz_headerp head; /* where to save gzip header information */
|
||||
/* sliding window */
|
||||
unsigned wbits; /* log base 2 of requested window size */
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if needed */
|
||||
/* bit accumulator */
|
||||
uint64_t hold; /* input bit accumulator */
|
||||
// unsigned long hold; /* input bit accumulator */
|
||||
unsigned bits; /* number of bits in "in" */
|
||||
/* for string and stored block copying */
|
||||
unsigned length; /* literal or length of data to copy */
|
||||
unsigned offset; /* distance back to copy string from */
|
||||
/* for table and code decoding */
|
||||
unsigned extra; /* extra bits needed */
|
||||
/* fixed and dynamic code tables */
|
||||
code const FAR *lencode; /* starting table for length/literal codes */
|
||||
code const FAR *distcode; /* starting table for distance codes */
|
||||
unsigned lenbits; /* index bits for lencode */
|
||||
unsigned distbits; /* index bits for distcode */
|
||||
/* dynamic table building */
|
||||
unsigned ncode; /* number of code length code lengths */
|
||||
unsigned nlen; /* number of length code lengths */
|
||||
unsigned ndist; /* number of distance code lengths */
|
||||
unsigned have; /* number of code lengths in lens[] */
|
||||
code FAR *next; /* next available space in codes[] */
|
||||
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||
unsigned short work[288]; /* work area for code table building */
|
||||
code codes[ENOUGH]; /* space for code tables */
|
||||
int sane; /* if false, allow invalid distance too far */
|
||||
int back; /* bits back of last unprocessed length/lit */
|
||||
unsigned was; /* initial length of match */
|
||||
};
|
||||
#endif // __INFLATE_H__
|
||||
|
||||
@@ -29,7 +29,13 @@ const char inflate_copyright[] =
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)
|
||||
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
#ifndef __INFTREES_H__
|
||||
#define __INFTREES_H__
|
||||
|
||||
/* Structure for decoding tables. Each entry provides either the
|
||||
information needed to do the operation requested by the code that
|
||||
@@ -62,4 +60,3 @@ typedef enum {
|
||||
int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
|
||||
unsigned codes, code FAR * FAR *table,
|
||||
unsigned FAR *bits, unsigned short FAR *work));
|
||||
#endif // __INFTREES_H__
|
||||
|
||||
@@ -60,41 +60,21 @@ static const uint16_t usGrayTo565[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x0020
|
||||
// C interface
|
||||
//
|
||||
#ifndef __cplusplus
|
||||
// Forward references
|
||||
PNG_STATIC int32_t readFLASH(PNGFILE *pFile, uint8_t *pBuf, int32_t iLen);
|
||||
PNG_STATIC int32_t seekMem(PNGFILE *pFile, int32_t iPosition);
|
||||
PNG_STATIC int PNGInit(PNGIMAGE *pPNG);
|
||||
|
||||
// C API
|
||||
int PNG_openRAM(PNGIMAGE *pPNG, uint8_t *pData, int iDataSize, PNG_DRAW_CALLBACK *pfnDraw)
|
||||
{
|
||||
pPNG->iError = PNG_SUCCESS;
|
||||
pPNG->pfnRead = readFLASH;
|
||||
pPNG->pfnRead = readMem;
|
||||
pPNG->pfnSeek = seekMem;
|
||||
pPNG->pfnDraw = pfnDraw;
|
||||
pPNG->pfnOpen = NULL;
|
||||
pPNG->pfnClose = NULL;
|
||||
pPNG->PNGFile.iSize = iDataSize;
|
||||
pPNG->PNGFile.pData = pData;
|
||||
pPNG->PNGFile.iPos = 0;
|
||||
return PNGInit(pPNG);
|
||||
} /* PNG_openRAM() */
|
||||
|
||||
#ifdef __LINUX__
|
||||
int32_t readFile(PNGFILE *handle, uint8_t *buffer, int32_t length) {
|
||||
if (!handle->fHandle) return 0;
|
||||
return (int32_t)fread(buffer, 1, length, (FILE *)handle->fHandle);
|
||||
}
|
||||
int32_t seekFile(PNGFILE *handle, int32_t position) {
|
||||
if (!handle->fHandle) return 0;
|
||||
return fseek((FILE *)handle->fHandle, position, SEEK_SET);
|
||||
}
|
||||
void closeFile(void *handle) {
|
||||
if (handle) {
|
||||
FILE *f = (FILE *)handle;
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
int PNG_openFile(PNGIMAGE *pPNG, const char *szFilename, PNG_DRAW_CALLBACK *pfnDraw)
|
||||
{
|
||||
pPNG->iError = PNG_SUCCESS;
|
||||
@@ -239,15 +219,6 @@ PNG_STATIC uint8_t PNGMakeMask(PNGDRAW *pDraw, uint8_t *pMask, uint8_t ucThresho
|
||||
} // switch on pixel type
|
||||
return cHasOpaque; // let the caller know if any pixels are opaque
|
||||
} /* PNGMakeMask() */
|
||||
#ifdef ARDUINO_ESP32S3_DEV
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
void s3_rgb565(uint8_t *pSrc, uint8_t *pDest, int iCount, bool bBigEndian);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
//
|
||||
// Convert a line of native PNG pixels into RGB565
|
||||
// handles all standard pixel types
|
||||
@@ -257,39 +228,18 @@ PNG_STATIC void PNGRGB565(PNGDRAW *pDraw, uint16_t *pPixels, int iEndiannes, uin
|
||||
{
|
||||
int x, j;
|
||||
uint16_t usPixel, *pDest = pPixels;
|
||||
uint8_t c=0, a, *pPal, *s = pDraw->pPixels;
|
||||
uint8_t c, a, *pPal, *s = pDraw->pPixels;
|
||||
|
||||
switch (pDraw->iPixelType) {
|
||||
case PNG_PIXEL_GRAY_ALPHA:
|
||||
if (u32Bkgd != 0xffffffff) {
|
||||
// gray level of background color choice
|
||||
uint8_t u8BG = (uint8_t)(((u32Bkgd & 0xff) + ((u32Bkgd >> 7) & 0x1fe) + ((u32Bkgd >> 16) & 0xff)) / 4);
|
||||
uint16_t usBG = usGrayTo565[u8BG];
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
c = *s++; // gray level
|
||||
a = *s++;
|
||||
if (a == 0) {
|
||||
usPixel = usBG;
|
||||
} else if (a == 255) { // fully opaque
|
||||
usPixel = usGrayTo565[c];
|
||||
} else { // mix the colors
|
||||
usPixel = (c * a) + (u8BG * (255-a));
|
||||
usPixel = usGrayTo565[(usPixel >> 8)];
|
||||
}
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
} // for x
|
||||
} else {
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
c = *s++; // gray level
|
||||
a = *s++;
|
||||
j = (a * c) >> 8; // multiply by the alpha
|
||||
usPixel = usGrayTo565[j];
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
}
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
c = *s++; // gray level
|
||||
a = *s++;
|
||||
j = (a * c) >> 8; // multiply by the alpha
|
||||
usPixel = usGrayTo565[j];
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
}
|
||||
break;
|
||||
case PNG_PIXEL_GRAYSCALE:
|
||||
@@ -387,49 +337,18 @@ PNG_STATIC void PNGRGB565(PNGDRAW *pDraw, uint16_t *pPixels, int iEndiannes, uin
|
||||
switch (pDraw->iBpp) {
|
||||
case 8: // 8-bit palette also supports palette alpha
|
||||
if (pDraw->iHasAlpha) { // use the alpha to modify the palette
|
||||
if (u32Bkgd != 0xffffffff) { // user wants to blend it with a background color
|
||||
uint32_t b_r, b_g, b_b;
|
||||
b_r = u32Bkgd & 0xff; b_g = (u32Bkgd & 0xff00) >> 8;
|
||||
b_b = (u32Bkgd >> 16) & 0xff;
|
||||
uint16_t u16Clr = (u32Bkgd & 0xf8) << 8;
|
||||
u16Clr |= ((u32Bkgd & 0xfc00) >> 5);
|
||||
u16Clr |= ((u32Bkgd & 0xf80000) >> 19);
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
int a;
|
||||
c = *s++;
|
||||
a = pDraw->pPalette[768+c]; // get alpha
|
||||
if (a == 0) { // pure BGColor
|
||||
usPixel = u16Clr;
|
||||
} else if (a == 255) { // opaque
|
||||
pPal = &pDraw->pPalette[c * 3];
|
||||
usPixel = ((pPal[2] * a) >> 11); // blue
|
||||
usPixel |= (((pPal[1] * a) >> 10) << 5); // green
|
||||
usPixel |= (((pPal[0] * a) >> 11) << 11); // red
|
||||
} else { // need to mix the bg & fg colors
|
||||
|
||||
pPal = &pDraw->pPalette[c * 3];
|
||||
usPixel = ((((pPal[2] * a) + (b_b * (255-a)))) >> 11); // blue
|
||||
usPixel |= ((((pPal[1] * a) + (b_g * (255-a)))>> 10) << 5); // green
|
||||
usPixel |= ((((pPal[0] * a) + (b_r * (255-a)))>> 11) << 11); // red
|
||||
} // need to mix with alpha
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
} // for x
|
||||
} else { // alpha 0 = black
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
int a;
|
||||
c = *s++;
|
||||
a = pDraw->pPalette[768+c]; // get alpha
|
||||
pPal = &pDraw->pPalette[c * 3];
|
||||
usPixel = ((pPal[2] * a) >> 11); // blue
|
||||
usPixel |= (((pPal[1] * a) >> 10) << 5); // green
|
||||
usPixel |= (((pPal[0] * a) >> 11) << 11); // red
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
} // for x
|
||||
}
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
int a;
|
||||
c = *s++;
|
||||
a = pDraw->pPalette[768+c]; // get alpha
|
||||
pPal = &pDraw->pPalette[c * 3];
|
||||
usPixel = ((pPal[2] * a) >> 11); // blue
|
||||
usPixel |= (((pPal[1] * a) >> 10) << 5); // green
|
||||
usPixel |= (((pPal[0] * a) >> 11) << 11); // red
|
||||
if (iEndiannes == PNG_RGB565_BIG_ENDIAN)
|
||||
usPixel = __builtin_bswap16(usPixel);
|
||||
*pDest++ = usPixel;
|
||||
} // for x
|
||||
} else {
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
c = *s++;
|
||||
@@ -525,9 +444,6 @@ PNG_STATIC void PNGRGB565(PNGDRAW *pDraw, uint16_t *pPixels, int iEndiannes, uin
|
||||
s += 4; // skip alpha
|
||||
}
|
||||
} else { // ignore alpha
|
||||
#ifdef ARDUINO_ESP32S3_DEV
|
||||
s3_rgb565(s, (uint8_t *)pDest, pDraw->iWidth, (iEndiannes == PNG_RGB565_BIG_ENDIAN));
|
||||
#else
|
||||
for (x=0; x<pDraw->iWidth; x++) {
|
||||
usPixel = (s[2] >> 3); // blue
|
||||
usPixel |= ((s[1] >> 2) << 5); // green
|
||||
@@ -537,7 +453,6 @@ PNG_STATIC void PNGRGB565(PNGDRAW *pDraw, uint16_t *pPixels, int iEndiannes, uin
|
||||
*pDest++ = usPixel;
|
||||
s += 4; // skip alpha
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -591,8 +506,8 @@ PNG_STATIC int PNGParseInfo(PNGIMAGE *pPage)
|
||||
|
||||
pPage->iHasAlpha = pPage->iInterlaced = 0;
|
||||
// Read a few bytes to just parse the size/pixel info
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, s, 33);
|
||||
if (iBytesRead < 33) { // a PNG file this tiny? probably bad
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, s, 32);
|
||||
if (iBytesRead < 32) { // a PNG file this tiny? probably bad
|
||||
pPage->iError = PNG_INVALID_FILE;
|
||||
return pPage->iError;
|
||||
}
|
||||
@@ -602,17 +517,6 @@ PNG_STATIC int PNGParseInfo(PNGIMAGE *pPage)
|
||||
return pPage->iError;
|
||||
}
|
||||
if (MOTOLONG(&s[12]) == 0x49484452/*'IHDR'*/) {
|
||||
int len = MOTOLONG(&s[8]);
|
||||
if (len != 13) {
|
||||
pPage->iError = PNG_INVALID_FILE;
|
||||
return pPage->iError;
|
||||
}
|
||||
int crc = (int)crc32(0, &s[12], len+4);
|
||||
int hdrcrc = MOTOLONG(&s[16+len]);
|
||||
if (len != 13 || crc != hdrcrc) {
|
||||
pPage->iError = PNG_INVALID_FILE;
|
||||
return pPage->iError;
|
||||
}
|
||||
pPage->iWidth = MOTOLONG(&s[16]);
|
||||
pPage->iHeight = MOTOLONG(&s[20]);
|
||||
pPage->ucBpp = s[24]; // bits per pixel
|
||||
@@ -725,7 +629,7 @@ PNG_STATIC void DeFilter(uint8_t *pCurr, uint8_t *pPrev, int iWidth, int iPitch)
|
||||
b = *pPrev++;
|
||||
p = b - c;
|
||||
pc = a - c;
|
||||
// assume no native ABS() instruction
|
||||
// asume no native ABS() instruction
|
||||
pa = p < 0 ? -p : p;
|
||||
pb = pc < 0 ? -pc : pc;
|
||||
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
|
||||
@@ -773,13 +677,8 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
return 0;
|
||||
}
|
||||
// Use internal buffer to maintain the current and previous lines
|
||||
y = (int)(intptr_t)&pPage->ucPixels[0];
|
||||
y &= 15; // make sure we're 16-byte aligned, -1 for filter byte
|
||||
y += (15 - y);
|
||||
pCurr = &pPage->ucPixels[y]; // so that the pixels are 16-byte aligned
|
||||
y += pPage->iPitch + 1; // both lines are 16-byte (minus 1)
|
||||
y += (15 - (y & 15));
|
||||
pPrev = &pPage->ucPixels[y];
|
||||
pCurr = pPage->ucPixels;
|
||||
pPrev = &pPage->ucPixels[pPage->iPitch+1];
|
||||
pPage->iError = PNG_SUCCESS;
|
||||
// Start decoding the image
|
||||
bDone = FALSE;
|
||||
@@ -792,7 +691,7 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
// Insert the memory pointer here to avoid having to use malloc() inside zlib
|
||||
state = (struct inflate_state FAR *)pPage->ucZLIB;
|
||||
d_stream.state = (struct internal_state FAR *)state;
|
||||
state->window = &pPage->ucZLIB[sizeof(struct inflate_state)]; // point to 32k dictionary buffer
|
||||
state->window = &pPage->ucZLIB[sizeof(inflate_state)]; // point to 32k dictionary buffer
|
||||
err = inflateInit(&d_stream);
|
||||
#ifdef FUTURE
|
||||
// if (inpage->cCompression == PIL_COMP_IPHONE_FLATE)
|
||||
@@ -803,27 +702,18 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
|
||||
iFileOffset = 8; // skip PNG file signature
|
||||
iOffset = 0; // internal buffer offset starts at 0
|
||||
iBytesRead = 0; // We haven't read yet anything
|
||||
// Read some data to start
|
||||
(*pPage->pfnSeek)(&pPage->PNGFile, iFileOffset);
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, s, PNG_FILE_BUF_SIZE);
|
||||
iFileOffset += iBytesRead;
|
||||
y = 0;
|
||||
d_stream.avail_out = 0;
|
||||
d_stream.next_out = pPage->pImage;
|
||||
|
||||
// continue until fully decoded
|
||||
// parse the markers until the next data block
|
||||
while (!bDone && y < pPage->iHeight)
|
||||
while (y < pPage->iHeight) { // continue until fully decoded
|
||||
// parse the markers until the next data block
|
||||
while (!bDone)
|
||||
{
|
||||
if (iOffset > iBytesRead-8) { // need to read more data
|
||||
iFileOffset += (iOffset - iBytesRead);
|
||||
(*pPage->pfnSeek)(&pPage->PNGFile, iFileOffset);
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, s, PNG_FILE_BUF_SIZE);
|
||||
if (iBytesRead < 8) {
|
||||
pPage->iError = PNG_DECODE_ERROR;
|
||||
return 1;
|
||||
}
|
||||
iFileOffset += iBytesRead;
|
||||
iOffset = 0;
|
||||
}
|
||||
|
||||
iLen = MOTOLONG(&s[iOffset]); // chunk length
|
||||
if (iLen < 0 || iLen + (iFileOffset - iBytesRead) > pPage->PNGFile.iSize) // invalid data
|
||||
{
|
||||
@@ -931,10 +821,7 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
pngd.iHasAlpha = pPage->iHasAlpha;
|
||||
pngd.iBpp = pPage->ucBpp;
|
||||
pngd.y = y;
|
||||
if (!(*pPage->pfnDraw)(&pngd)) { // user code returned 0 from PNGDraw
|
||||
pPage->iError = PNG_QUIT_EARLY;
|
||||
return pPage->iError;
|
||||
}
|
||||
(*pPage->pfnDraw)(&pngd);
|
||||
} else {
|
||||
// copy to destination bitmap
|
||||
memcpy(&pPage->pImage[y * pPage->iPitch], &pCurr[1], pPage->iPitch);
|
||||
@@ -959,14 +846,17 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
y |= 0; // need more data
|
||||
}
|
||||
} // while (iLen)
|
||||
if (iBytesRead) { // data remaining in buffer
|
||||
// Restore iBytesRead to be total ucFileBuf bytes, not remainder
|
||||
iBytesRead += iOffset;
|
||||
} else {
|
||||
// We consumed everything, so move the pointer to the zero.
|
||||
// We haven't read CRC for the block, but it doesn't matter as
|
||||
// pfnSeek will move past it to the next chunk.
|
||||
iOffset = 0;
|
||||
if (y != pPage->iHeight && iFileOffset < pPage->PNGFile.iSize) {
|
||||
// need to read more IDAT chunks
|
||||
if (iBytesRead) { // data remaining in buffer
|
||||
// move the data down
|
||||
memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], iBytesRead);
|
||||
iOffset = 0;
|
||||
} else {
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, pPage->ucFileBuf, PNG_FILE_BUF_SIZE);
|
||||
iFileOffset += iBytesRead;
|
||||
iOffset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// case 0x69545874: //'iTXt'
|
||||
@@ -999,6 +889,14 @@ PNG_STATIC int DecodePNG(PNGIMAGE *pPage, void *pUser, int iOptions)
|
||||
#endif
|
||||
} // switch
|
||||
iOffset += (iLen + 4); // skip data + CRC
|
||||
if (iOffset > iBytesRead-8) { // need to read more data
|
||||
iFileOffset += (iOffset - iBytesRead);
|
||||
(*pPage->pfnSeek)(&pPage->PNGFile, iFileOffset);
|
||||
iBytesRead = (*pPage->pfnRead)(&pPage->PNGFile, s, PNG_FILE_BUF_SIZE);
|
||||
iFileOffset += iBytesRead;
|
||||
iOffset = 0;
|
||||
}
|
||||
} // while !bDone
|
||||
} // while y < height
|
||||
err = inflateEnd(&d_stream);
|
||||
return pPage->iError;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
//
|
||||
// ESP32-S3 SIMD optimized code
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
// written April 17, 2024
|
||||
//
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#include "dsps_fft2r_platform.h"
|
||||
#if (dsps_fft2r_sc16_aes3_enabled == 1)
|
||||
.text
|
||||
.align 4
|
||||
|
||||
// Convert N pixels of RGBA (RGB8888) to RGB565
|
||||
// A2 A3 A4 A5
|
||||
// Call as void s3_rgb565(uint8_t *pSrc, uint8_t *pDest, int iCount, bool bBigEndian);
|
||||
.global s3_rgb565
|
||||
.type s3_rgb565,@function
|
||||
|
||||
s3_rgb565:
|
||||
# no idea what this frequency keyword does
|
||||
# .frequency 1.000 0.000
|
||||
entry a1,16
|
||||
addi.n a4,a4,7 # process pixels in groups of 8
|
||||
movi.n a6,-8
|
||||
and a4,a4,a6
|
||||
.top_rgb565:
|
||||
ee.vld.128.ip q0,a2,16 # load 4 pixels into Q0
|
||||
ee.vld.128.ip q1,a2,16 # load another 4 pixels into Q1
|
||||
ee.xorq q4,q4,q4 # destination reg set to 0s
|
||||
ee.vcmp.eq.s16 q2,q2,q2 # create FFs
|
||||
ee.vunzip.16 q0,q1 # interleave RG and BA from Q0/Q1
|
||||
ee.vsubs.s16 q3,q4,q2 # make 16-bit 1's in q3
|
||||
movi.n a6,10 # load the shift register with 10 (for green)
|
||||
wsr.sar a6 # put it in the SAR (shift amount register)
|
||||
ee.vmul.u16 q5,q0,q3 # shift green into lower 6 bits of q5
|
||||
movi.n a6,3 # shift value 3 for red and blue
|
||||
wsr.sar a6
|
||||
ee.vmul.s16 q6,q0,q3 # shift red into lower 5 bits of q6
|
||||
ee.vmul.s16 q7,q1,q3 # shift blue into lower 5 bits of q7
|
||||
movi.n a6,5
|
||||
wsr.sar a6 # set shift to 5
|
||||
ee.vsl.32 q4,q3 # q4 = 0x00200020...
|
||||
ee.vsubs.s16 q4,q4,q3 # Now q4 has the r/b mask of 0x001f001f...
|
||||
ee.andq q6,q4,q6 # mask off 5 bits of red
|
||||
ee.andq q7,q4,q7 # mask off 5 bits of blue
|
||||
ee.vsl.32 q5,q5 # shift green left 5
|
||||
movi.n a6,11
|
||||
wsr.sar a6 # set shift to 11
|
||||
ee.vsl.32 q6,q6 # shift red left 11
|
||||
ee.orq q6,q6,q5 # combine red+green
|
||||
ee.orq q6,q6,q7 # combine rg with b
|
||||
mv.qr q5,q6 # in case we're generating little endian output
|
||||
beqi a5,0,.rgb565_out # RGB565 little endian?
|
||||
ee.vunzip.8 q6,q5 # swap the byte order to be big-endian
|
||||
ee.vzip.8 q5,q6
|
||||
.rgb565_out:
|
||||
ee.vst.128.ip q5,a3,16 # store 8 RGB565 pixels
|
||||
addi.n a4,a4,-8
|
||||
bnez.n a4,.top_rgb565
|
||||
retw.n
|
||||
#endif // dsps_fft2r_sc16_aes3_enabled
|
||||
#endif // ESP32
|
||||
@@ -8,10 +8,6 @@
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC optimize("O2")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||
|
||||
@@ -24,12 +24,12 @@ z_const char * const z_errmsg[10] = {
|
||||
};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion(void)
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
}
|
||||
|
||||
uLong ZEXPORT zlibCompileFlags(void)
|
||||
uLong ZEXPORT zlibCompileFlags()
|
||||
{
|
||||
uLong flags;
|
||||
|
||||
@@ -119,7 +119,8 @@ uLong ZEXPORT zlibCompileFlags(void)
|
||||
# endif
|
||||
int ZLIB_INTERNAL z_verbose = verbose;
|
||||
|
||||
void ZLIB_INTERNAL z_error (char * m)
|
||||
void ZLIB_INTERNAL z_error (m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "%s\n", m);
|
||||
exit(1);
|
||||
@@ -129,7 +130,8 @@ void ZLIB_INTERNAL z_error (char * m)
|
||||
/* exported to allow conversion of error code to string for compress() and
|
||||
* uncompress()
|
||||
*/
|
||||
const char * ZEXPORT zError(int err)
|
||||
const char * ZEXPORT zError(err)
|
||||
int err;
|
||||
{
|
||||
return ERR_MSG(err);
|
||||
}
|
||||
@@ -300,7 +302,10 @@ extern voidp calloc OF((uInt items, uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
|
||||
voidpf opaque;
|
||||
unsigned items;
|
||||
unsigned size;
|
||||
{
|
||||
(void)opaque;
|
||||
// return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||
@@ -308,7 +313,9 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
return Z_NULL; // DEBUG - no longer used
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
void ZLIB_INTERNAL zcfree (opaque, ptr)
|
||||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
(void)opaque;
|
||||
// free(ptr); // DEBUG - no longer used
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#if defined(STDC) && !defined(Z_SOLO)
|
||||
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
@@ -160,7 +159,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
# define OS_CODE 18
|
||||
#endif
|
||||
|
||||
#if defined( __APPLE__ ) && !(defined(MACOS) || defined(TARGET_OS_MAC))
|
||||
#ifdef __APPLE__
|
||||
# define OS_CODE 19
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user