blob: a389c02af66f813fbbaaaa7df4d72db233118825 [file] [log] [blame] [edit]
#include <cstdint>
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_jpeg.h"
extern "C" {
#include "JPEG/jpeg_utils.h"
}
#include "jpeg.hpp"
#include "file.hpp"
static bool jpeg_tables_initialised = false;
static blit::AllocateCallback jpeg_alloc;
static JPEG_HandleTypeDef jpeg_handle;
static const int jpeg_max_block_len = 768; // can fit a whole number of all block sizes
static uint8_t jpeg_dec_block[jpeg_max_block_len];
static const uint8_t *jpeg_in_buf = nullptr;
static uint8_t *jpeg_out_buf = nullptr;
static uint32_t jpeg_in_len = 0, jpeg_in_off = 0;
static void *jpeg_in_file = nullptr;
static uint32_t jpeg_out_block = 0;
static JPEG_YCbCrToRGB_Convert_Function jpeg_conv_func = nullptr;
void HAL_JPEG_InfoReadyCallback(JPEG_HandleTypeDef *hjpeg, JPEG_ConfTypeDef *pInfo) {
// allocate output RGB buffer
if(pInfo->ImageWidth * pInfo->ImageHeight != 0) {
uint32_t jpeg_out_len = pInfo->ImageWidth * pInfo->ImageHeight * 3;
jpeg_out_buf = jpeg_alloc(jpeg_out_len);
}
// else fail horribly
// get conversion func
uint32_t num_mcus;
JPEG_GetDecodeColorConvertFunc(pInfo, &jpeg_conv_func, &num_mcus);
}
void HAL_JPEG_GetDataCallback(JPEG_HandleTypeDef *hjpeg, uint32_t NbDecodedData) {
jpeg_in_off += NbDecodedData;
if(jpeg_in_file) {
jpeg_in_len = read_file(jpeg_in_file, jpeg_in_off, 1024, (char *)jpeg_in_buf);
HAL_JPEG_ConfigInputBuffer(&jpeg_handle, (uint8_t *)jpeg_in_buf, jpeg_in_len);
} else if(jpeg_in_off < jpeg_in_len)
HAL_JPEG_ConfigInputBuffer(&jpeg_handle, (uint8_t *)jpeg_in_buf + jpeg_in_off, jpeg_in_len - jpeg_in_off);
}
void HAL_JPEG_DataReadyCallback(JPEG_HandleTypeDef *hjpeg, uint8_t *pDataOut, uint32_t OutDataLength) {
uint32_t conv_count;
jpeg_out_block += jpeg_conv_func(jpeg_dec_block, jpeg_out_buf, jpeg_out_block, OutDataLength, &conv_count);
}
blit::JPEGImage blit_decode_jpeg_buffer(const uint8_t *ptr, uint32_t len, blit::AllocateCallback alloc) {
if(!jpeg_tables_initialised) {
JPEG_InitColorTables();
jpeg_tables_initialised = true;
}
jpeg_alloc = alloc;
jpeg_in_buf = ptr;
jpeg_in_len = len;
jpeg_in_off = 0;
jpeg_in_file = nullptr;
jpeg_out_block = 0;
jpeg_handle.Instance = JPEG;
HAL_JPEG_Init(&jpeg_handle);
auto status = HAL_JPEG_Decode(&jpeg_handle, (uint8_t *)ptr, len, jpeg_dec_block, jpeg_max_block_len, 0xFFFFFFFF);
if(status != HAL_OK)
return {blit::Size(0, 0), nullptr};
JPEG_ConfTypeDef conf;
HAL_JPEG_GetInfo(&jpeg_handle, &conf);
HAL_JPEG_DeInit(&jpeg_handle);
return {blit::Size(conf.ImageWidth, conf.ImageHeight), jpeg_out_buf};
}
blit::JPEGImage blit_decode_jpeg_file(const std::string &filename, blit::AllocateCallback alloc) {
auto file = open_file(filename, blit::OpenMode::read);
if(!file)
return {};
jpeg_in_file = file;
if(!jpeg_tables_initialised) {
JPEG_InitColorTables();
jpeg_tables_initialised = true;
}
jpeg_alloc = alloc;
jpeg_in_buf = new uint8_t[1024];
jpeg_in_len = read_file(file, 0, 1024, (char *)jpeg_in_buf);
jpeg_in_off = 0;
jpeg_out_block = 0;
jpeg_handle.Instance = JPEG;
HAL_JPEG_Init(&jpeg_handle);
auto status = HAL_JPEG_Decode(&jpeg_handle, (uint8_t *)jpeg_in_buf, jpeg_in_len, jpeg_dec_block, jpeg_max_block_len, 0xFFFFFFFF);
if(status != HAL_OK)
return {blit::Size(0, 0), nullptr};
JPEG_ConfTypeDef conf;
HAL_JPEG_GetInfo(&jpeg_handle, &conf);
HAL_JPEG_DeInit(&jpeg_handle);
delete[] jpeg_in_buf;
close_file(file);
return {blit::Size(conf.ImageWidth, conf.ImageHeight), jpeg_out_buf};
}