luat_lib_lcd_jpg.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. @module lcd
  3. @summary lcd驱动模块
  4. @version 1.0
  5. @date 2021.06.16
  6. @demo lcd
  7. @tag LUAT_USE_LCD
  8. */
  9. #include "luat_base.h"
  10. #include "luat_lcd.h"
  11. #include "luat_mem.h"
  12. #include "luat_zbuff.h"
  13. #include "luat_fs.h"
  14. #include "luat_gpio.h"
  15. #define LUAT_LOG_TAG "lcd"
  16. #include "luat_log.h"
  17. #include "u8g2.h"
  18. #include "u8g2_luat_fonts.h"
  19. #include "luat_u8g2.h"
  20. #include "qrcodegen.h"
  21. extern luat_color_t BACK_COLOR , FORE_COLOR ;
  22. extern luat_lcd_conf_t *lcd_dft_conf;
  23. extern void lcd_auto_flush(luat_lcd_conf_t *conf);
  24. #ifdef LUAT_USE_TJPGD
  25. #include "tjpgd.h"
  26. #include "tjpgdcnf.h"
  27. #define N_BPP (3 - JD_FORMAT)
  28. /* Session identifier for input/output functions (name, members and usage are as user defined) */
  29. typedef struct {
  30. FILE *fp; /* Input stream */
  31. int x;
  32. int y;
  33. // int width;
  34. // int height;
  35. uint16_t buff[16*16];
  36. } IODEV;
  37. static unsigned int file_in_func (JDEC* jd, uint8_t* buff, unsigned int nbyte){
  38. IODEV *dev = (IODEV*)jd->device; /* Device identifier for the session (5th argument of luat_jd_prepare function) */
  39. if (buff) {
  40. /* Read bytes from input stream */
  41. return luat_fs_fread(buff, 1, nbyte, dev->fp);
  42. } else {
  43. /* Remove bytes from input stream */
  44. return luat_fs_fseek(dev->fp, nbyte, SEEK_CUR) ? 0 : nbyte;
  45. }
  46. }
  47. static int lcd_out_func (JDEC* jd, void* bitmap, JRECT* rect){
  48. IODEV *dev = (IODEV*)jd->device;
  49. uint16_t* tmp = (uint16_t*)bitmap;
  50. // rgb高低位swap
  51. uint16_t count = (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1);
  52. for (size_t i = 0; i < count; i++){
  53. if (lcd_dft_conf->endianness_swap)
  54. dev->buff[i] = ((tmp[i] >> 8) & 0xFF)+ ((tmp[i] << 8) & 0xFF00);
  55. else
  56. dev->buff[i] = tmp[i];
  57. }
  58. // LLOGD("jpeg seg %dx%d %dx%d", rect->left, rect->top, rect->right, rect->bottom);
  59. // LLOGD("jpeg seg size %d %d %d", rect->right - rect->left + 1, rect->bottom - rect->top + 1, (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1));
  60. luat_lcd_draw(lcd_dft_conf, dev->x + rect->left, dev->y + rect->top,
  61. dev->x + rect->right, dev->y + rect->bottom,
  62. dev->buff);
  63. return 1; /* Continue to decompress */
  64. }
  65. int lcd_draw_jpeg_default(luat_lcd_conf_t* conf, const char* path, int16_t x, int16_t y){
  66. JRESULT res; /* Result code of TJpgDec API */
  67. JDEC jdec; /* Decompression object */
  68. void *work; /* Pointer to the decompressor work area */
  69. #if JD_FASTDECODE == 2
  70. size_t sz_work = 3500 * 3; /* Size of work area */
  71. #else
  72. size_t sz_work = 3500; /* Size of work area */
  73. #endif
  74. IODEV devid; /* User defined device identifier */
  75. FILE* fd = luat_fs_fopen(path, "rb");
  76. if (fd == NULL) {
  77. LLOGW("no such file %s", path);
  78. return -1;
  79. }
  80. devid.fp = fd;
  81. work = luat_heap_malloc(sz_work);
  82. if (work == NULL) {
  83. LLOGE("out of memory when malloc jpeg decode workbuff");
  84. return -3;
  85. }
  86. res = luat_jd_prepare(&jdec, file_in_func, work, sz_work, &devid);
  87. if (res != JDR_OK) {
  88. luat_heap_free(work);
  89. luat_fs_fclose(fd);
  90. LLOGW("luat_jd_prepare file %s error %d", path, res);
  91. return -2;
  92. }
  93. devid.x = x;
  94. devid.y = y;
  95. // devid.width = jdec.width;
  96. // devid.height = jdec.height;
  97. res = luat_jd_decomp(&jdec, lcd_out_func, 0);
  98. luat_heap_free(work);
  99. luat_fs_fclose(fd);
  100. if (res != JDR_OK) {
  101. LLOGW("luat_jd_decomp file %s error %d", path, res);
  102. return -2;
  103. }else {
  104. lcd_auto_flush(lcd_dft_conf);
  105. return 0;
  106. }
  107. }
  108. static unsigned int decode_file_in_func (JDEC* jd, uint8_t* buff, unsigned int nbyte){
  109. luat_lcd_buff_info_t *buff_info = (luat_lcd_buff_info_t*)jd->device; /* Device identifier for the session (5th argument of luat_jd_prepare function) */
  110. if (buff) {
  111. /* Read bytes from input stream */
  112. return luat_fs_fread(buff, 1, nbyte, (FILE*)(buff_info->userdata));
  113. } else {
  114. /* Remove bytes from input stream */
  115. return luat_fs_fseek((FILE*)(buff_info->userdata), nbyte, SEEK_CUR) ? 0 : nbyte;
  116. }
  117. }
  118. static int decode_out_func (JDEC* jd, void* bitmap, JRECT* rect){
  119. luat_lcd_buff_info_t *buff_info = (luat_lcd_buff_info_t*)jd->device;
  120. uint16_t* tmp = (uint16_t*)bitmap;
  121. // rgb高低位swap
  122. uint16_t idx = 0;
  123. for (size_t y = rect->top; y <= rect->bottom; y++){
  124. // 防止大图时 y*width 溢出 16bit,改用 size_t 计算偏移
  125. size_t offset = (size_t)y * buff_info->width + rect->left;
  126. for (size_t x = rect->left; x <= rect->right; x++){
  127. if (lcd_dft_conf->endianness_swap)
  128. buff_info->buff[offset] = ((tmp[idx] >> 8) & 0xFF)+ ((tmp[idx] << 8) & 0xFF00);
  129. else
  130. buff_info->buff[offset] = tmp[idx];
  131. offset++;idx++;
  132. }
  133. }
  134. // LLOGD("jpeg seg %dx%d %dx%d", rect->left, rect->top, rect->right, rect->bottom);
  135. // LLOGD("jpeg seg size %d %d %d", rect->right - rect->left + 1, rect->bottom - rect->top + 1, (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1));
  136. return 1; /* Continue to decompress */
  137. }
  138. int lcd_jpeg_decode_default(luat_lcd_conf_t* conf, const char* path, luat_lcd_buff_info_t* buff_info){
  139. JRESULT res; /* Result code of TJpgDec API */
  140. JDEC jdec; /* Decompression object */
  141. void *work = NULL; /* Pointer to the decompressor work area */
  142. #if JD_FASTDECODE == 2
  143. size_t sz_work = 3500 * 3; /* Size of work area */
  144. #else
  145. size_t sz_work = 3500; /* Size of work area */
  146. #endif
  147. FILE* fd = luat_fs_fopen(path, "rb");
  148. if (fd == NULL) {
  149. LLOGW("no such file %s", path);
  150. goto error;
  151. }
  152. buff_info->userdata = fd;
  153. work = luat_heap_malloc(sz_work);
  154. if (work == NULL) {
  155. LLOGE("out of memory when malloc jpeg decode workbuff");
  156. goto error;
  157. }
  158. res = luat_jd_prepare(&jdec, decode_file_in_func, work, sz_work, buff_info);
  159. if (res != JDR_OK) {
  160. LLOGW("luat_jd_prepare file %s error %d", path, res);
  161. goto error;
  162. }
  163. buff_info->width = jdec.width;
  164. buff_info->height = jdec.height;
  165. buff_info->len = jdec.width*jdec.height*sizeof(luat_color_t);
  166. buff_info->buff = luat_heap_malloc(buff_info->len);
  167. res = luat_jd_decomp(&jdec, decode_out_func, 0);
  168. if (res != JDR_OK) {
  169. LLOGW("luat_jd_decomp file %s error %d", path, res);
  170. goto error;
  171. }
  172. luat_heap_free(work);
  173. luat_fs_fclose(fd);
  174. return 0;
  175. error:
  176. if (work){
  177. luat_heap_free(work);
  178. }
  179. if (fd){
  180. luat_fs_fclose(fd);
  181. }
  182. return -1;
  183. }
  184. LUAT_WEAK int lcd_draw_jpeg(luat_lcd_conf_t* conf, const char* path, int16_t x, int16_t y){
  185. return lcd_draw_jpeg_default(conf, path, x, y);
  186. }
  187. LUAT_WEAK int lcd_jpeg_decode(luat_lcd_conf_t* conf, const char* path, luat_lcd_buff_info_t* buff_info){
  188. return lcd_jpeg_decode_default(conf, path, buff_info);
  189. }
  190. #endif