Merge pull request #600 from pimoroni/patch-jpegdec-rgb888

JPEGDEC/PicoGraphics: Add support for RGB888 target.
pull/606/head
Philip Howard 2022-12-16 20:53:55 +00:00 zatwierdzone przez GitHub
commit 930784df08
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 55 dodań i 17 usunięć

Wyświetl plik

@ -142,6 +142,22 @@ int JPEGDEC::open(const char *szFilename, JPEG_OPEN_CALLBACK *pfnOpen, JPEG_CLOS
} /* open() */
//
// data stream initialization
//
int JPEGDEC::open(void *fHandle, int iDataSize, JPEG_CLOSE_CALLBACK *pfnClose, JPEG_READ_CALLBACK *pfnRead, JPEG_SEEK_CALLBACK *pfnSeek, JPEG_DRAW_CALLBACK *pfnDraw)
{
memset(&_jpeg, 0, sizeof(JPEGIMAGE));
_jpeg.pfnRead = pfnRead;
_jpeg.pfnSeek = pfnSeek;
_jpeg.pfnDraw = pfnDraw;
_jpeg.pfnClose = pfnClose;
_jpeg.iMaxMCUs = 1000; // set to an unnaturally high value to start
_jpeg.JPEGFile.iSize = iDataSize;
_jpeg.JPEGFile.fHandle = fHandle;
return JPEGInit(&_jpeg);
} /* open() */
#ifdef FS_H
static int32_t FileRead(JPEGFILE *handle, uint8_t *buffer, int32_t length)
{
@ -191,6 +207,13 @@ int JPEGDEC::decode(int x, int y, int iOptions)
_jpeg.pDitherBuffer = nullptr;
return DecodeJPEG(&_jpeg);
} /* decode() */
//
// set draw callback user pointer variable
//
void JPEGDEC::setUserPointer(void *p)
{
_jpeg.pUser = p;
}
// TODO PR these tweaks to https://github.com/bitbank2/JPEGDEC
int JPEGDEC::decodeDither(int x, int y, uint8_t *pDither, int iOptions)

Wyświetl plik

@ -13,7 +13,7 @@
//
#ifndef __JPEGDEC__
#define __JPEGDEC__
#if defined( __MACH__ ) || defined( __LINUX__ ) || defined( __MCUXPRESSO ) || defined( PICO_BUILD )
#if defined( __MACH__ ) || defined( __LINUX__ ) || defined( __MCUXPRESSO ) || defined( ESP_PLATFORM ) || defined( PICO_BUILD )
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
@ -108,8 +108,10 @@ typedef struct jpeg_draw_tag
{
int x, y; // upper left corner of current MCU
int iWidth, iHeight; // size of this MCU
int iWidthUsed; // clipped size for odd/edges
int iBpp; // bit depth of the pixels (8 or 16)
uint16_t *pPixels; // 16-bit pixels
void *pUser;
} JPEGDRAW;
// Callback function prototypes
@ -185,6 +187,7 @@ typedef struct jpeg_image_tag
JPEGCOMPINFO JPCI[MAX_COMPS_IN_SCAN]; /* Max color components */
JPEGFILE JPEGFile;
BUFFERED_BITS bb;
void *pUser;
uint8_t *pDitherBuffer; // provided externally to do Floyd-Steinberg dithering
uint16_t usPixels[MAX_BUFFERED_PIXELS];
int16_t sMCUs[DCTSIZE * MAX_MCU_COUNT]; // 4:2:0 needs 6 DCT blocks per MCU
@ -208,6 +211,7 @@ class JPEGDEC
int openRAM(uint8_t *pData, int iDataSize, JPEG_DRAW_CALLBACK *pfnDraw);
int openFLASH(uint8_t *pData, int iDataSize, JPEG_DRAW_CALLBACK *pfnDraw);
int open(const char *szFilename, JPEG_OPEN_CALLBACK *pfnOpen, JPEG_CLOSE_CALLBACK *pfnClose, JPEG_READ_CALLBACK *pfnRead, JPEG_SEEK_CALLBACK *pfnSeek, JPEG_DRAW_CALLBACK *pfnDraw);
int open(void *fHandle, int iDataSize, JPEG_CLOSE_CALLBACK *pfnClose, JPEG_READ_CALLBACK *pfnRead, JPEG_SEEK_CALLBACK *pfnSeek, JPEG_DRAW_CALLBACK *pfnDraw);
#ifdef FS_H
int open(File &file, JPEG_DRAW_CALLBACK *pfnDraw);
#endif
@ -218,6 +222,7 @@ class JPEGDEC
int getWidth();
int getHeight();
int getBpp();
void setUserPointer(void *p);
int getSubSample();
int hasThumb();
int getThumbWidth();

