120 lines
2.9 KiB
C
120 lines
2.9 KiB
C
#define TJE_IMPLEMENTATION
|
|
#include "tiny_jpeg.h"
|
|
#include "sysheap.h"
|
|
|
|
#include "lisa_log.h"
|
|
|
|
#define TAG "img_helper"
|
|
|
|
struct jpeg_write_context {
|
|
uint8_t *buf;
|
|
uint32_t total_size;
|
|
uint32_t wrote;
|
|
};
|
|
|
|
static void jpeg_write(void *context, void *data, int size)
|
|
{
|
|
struct jpeg_write_context *ctx = (struct jpeg_write_context *)context;
|
|
if (ctx == NULL) {
|
|
return;
|
|
}
|
|
|
|
uint32_t can_write = ctx->total_size - ctx->wrote;
|
|
can_write = can_write >= size ? size : can_write;
|
|
|
|
memcpy(ctx->buf + ctx->wrote, data, can_write);
|
|
ctx->wrote += can_write;
|
|
}
|
|
|
|
int img_helper_rgb888_to_jpeg(const uint8_t *rgb_data, uint32_t width, uint32_t height, uint8_t **jpeg_data, uint32_t *jpeg_len)
|
|
{
|
|
if (!rgb_data || !jpeg_data || !jpeg_len || width == 0 || height == 0) {
|
|
return -1;
|
|
}
|
|
|
|
uint32_t jpeg_buf_size = width * height * 3 / 5;
|
|
if (jpeg_buf_size < 1024) {
|
|
jpeg_buf_size = 1024;
|
|
}
|
|
|
|
uint8_t *jpeg_buf = psram_malloc(jpeg_buf_size);
|
|
if (!jpeg_buf) {
|
|
LOGE("failed to allocate JPEG buffer");
|
|
return -1;
|
|
}
|
|
|
|
struct jpeg_write_context jpeg_write_ctx = {
|
|
.buf = jpeg_buf,
|
|
.total_size = jpeg_buf_size,
|
|
.wrote = 0,
|
|
};
|
|
|
|
int result = tje_encode_with_func(jpeg_write, &jpeg_write_ctx, 1, width, height, 3, rgb_data);
|
|
if (result == 0) {
|
|
LOGE("JPEG encoding failed");
|
|
psram_free(jpeg_buf);
|
|
return -1;
|
|
}
|
|
|
|
*jpeg_data = jpeg_buf;
|
|
*jpeg_len = jpeg_write_ctx.wrote;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void img_helper_rgb565_to_rgb888(const uint16_t *rgb565, uint8_t *rgb888, uint32_t width, uint32_t height)
|
|
{
|
|
uint32_t pixel_count = width * height;
|
|
|
|
for (uint32_t i = 0; i < pixel_count; i++) {
|
|
uint16_t pixel = rgb565[i];
|
|
|
|
uint8_t r5 = (pixel >> 11) & 0x1F;
|
|
uint8_t g6 = (pixel >> 5) & 0x3F;
|
|
uint8_t b5 = pixel & 0x1F;
|
|
|
|
rgb888[i * 3 + 0] = (r5 * 255 + 15) / 31;
|
|
rgb888[i * 3 + 1] = (g6 * 255 + 31) / 63;
|
|
rgb888[i * 3 + 2] = (b5 * 255 + 15) / 31;
|
|
}
|
|
}
|
|
|
|
int img_helper_rgb565_to_jpeg(uint8_t *rgb565, uint32_t len, int width, int height, uint8_t **jpeg_data, uint32_t *jpeg_len)
|
|
{
|
|
if (!rgb565 || !jpeg_data || !jpeg_len || width <= 0 || height <= 0) {
|
|
LOGE("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
uint32_t pixel_count = len / 2;
|
|
uint8_t *rgb888 = psram_malloc(pixel_count * 3);
|
|
if (!rgb888) {
|
|
LOGE("Failed to allocate RGB888 buffer");
|
|
return -1;
|
|
}
|
|
|
|
img_helper_rgb565_to_rgb888((const uint16_t *)rgb565, rgb888, width, height);
|
|
|
|
uint8_t *jpeg_buf = NULL;
|
|
uint32_t jpeg_size = 0;
|
|
int ret = img_helper_rgb888_to_jpeg(rgb888, width, height, &jpeg_buf, &jpeg_size);
|
|
psram_free(rgb888);
|
|
|
|
if (ret != 0) {
|
|
LOGE("Failed to encode JPEG");
|
|
return -1;
|
|
}
|
|
|
|
*jpeg_data = jpeg_buf;
|
|
*jpeg_len = jpeg_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void img_helper_jpeg_free(void *jpeg)
|
|
{
|
|
if (jpeg) {
|
|
psram_free(jpeg);
|
|
}
|
|
}
|