lcd_qrcode.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rtconfig.h>
  10. #ifdef BSP_USING_LCD_QRCODE
  11. #include <qrcode.h>
  12. #include "drv_lcd.h"
  13. #include "lcd_qrcode.h"
  14. #define DBG_TAG "drv.lcd.qrcode"
  15. #define DBG_LVL DBG_INFO
  16. #include <rtdbg.h>
  17. static QRCode qrcode;
  18. static rt_uint8_t get_enlargement_factor(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size)
  19. {
  20. rt_uint8_t enlargement_factor = 1 ;
  21. if (x + size * 8 <= LCD_W && y + size * 8 <= LCD_H)
  22. {
  23. enlargement_factor = 8;
  24. }
  25. else if (x + size * 4 <= LCD_W &&y + size * 4 <= LCD_H)
  26. {
  27. enlargement_factor = 4;
  28. }
  29. else if (x + size * 2 <= LCD_W && y + size * 2 <= LCD_H)
  30. {
  31. enlargement_factor = 2;
  32. }
  33. return enlargement_factor;
  34. }
  35. static void show_qrcode_by_point(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor)
  36. {
  37. rt_uint32_t width = 0, high = 0;
  38. for (high = 0; high < size; high++)
  39. {
  40. for (width = 0; width < size; width++)
  41. {
  42. if (qrcode_getModule(&qrcode, width, high))
  43. {
  44. /* magnify pixel */
  45. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  46. {
  47. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  48. {
  49. lcd_draw_point(x + enlargement_factor * width + offset_x, y + enlargement_factor * high + offset_y);
  50. }
  51. }
  52. }
  53. }
  54. }
  55. }
  56. static void show_qrcode_by_line(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor,rt_uint8_t *qrcode_buf)
  57. {
  58. rt_uint32_t width = 0, high = 0;
  59. for (high = 0; high < qrcode.size; high++)
  60. {
  61. for (width = 0; width < qrcode.size; width++)
  62. {
  63. if (qrcode_getModule(&qrcode, width, high))
  64. {
  65. /* magnify pixel */
  66. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  67. {
  68. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  69. {
  70. /* save the information of modules */
  71. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = FORE_COLOR >> 8;
  72. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = FORE_COLOR;
  73. }
  74. }
  75. }
  76. else
  77. {
  78. /* magnify pixel */
  79. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  80. {
  81. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  82. {
  83. /* save the information of blank */
  84. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = BACK_COLOR >> 8;
  85. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = BACK_COLOR;
  86. }
  87. }
  88. }
  89. }
  90. /* display a line of qrcode */
  91. lcd_show_image(x, y + high * enlargement_factor, qrcode.size * enlargement_factor, enlargement_factor, qrcode_buf);
  92. }
  93. }
  94. /**
  95. * display the qrcode on the lcd.
  96. * size = (4 * version +17) * enlargement
  97. *
  98. * @param x x position
  99. * @param y y position
  100. * @param version version of qrcode (ECC_LOW, ECC_MEDIUM, ECC_QUARTILE or ECC_HIGH)
  101. * @param ecc level of error correction
  102. * @param data string
  103. * @param enlargement enlargement_factor
  104. *
  105. * @return 0: display success
  106. * -1: generate qrcode failed
  107. * -5: memory low
  108. */
  109. rt_err_t lcd_show_qrcode(rt_uint16_t x, rt_uint16_t y, rt_uint8_t version, rt_uint8_t ecc, const char *data, rt_uint8_t enlargement)
  110. {
  111. RT_ASSERT(data);
  112. rt_int8_t result = 0;
  113. rt_uint8_t enlargement_factor = 1;
  114. rt_uint8_t *qrcode_buf = RT_NULL;
  115. if (x + version * 4 + 17 > LCD_W || y + version * 4 + 17 > LCD_H)
  116. {
  117. LOG_E("The qrcode is too big!");
  118. return -RT_ERROR;
  119. }
  120. rt_uint8_t *qrcodeBytes = (rt_uint8_t *)rt_calloc(1, qrcode_getBufferSize(version));
  121. if (qrcodeBytes == RT_NULL)
  122. {
  123. LOG_E("no memory for qrcode!");
  124. return -RT_ENOMEM;
  125. }
  126. /* generate qrcode */
  127. result = qrcode_initText(&qrcode, qrcodeBytes, version, ecc, data);
  128. if (result >= 0)
  129. {
  130. /* set enlargement factor */
  131. if(enlargement == 0)
  132. {
  133. enlargement_factor = get_enlargement_factor(x, y, qrcode.size);
  134. }
  135. else
  136. {
  137. enlargement_factor = enlargement;
  138. }
  139. /* malloc memory for quick display of qrcode */
  140. qrcode_buf = rt_malloc(qrcode.size * 2 * enlargement_factor * enlargement_factor);
  141. if (qrcode_buf == RT_NULL)
  142. {
  143. /* clear lcd */
  144. lcd_fill(x, y, x + qrcode.size, y + qrcode.size, BACK_COLOR);
  145. /* draw point to display qrcode */
  146. show_qrcode_by_point(x, y, qrcode.size, enlargement_factor);
  147. }
  148. else
  149. {
  150. /* quick display of qrcode */
  151. show_qrcode_by_line(x, y, qrcode.size, enlargement_factor,qrcode_buf);
  152. }
  153. result = RT_EOK;
  154. }
  155. else
  156. {
  157. LOG_E("QRCODE(%s) generate falied(%d)\n", data, result);
  158. result = -RT_ENOMEM;
  159. goto __exit;
  160. }
  161. __exit:
  162. if (qrcodeBytes)
  163. {
  164. rt_free(qrcodeBytes);
  165. }
  166. if (qrcode_buf)
  167. {
  168. rt_free(qrcode_buf);
  169. }
  170. return result;
  171. }
  172. #endif /* BSP_USING_LCD_QRCODE */