Wyświetl plik

@ -33,9 +33,11 @@ static void JPEGGetMoreData(JPEGIMAGE *pPage);
static int DecodeJPEG(JPEGIMAGE *pImage);
static int32_t readRAM(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen);
static int32_t seekMem(JPEGFILE *pFile, int32_t iPosition);
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
static int32_t readFile(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen);
static int32_t seekFile(JPEGFILE *pFile, int32_t iPosition);
static void closeFile(void *handle);
#endif
static void JPEGDither(JPEGIMAGE *pJPEG, int iWidth, int iHeight);
/* JPEG tables */
// zigzag ordering of DCT coefficients
@ -474,7 +476,7 @@ static const uint16_t usRangeTableB[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x00
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO ) || defined( PICO_BUILD )
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
//
// API for C
//
@ -499,7 +501,6 @@ int JPEG_openRAM(JPEGIMAGE *pJPEG, uint8_t *pData, int iDataSize, JPEG_DRAW_CALL
//
// File initialization
//
/*
int JPEG_openFile(JPEGIMAGE *pJPEG, const char *szFilename, JPEG_DRAW_CALLBACK *pfnDraw)
{
memset(pJPEG, 0, sizeof(JPEGIMAGE));
@ -517,7 +518,7 @@ int JPEG_openFile(JPEGIMAGE *pJPEG, const char *szFilename, JPEG_DRAW_CALLBACK *
pJPEG->JPEGFile.iSize = (int)ftell((FILE *)pJPEG->JPEGFile.fHandle);
fseek((FILE *)pJPEG->JPEGFile.fHandle, 0, SEEK_SET);
return JPEGInit(pJPEG);
} *//* JPEG_openFile() */
} /* JPEG_openFile() */
int JPEG_getLastError(JPEGIMAGE *pJPEG)
{
@ -631,7 +632,7 @@ static int32_t seekMem(JPEGFILE *pFile, int32_t iPosition)
return iPosition;
} /* seekMem() */
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO ) || defined( PICO_BUILD )
#if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
static void closeFile(void *handle)
{
@ -2350,15 +2351,15 @@ static void JPEGPixel2LE(uint16_t *pDest, int iY1, int iY2, int iCb, int iCr)
#endif
} /* JPEGPixel2LE() */
static void JPEGPixel2BE(uint16_t *pDest, int iY1, int iY2, int iCb, int iCr)
static void JPEGPixel2BE(uint16_t *pDest, int32_t iY1, int32_t iY2, int32_t iCb, int32_t iCr)
{
int iCBB, iCBG, iCRG, iCRR;
int32_t iCBB, iCBG, iCRG, iCRR;
uint32_t ulPixel1, ulPixel2;
iCBB = 7258 * (iCb-0x80);
iCBG = -1409 * (iCb-0x80);
iCRG = -2925 * (iCr-0x80);
iCRR = 5742 * (iCr-0x80);
iCBB = 7258L * (iCb-0x80);
iCBG = -1409L * (iCb-0x80);
iCRG = -2925L * (iCr-0x80);
iCRR = 5742L * (iCr-0x80);
ulPixel1 = usRangeTableB[((iCBB + iY1) >> 12) & 0x3ff]; // blue pixel
ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 12) & 0x3ff]; // green pixel
ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 12) & 0x3ff]; // red pixel
@ -2366,7 +2367,7 @@ static void JPEGPixel2BE(uint16_t *pDest, int iY1, int iY2, int iCb, int iCr)
ulPixel2 = usRangeTableB[((iCBB + iY2) >> 12) & 0x3ff]; // blue pixel
ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 12) & 0x3ff]; // green pixel
ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 12) & 0x3ff]; // red pixel
*(uint32_t *)&pDest[0] = __builtin_bswap16(ulPixel1) | (__builtin_bswap16(ulPixel2)<<16);
*(uint32_t *)&pDest[0] = __builtin_bswap16(ulPixel1) | ((uint32_t)__builtin_bswap16(ulPixel2)<<16);
} /* JPEGPixel2BE() */
static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch)
@ -3453,9 +3454,13 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG)
if (xoff == iPitch || x == cx-1) // time to draw
{
xoff = 0;
jd.iWidth = iPitch; // width of each LCD block group
jd.iWidth = jd.iWidthUsed = iPitch; // width of each LCD block group
jd.pUser = pJPEG->pUser;
if (pJPEG->ucPixelType > EIGHT_BIT_GRAYSCALE) // dither to 4/2/1 bits
JPEGDither(pJPEG, cx * mcuCX, mcuCY);
if ((x+1)*mcuCX > pJPEG->iWidth) { // right edge has clipped pixels
jd.iWidthUsed = iPitch - (cx*mcuCX - pJPEG->iWidth);
}
if ((jd.y - pJPEG->iYOffset + mcuCY) > (pJPEG->iHeight>>iScaleShift)) { // last row needs to be trimmed
jd.iHeight = (pJPEG->iHeight>>iScaleShift) - (jd.y - pJPEG->iYOffset);
}

Wyświetl plik

@ -29,7 +29,6 @@ typedef struct _JPEG_obj_t {
} _JPEG_obj_t;
PicoGraphics *current_graphics = nullptr;
uint8_t current_flags = 0;
enum FLAGS : uint8_t {
@ -88,6 +87,7 @@ int JPEGDraw(JPEGDRAW *pDraw) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
PicoGraphics *current_graphics = (PicoGraphics *)pDraw->pUser;
// "pixel" is slow and clipped,
// guaranteeing we wont draw jpeg data out of the framebuffer..
// Can we clip beforehand and make this faster?
@ -95,6 +95,7 @@ MICROPY_EVENT_POLL_HOOK
uint8_t *pixel = (uint8_t *)pDraw->pPixels;
for(int y = 0; y < pDraw->iHeight; y++) {
for(int x = 0; x < pDraw->iWidth; x++) {
if(x >= pDraw->iWidthUsed) break; // Clip to the used width
current_graphics->set_pen((uint8_t)(*pixel >> 4));
current_graphics->set_pixel({pDraw->x + x, pDraw->y + y});
pixel++;
@ -104,6 +105,7 @@ MICROPY_EVENT_POLL_HOOK
uint8_t *pixels = (uint8_t *)pDraw->pPixels;
for(int y = 0; y < pDraw->iHeight; y++) {
for(int x = 0; x < pDraw->iWidth; x++) {
if(x >= pDraw->iWidthUsed) break; // Clip to the used width
int i = y * pDraw->iWidth + x;
uint8_t p = pixels[i / 2];
p >>= (i & 0b1) ? 0 : 4;
@ -116,6 +118,7 @@ MICROPY_EVENT_POLL_HOOK
uint8_t *pixels = (uint8_t *)pDraw->pPixels;
for(int y = 0; y < pDraw->iHeight; y++) {
for(int x = 0; x < pDraw->iWidth; x++) {
if(x >= pDraw->iWidthUsed) break; // Clip to the used width
int i = y * pDraw->iWidth + x;
uint8_t p = pixels[i / 8];
p >>= 7 - (i & 0b111);
@ -127,6 +130,7 @@ MICROPY_EVENT_POLL_HOOK
} else {
for(int y = 0; y < pDraw->iHeight; y++) {
for(int x = 0; x < pDraw->iWidth; x++) {
if(x >= pDraw->iWidthUsed) break; // Clip to the used width
int i = y * pDraw->iWidth + x;
if (current_graphics->pen_type == PicoGraphics::PEN_RGB332) {
if (current_flags & FLAG_NO_DITHER) {
@ -137,6 +141,9 @@ MICROPY_EVENT_POLL_HOOK
// Dithered output to RGB332
current_graphics->set_pixel_dither({pDraw->x + x, pDraw->y + y}, (RGB565)(pDraw->pPixels[i]));
}
} else if (current_graphics->pen_type == PicoGraphics::PEN_RGB888) {
current_graphics->set_pen(RGB((RGB565)pDraw->pPixels[i]).to_rgb888());
current_graphics->pixel({pDraw->x + x, pDraw->y + y});
} else if (current_graphics->pen_type == PicoGraphics::PEN_P8 || current_graphics->pen_type == PicoGraphics::PEN_P4 || current_graphics->pen_type == PicoGraphics::PEN_3BIT) {
current_graphics->set_pixel_dither({pDraw->x + x, pDraw->y + y}, RGB((RGB565)pDraw->pPixels[i]));
} else {
@ -264,12 +271,10 @@ mp_obj_t _JPEG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
}
// We need to store a pointer to the PicoGraphics surface
// since the JPEGDRAW struct has no userdata
current_graphics = self->graphics->graphics;
self->jpeg->setUserPointer((void *)self->graphics->graphics);
result = self->jpeg->decode(x, y, f);
current_graphics = nullptr;
current_flags = 0;
// Close the file since we've opened it on-demand