From a6bd626334a5dc2d6c32308aa1b1416c0b355e48 Mon Sep 17 00:00:00 2001 From: Mike Bell Date: Sat, 3 Jun 2023 17:51:03 +0100 Subject: [PATCH] RGB888 JPEG decode (implemented in some cases only) --- examples/dv_stick/dv_slideshow.cpp | 24 +++++++++++++----------- examples/dv_stick/dv_stick_test.cpp | 9 ++++++++- libraries/jpegdec/JPEGDEC.h | 1 + libraries/jpegdec/jpeg.inl | 28 ++++++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/examples/dv_stick/dv_slideshow.cpp b/examples/dv_stick/dv_slideshow.cpp index 918fa642..3c34a9c5 100644 --- a/examples/dv_stick/dv_slideshow.cpp +++ b/examples/dv_stick/dv_slideshow.cpp @@ -12,14 +12,14 @@ using namespace pimoroni; -#define FRAME_WIDTH 1280 +#define FRAME_WIDTH 640 #define FRAME_HEIGHT 720 FATFS fs; FRESULT fr; -DVDisplay display(FRAME_WIDTH, FRAME_HEIGHT); -PicoGraphics_PenDV_RGB555 graphics(FRAME_WIDTH, FRAME_HEIGHT, display); +DVDisplay display(FRAME_WIDTH, FRAME_HEIGHT, DVDisplay::MODE_RGB888); +PicoGraphics_PenDV_RGB888 graphics(FRAME_WIDTH, FRAME_HEIGHT, display); JPEGDEC jpeg; struct { @@ -48,24 +48,26 @@ int32_t jpegdec_seek_callback(JPEGFILE *jpeg, int32_t p) { } int jpegdec_draw_callback(JPEGDRAW *draw) { - uint16_t *p = draw->pPixels; + uint8_t *p = (uint8_t*)draw->pPixels; int xo = jpeg_decode_options.x; int yo = jpeg_decode_options.y; for(int y = 0; y < draw->iHeight; y++) { - for(int x = 0; x < draw->iWidth; x++) { - int sx = draw->x + x + xo; + for(int x = 0; x < draw->iWidth; x+=2) { + int sx = ((draw->x + x) >> 1) + xo; int sy = draw->y + y + yo; if(sx >= 0 && sx < graphics.bounds.w && x < draw->iWidthUsed && sy >= 0 && sy < graphics.bounds.h) { - const RGB565 col = *p; - graphics.set_pen((col & 0x1F) | ((col & 0xFFC0) >> 1)); + RGB888 col = ((((uint32_t)p[0] + (uint32_t)p[3]) << 15) & 0xff0000) | + ((((uint32_t)p[1] + (uint32_t)p[4]) << 7) & 0xff00) | + (((uint32_t)p[2] + (uint32_t)p[5]) >> 1); + graphics.set_pen(col); graphics.pixel({sx, sy}); } - p++; + p += 6; } } @@ -82,10 +84,10 @@ void draw_jpeg(std::string filename) { jpegdec_draw_callback ); - jpeg_decode_options.x = (FRAME_WIDTH - jpeg.getWidth()) >> 1; + jpeg_decode_options.x = (FRAME_WIDTH - (jpeg.getWidth() >> 1)) >> 1; jpeg_decode_options.y = (FRAME_HEIGHT - jpeg.getHeight()) >> 1; - jpeg.setPixelType(RGB565_LITTLE_ENDIAN); + jpeg.setPixelType(RGB888_LITTLE_ENDIAN); printf("- starting jpeg decode.."); int start = millis(); diff --git a/examples/dv_stick/dv_stick_test.cpp b/examples/dv_stick/dv_stick_test.cpp index 3c217ca9..06900608 100644 --- a/examples/dv_stick/dv_stick_test.cpp +++ b/examples/dv_stick/dv_stick_test.cpp @@ -46,7 +46,7 @@ int main() { gpio_set_dir(BUTTON_A, GPIO_IN); gpio_pull_up(BUTTON_A); - sleep_ms(5000); + //sleep_ms(5000); DVDisplay display(FRAME_WIDTH, FRAME_HEIGHT, DVDisplay::MODE_RGB888); display.init(); @@ -120,8 +120,15 @@ int main() { //} uint32_t render_start_time = time_us_32(); +#if 1 + for (int j = 0; j < FRAME_HEIGHT; ++j) { + graphics.set_pen(j, 0xFF, 0xFF); + graphics.pixel_span({0,j}, FRAME_WIDTH); + } +#else graphics.set_pen(0xFF, 0xFF, 0xFF); graphics.clear(); +#endif #if 0 for (uint i = 0; i < 128; i++) { diff --git a/libraries/jpegdec/JPEGDEC.h b/libraries/jpegdec/JPEGDEC.h index a3f55b8e..274e0102 100644 --- a/libraries/jpegdec/JPEGDEC.h +++ b/libraries/jpegdec/JPEGDEC.h @@ -68,6 +68,7 @@ enum { RGB565_LITTLE_ENDIAN = 0, RGB565_BIG_ENDIAN, + RGB888_LITTLE_ENDIAN, EIGHT_BIT_GRAYSCALE, FOUR_BIT_DITHERED, TWO_BIT_DITHERED, diff --git a/libraries/jpegdec/jpeg.inl b/libraries/jpegdec/jpeg.inl index d6bfb543..29255f6c 100644 --- a/libraries/jpegdec/jpeg.inl +++ b/libraries/jpegdec/jpeg.inl @@ -2210,7 +2210,6 @@ static void JPEGPixel2BE(uint16_t *pDest, int32_t iY1, int32_t iY2, int32_t iCb, *(uint32_t *)&pDest[0] = __builtin_bswap16(ulPixel1) | ((uint32_t)__builtin_bswap16(ulPixel2)<<16); } /* JPEGPixel2BE() */ -#if 0 static void JPEGPixelLE888(uint8_t *pDest, int iY, int iCb, int iCr) { int32_t iCBB, iCBG, iCRG, iCRR; @@ -2236,7 +2235,6 @@ static void JPEGPixelLE888(uint8_t *pDest, int iY, int iCb, int iCr) if (uVal & 0x100) uVal = 0; *pDest++ = uVal; } -#endif static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch) { @@ -2246,6 +2244,7 @@ static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch) int iRow; uint8_t *pY, *pCr, *pCb; uint16_t *pOutput = &pJPEG->usPixels[x]; + uint8_t *pOutput8 = ((uint8_t*)pJPEG->usPixels) + x * 3; pY = (unsigned char *)&pJPEG->sMCUs[0*DCTSIZE]; pCb = (unsigned char *)&pJPEG->sMCUs[1*DCTSIZE]; @@ -2342,6 +2341,17 @@ static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch) JPEGPixelLE(pOutput+iCol, Y, iCb, iCr); } // for col } + else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN) + { + for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do + { + iCr = *pCr++; + iCb = *pCb++; + Y = (int)(*pY++) << 12; + JPEGPixelLE888(pOutput8+iCol*3, Y, iCb, iCr); + } // for col + pOutput8 += iPitch * 3; + } else { for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do @@ -2697,6 +2707,7 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch) int iRow, iCol, iXCount, iYCount; uint8_t *pY, *pCr, *pCb; uint16_t *pOutput = &pJPEG->usPixels[x]; + uint8_t *pOutput8 = ((uint8_t*)pJPEG->usPixels) + x * 3; pY = (uint8_t *)&pJPEG->sMCUs[0*DCTSIZE]; pCb = (uint8_t *)&pJPEG->sMCUs[2*DCTSIZE]; @@ -2828,6 +2839,11 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch) JPEGPixelLE(pOutput + iCol, Y1, Cb, Cr); JPEGPixelLE(pOutput + iPitch + iCol, Y2, Cb, Cr); } + else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN) + { + JPEGPixelLE888(pOutput8 + iCol*3, Y1, Cb, Cr); + JPEGPixelLE888(pOutput8 + (iPitch + iCol)*3, Y2, Cb, Cr); + } else { JPEGPixelBE(pOutput + iCol, Y1, Cb, Cr); @@ -2840,6 +2856,7 @@ static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch) pCb += 8; pCr += 8; pOutput += iPitch*2; // next 2 lines of dest pixels + pOutput8 += iPitch*6; } } /* JPEGPutMCU12() */ static void JPEGPutMCU21(JPEGIMAGE *pJPEG, int x, int iPitch) @@ -3097,6 +3114,8 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG) cDCTable2 = pJPEG->JPCI[2].dc_tbl_no; cACTable2 = pJPEG->JPCI[2].ac_tbl_no; iDCPred0 = iDCPred1 = iDCPred2 = mcuCX = mcuCY = 0; + + printf("SubSample mode: 0x%x\n", pJPEG->ucSubSample); switch (pJPEG->ucSubSample) // set up the parameters for the different subsampling options { @@ -3155,6 +3174,8 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG) iMCUCount = MAX_BUFFERED_PIXELS / (mcuCX * mcuCY); if (pJPEG->ucPixelType == EIGHT_BIT_GRAYSCALE) iMCUCount *= 2; // each pixel is only 1 byte + else if (pJPEG->ucPixelType == RGB888_LITTLE_ENDIAN) + iMCUCount = (iMCUCount >> 1) + (iMCUCount >> 3); // each picel is 3 bytes if (iMCUCount > cx) iMCUCount = cx; // don't go wider than the image if (iMCUCount > pJPEG->iMaxMCUs) // did the user set an upper bound on how many pixels per JPEGDraw callback? @@ -3164,6 +3185,9 @@ static int DecodeJPEG(JPEGIMAGE *pJPEG) jd.iBpp = 16; switch (pJPEG->ucPixelType) { + case RGB888_LITTLE_ENDIAN: + jd.iBpp = 24; + break; case EIGHT_BIT_GRAYSCALE: jd.iBpp = 8; break;