1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

fix(qrcode):minimize margins as much as possible (#2804)

This commit is contained in:
guoweilkd 2021-11-22 16:53:21 +08:00 committed by GitHub
parent 3035d27d4a
commit 477abcf27a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 7 deletions

View File

@ -85,15 +85,32 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le
if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV;
uint8_t * qr0 = lv_mem_alloc(qrcodegen_BUFFER_LEN_MAX);
lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode);
int32_t qr_version = qrcodegen_getMinFitVersion(qrcodegen_Ecc_MEDIUM, data_len);
if (qr_version <= 0) return LV_RES_INV;
int32_t qr_size = qrcodegen_version2size(qr_version);
if (qr_size <= 0) return LV_RES_INV;
int32_t scale = imgdsc->header.w / qr_size;
if (scale <= 0) return LV_RES_INV;
int32_t remain = imgdsc->header.w % qr_size;
/* The qr version is incremented by four point */
uint32_t version_extend = remain / (scale << 2);
if (version_extend && qr_version < qrcodegen_VERSION_MAX) {
qr_version = qr_version + version_extend > qrcodegen_VERSION_MAX ?
qrcodegen_VERSION_MAX : qr_version + version_extend;
}
uint8_t * qr0 = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
LV_ASSERT_MALLOC(qr0);
uint8_t * data_tmp = lv_mem_alloc(qrcodegen_BUFFER_LEN_MAX);
uint8_t * data_tmp = lv_mem_alloc(qrcodegen_BUFFER_LEN_FOR_VERSION(qr_version));
LV_ASSERT_MALLOC(data_tmp);
memcpy(data_tmp, data, data_len);
bool ok = qrcodegen_encodeBinary(data_tmp, data_len,
qr0, qrcodegen_Ecc_MEDIUM,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
qr_version, qr_version,
qrcodegen_Mask_AUTO, true);
if (!ok) {
@ -102,11 +119,9 @@ lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_le
return LV_RES_INV;
}
lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode);
lv_coord_t obj_w = imgdsc->header.w;
int qr_size = qrcodegen_getSize(qr0);
int scale = obj_w / qr_size;
qr_size = qrcodegen_getSize(qr0);
scale = obj_w / qr_size;
int scaled = qr_size * scale;
int margin = (obj_w - scaled) / 2;
uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/

View File

@ -1007,3 +1007,28 @@ static int numCharCountBits(enum qrcodegen_Mode mode, int version) {
default: assert(false); return -1; // Dummy value
}
}
int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen)
{
struct qrcodegen_Segment seg;
seg.mode = qrcodegen_Mode_BYTE;
seg.bitLength = calcSegmentBitLength(seg.mode, dataLen);
seg.numChars = (int)dataLen;
for (int version = qrcodegen_VERSION_MIN; version <= qrcodegen_VERSION_MAX; version++) {
int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
int dataUsedBits = getTotalBits(&seg, 1, version);
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
return version;
}
return -1;
}
int qrcodegen_version2size(int version)
{
if (version < qrcodegen_VERSION_MIN || version > qrcodegen_VERSION_MAX) {
return -1;
}
return ((version - 1)*4 + 21);
}

View File

@ -305,6 +305,14 @@ int qrcodegen_getSize(const uint8_t qrcode[]);
*/
bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y);
/*
* Returns the qrcode size of the specified version. Returns -1 on failure
*/
int qrcodegen_version2size(int version);
/*
* Returns the min version of the data that can be stored. Returns -1 on failure
*/
int qrcodegen_getMinFitVersion(enum qrcodegen_Ecc ecl, size_t dataLen);
#ifdef __cplusplus
}