/* SPI Master example: jpeg decoder. This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ /* The image used for the effect on the LCD in the SPI master example is stored in flash as a jpeg file. This file contains the decode_image routine, which uses the tiny JPEG decoder library in ROM to decode this JPEG into a format that can be sent to the display. Keep in mind that the decoder library cannot handle progressive files (will give ``Image decoder: jd_prepare failed (8)`` as an error) so make sure to save in the correct format if you want to use a different image file. */ #include "decode_image.h" #include "rom/tjpgd.h" #include "esp_log.h" #include //Reference the binary-included jpeg file extern const uint8_t image_jpg_start[] asm("_binary_image_jpg_start"); extern const uint8_t image_jpg_end[] asm("_binary_image_jpg_end"); //Define the height and width of the jpeg file. Make sure this matches the actual jpeg //dimensions. #define IMAGE_W 336 #define IMAGE_H 256 const char *TAG="ImageDec"; //Data that is passed from the decoder function to the infunc/outfunc functions. typedef struct { const unsigned char *inData; //Pointer to jpeg data int inPos; //Current position in jpeg data uint16_t **outData; //Array of IMAGE_H pointers to arrays of IMAGE_W 16-bit pixel values int outW; //Width of the resulting file int outH; //Height of the resulting file } JpegDev; //Input function for jpeg decoder. Just returns bytes from the inData field of the JpegDev structure. static UINT infunc(JDEC *decoder, BYTE *buf, UINT len) { //Read bytes from input file JpegDev *jd=(JpegDev*)decoder->device; if (buf!=NULL) memcpy(buf, jd->inData+jd->inPos, len); jd->inPos+=len; return len; } //Output function. Re-encodes the RGB888 data from the decoder as big-endian RGB565 and //stores it in the outData array of the JpegDev structure. static UINT outfunc(JDEC *decoder, void *bitmap, JRECT *rect) { JpegDev *jd=(JpegDev*)decoder->device; uint8_t *in=(uint8_t*)bitmap; for (int y=rect->top; y<=rect->bottom; y++) { for (int x=rect->left; x<=rect->right; x++) { //We need to convert the 3 bytes in `in` to a rgb565 value. uint16_t v=0; v|=((in[0]>>3)<<11); v|=((in[1]>>2)<<5); v|=((in[2]>>3)<<0); //The LCD wants the 16-bit value in big-endian, so swap bytes v=(v>>8)|(v<<8); jd->outData[y][x]=v; in+=3; } } return 1; } //Size of the work space for the jpeg decoder. #define WORKSZ 3100 //Decode the embedded image into pixel lines that can be used with the rest of the logic. esp_err_t decode_image(uint16_t ***pixels) { char *work=NULL; int r; JDEC decoder; JpegDev jd; *pixels=NULL; esp_err_t ret=ESP_OK; //Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. *pixels=calloc(IMAGE_H, sizeof(uint16_t*)); if (*pixels==NULL) { ESP_LOGE(TAG, "Error allocating memory for lines"); ret=ESP_ERR_NO_MEM; goto err; } for (int i=0; i