具体分析如下代码
jpg解码
#include "lv_jpg_decode.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "../include/jpeg/jpeglib.h"
#include <setjmp.h>
#include "../../../include/anyka37d/ak_common_graphics.h"
#include "../../../include/anyka37d/ak_mem.h"
#include "../../../include/anyka37d/ak_tde.h"
struct my_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr *my_error_ptr;
static void my_error_exit(j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr)cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message)(cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
/***
** 日期:2022-07-01 13:50:29
** 作者: leo.liu
** 函数作用:获取解码的数据
** 参数说明:
***/
bool lv_jpg_decode_data(const char *file, rom_bin_info *info, int dst_w, int dst_h)
{
FILE *jpeg_fd = fopen(file, "rb");
if (jpeg_fd == NULL)
{
printf("jpg decode :open %s failed \n", file);
return false;
}
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
/* Step 1: allocate and initialize JPEG decompression object */
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress(&cinfo);
fclose(jpeg_fd);
return false;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src(&cinfo, jpeg_fd);
/* Step 3: read file parameters with jpeg_read_header() */
(void)jpeg_read_header(&cinfo, TRUE);
/* Step 4: set parameters for decompression */
cinfo.out_color_space = JCS_RGB;
if ((dst_w * dst_h) < (cinfo.image_width * cinfo.image_height))
{
if (((abs(dst_w - cinfo.image_width)) < (abs(dst_h - cinfo.image_height))) && (dst_h < cinfo.image_height))
{
cinfo.scale_num = dst_h;
cinfo.scale_denom = cinfo.image_height;
}
else
{
cinfo.scale_num = dst_h;
cinfo.scale_denom = cinfo.image_width;
}
}
/* Step 5: Start decompressor */
(void)jpeg_start_decompress(&cinfo);
printf("image_width = %d out_wdith=%d\n", cinfo.image_width, cinfo.output_width);
printf("image_height = %d out_hegiht=%d\n", cinfo.image_height, cinfo.output_height);
printf("num_components = %d\n", cinfo.num_components);
/* JSAMPLEs per row in output buffer */
int row_stride = cinfo.output_width * cinfo.output_components;
/* Make a one-row-high sample array that will go away when done with image */
unsigned char *jpeg_raw_data = (unsigned char *)ak_mem_dma_alloc(MODULE_ID_GUI, cinfo.output_height * row_stride);
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);
while (cinfo.output_scanline < cinfo.output_height)
{
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void)jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(&jpeg_raw_data[cinfo.output_scanline * row_stride], buffer[0], row_stride);
/* Assume put_scanline_someplace wants a pointer and sample count. */
}
struct ak_tde_layer src, dst;
src.format_param = GP_FORMAT_RGB888;
src.pos_width = src.width = cinfo.output_width;
src.pos_height = src.height = cinfo.output_height;
src.pos_left = src.pos_top = 0;
ak_mem_dma_vaddr2paddr(jpeg_raw_data, (unsigned long *)&src.phyaddr);
#if LV_COLOR_DEPTH == 32
dst.format_param = GP_FORMAT_BGR888;
#elif LV_COLOR_DEPTH == 16
dst.format_param = GP_FORMAT_BGR565;
#endif
dst.pos_width = dst.width = dst_w;
dst.pos_height = dst.height = dst_h;
dst.pos_left = dst.pos_top = 0;
unsigned char *data = (unsigned char *)info->offset;
ak_mem_dma_vaddr2paddr(data, (unsigned long *)&dst.phyaddr);
ak_tde_opt_scale(&src, &dst);
ak_mem_dma_free(jpeg_raw_data);
#if LV_COLOR_DEPTH == 32
int len = dst_w * dst_h;
unsigned char *dst_data = data + dst_w * dst_h * 4 - 1;
unsigned char *src_data = data + dst_w * dst_h * 3 - 1;
for (int i = 0; i < len; i++)
{
*dst_data = 0xFF;
dst_data--;
*dst_data = *src_data;
dst_data--;
src_data--;
*dst_data = *src_data;
dst_data--;
src_data--;
*dst_data = *src_data;
dst_data--;
src_data--;
}
#endif
/* Step 7: Finish decompression */
(void)jpeg_finish_decompress(&cinfo);
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&cinfo);
fclose(jpeg_fd);
return true;
}
二维码使用
/**
* @file lv_qrcode.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lvgl/drive/lv_qrcode.h"
#include "lvgl/drive/qrcodegen.h"
/*********************
* DEFINES
*********************/
#define QR_SIZE 140
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create an empty QR code (an `lv_canvas`) object.
* @param parent point to an object where to create the QR code
* @param size width and height of the QR code
* @param dark_color dark color of the QR code
* @param light_color light color of the QR code
* @return pointer to the created QR code object
*/
lv_obj_t *lv_qrcode_create(lv_obj_t *parent, void *data, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color)
{
lv_obj_t *canvas = lv_canvas_create(parent, NULL);
if (canvas == NULL)
return NULL;
lv_img_set_src(canvas, data);
lv_img_dsc_t *imgdsc = lv_canvas_get_img(canvas);
imgdsc->header.cf = LV_IMG_CF_RAW;
imgdsc->header.w = size;
imgdsc->header.h = size;
rom_bin_info *img = (rom_bin_info *)(data);
imgdsc->data = ((unsigned char *)img->offset);
lv_canvas_set_palette(canvas, 0, dark_color);
lv_canvas_set_palette(canvas, 1, light_color);
return canvas;
}
/**
* Set the data of a QR code object
* @param qrcode pointer to aQ code object
* @param data data to display
* @param data_len length of data in bytes
* @return LV_RES_OK: if no error; LV_RES_INV: on error
*/
lv_res_t lv_qrcode_update(lv_obj_t *qrcode, const void *data, uint32_t data_len)
{
lv_color_t c;
c.full = 1;
lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER);
if (data_len > qrcodegen_BUFFER_LEN_MAX)
return LV_RES_INV;
uint8_t qr0[qrcodegen_BUFFER_LEN_MAX];
uint8_t data_tmp[qrcodegen_BUFFER_LEN_MAX];
memcpy(data_tmp, data, data_len);
bool ok = qrcodegen_encodeBinary(data_tmp, data_len,
qr0, qrcodegen_Ecc_MEDIUM,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
qrcodegen_Mask_AUTO, true);
if (!ok)
return LV_RES_INV;
lv_img_ext_t *imgdsc = lv_obj_get_ext_attr(qrcode);
lv_coord_t obj_w = imgdsc->w;
int qr_size = qrcodegen_getSize(qr0);
int scale = obj_w / qr_size;
int scaled = qr_size * scale;
int margin = (obj_w - scaled) / 2;
rom_bin_info *img = (rom_bin_info *)(imgdsc->src);
unsigned char *buf_u8 = ((unsigned char *)img->offset);
int raw_byte = LV_COLOR_SIZE / 8;
uint32_t row_byte_cnt = obj_w * raw_byte;
lv_color32_t d_c32;
lv_color32_t l_c32;
_lv_memcpy_small(&d_c32, &buf_u8[0 * sizeof(d_c32)], sizeof(d_c32));
lv_color_t d_color = lv_color_hex(d_c32.full);
_lv_memcpy_small(&l_c32, &buf_u8[1 * sizeof(l_c32)], sizeof(l_c32));
lv_color_t l_color = lv_color_hex(l_c32.full);
//_lv_memcpy_small(buf_u8, &(d_color.full), raw_byte);
for (int y = 0; y < obj_w; y++)
{
for (int x = 0; x < obj_w; x++)
{
bool a = qrcodegen_getModule(qr0, (x - margin) / scale, (y - margin) / scale);
if (a == false)
{
_lv_memcpy_small(&buf_u8[y * row_byte_cnt + x * raw_byte], &(l_color.full), raw_byte);
}
else
{
_lv_memcpy_small(&buf_u8[y * row_byte_cnt + x * raw_byte], &(d_color.full), raw_byte);
}
}
}
lv_obj_invalidate(qrcode);
return LV_RES_OK;
}
/**
* Delete a QR code object
* @param qrcode pointer to a QR code obejct
*/
void lv_qrcode_delete(lv_obj_t *qrcode)
{
lv_img_dsc_t *img = lv_canvas_get_img(qrcode);
lv_img_cache_invalidate_src(img);
// lv_mem_free(img->data);
lv_obj_del(qrcode);
}