/* jpeg_utils.c - Version header file for Tasmota Copyright (C) 2021 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifdef ESP32 #ifdef JPEG_PICTS #include "img_converters.h" #include "esp_jpg_decode.h" void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len) { uint8_t red, grn, blu; uint16_t b , g, r; for (uint32_t cnt=0; cnt> 3) & 0x1f; g = ((grn >> 2) & 0x3f) << 5; r = ((red >> 3) & 0x1f) << 11; *out++ = (r | g | b); } } typedef struct { uint16_t width; uint16_t height; uint16_t data_offset; const uint8_t *input; uint8_t *output; } rgb_jpg_decoder; //input buffer static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len) { rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; if(buf) { memcpy(buf, jpeg->input + index, len); } return len; } //output buffer and image width static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data) { rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; if(!data){ if(x == 0 && y == 0){ //write start jpeg->width = w; jpeg->height = h; //if output is null, this is BMP if(!jpeg->output){ jpeg->output = (uint8_t *)malloc((w*h*3)+jpeg->data_offset); if(!jpeg->output){ return false; } } } else { //write end } return true; } size_t jw = jpeg->width*3; size_t t = y * jw; size_t b = t + (h * jw); size_t l = x * 3; uint8_t *out = jpeg->output+jpeg->data_offset; uint8_t *o = out; size_t iy, ix; w = w * 3; for(iy=t; iy= data_size) return false; //Check to protect against segmentation faults if(data[i] != 0xFF) return false; //Check that we are truly at the start of another block if(data[i+1] == 0xC0) { //0xFFC0 is the "Start of frame" marker which contains the file size //The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y] *height = data[i+5]*256 + data[i+6]; *width = data[i+7]*256 + data[i+8]; return true; } else { i+=2; //Skip the block marker block_length = data[i] * 256 + data[i+1]; //Go to the next block } } return false; //If this point is reached then no size was found }else{ return false; } //Not a valid JFIF string }else{ return false; } //Not a valid SOI header } #endif // JPEG_PICTS #endif //ESP32 #ifdef USE_DISPLAY_DUMP #define bytesPerPixel 3 #define fileHeaderSize 14 #define infoHeaderSize 40 void createBitmapFileHeader(uint32_t height, uint32_t width, uint8_t *fileHeader) { int paddingSize = (4 - (width*bytesPerPixel) % 4) % 4; int fileSize = fileHeaderSize + infoHeaderSize + (bytesPerPixel*width+paddingSize) * height; memset(fileHeader,0,fileHeaderSize); fileHeader[ 0] = (unsigned char)('B'); fileHeader[ 1] = (unsigned char)('M'); fileHeader[ 2] = (unsigned char)(fileSize ); fileHeader[ 3] = (unsigned char)(fileSize>> 8); fileHeader[ 4] = (unsigned char)(fileSize>>16); fileHeader[ 5] = (unsigned char)(fileSize>>24); fileHeader[10] = (unsigned char)(fileHeaderSize + infoHeaderSize); } void createBitmapInfoHeader(uint32_t height, uint32_t width, uint8_t *infoHeader ) { memset(infoHeader,0,infoHeaderSize); infoHeader[ 0] = (unsigned char)(infoHeaderSize); infoHeader[ 4] = (unsigned char)(width ); infoHeader[ 5] = (unsigned char)(width>> 8); infoHeader[ 6] = (unsigned char)(width>>16); infoHeader[ 7] = (unsigned char)(width>>24); infoHeader[ 8] = (unsigned char)(height ); infoHeader[ 9] = (unsigned char)(height>> 8); infoHeader[10] = (unsigned char)(height>>16); infoHeader[11] = (unsigned char)(height>>24); infoHeader[12] = (unsigned char)(1); infoHeader[14] = (unsigned char)(bytesPerPixel*8); infoHeader[24] = (unsigned char)0x13; // 72 dpi infoHeader[25] = (unsigned char)0x0b; infoHeader[28] = (unsigned char)0x13; infoHeader[29] = (unsigned char)0x0b; } #endif // USE_DISPLAY_DUMP