Browse Source

add: 添加lcd.image2raw函数
add:lcd.draw支持zbuff绘制
del:lcd.draw删除number类型支持

Dozingfiretruck 7 tháng trước cách đây
mục cha
commit
040a5cd361
3 tập tin đã thay đổi với 171 bổ sung38 xóa
  1. 13 2
      components/lcd/luat_lcd.h
  2. 71 36
      components/lcd/luat_lib_lcd.c
  3. 87 0
      components/lcd/luat_lib_lcd_jpg.c

+ 13 - 2
components/lcd/luat_lcd.h

@@ -113,6 +113,15 @@ typedef struct luat_lcd_conf {
     u8g2_t luat_lcd_u8g2 ;
 } luat_lcd_conf_t;
 
+typedef struct luat_lcd_buff_info {
+	luat_color_t * buff;
+    size_t len;
+    uint32_t width;
+    uint32_t height;
+	// size_t offset;
+	void* userdata;
+}luat_lcd_buff_info_t;
+
 typedef struct luat_lcd_opts {
     const char* name;
     uint8_t sleep_cmd;
@@ -193,9 +202,11 @@ int luat_lcd_draw_hline(luat_lcd_conf_t* conf, int16_t x, int16_t y,int16_t h, l
 int luat_lcd_draw_rectangle(luat_lcd_conf_t* conf, int16_t x1, int16_t y1, int16_t x2, int16_t y2, luat_color_t color);
 int luat_lcd_draw_circle(luat_lcd_conf_t* conf, int16_t x0, int16_t y0, uint8_t r, luat_color_t color);
 int luat_lcd_set_direction(luat_lcd_conf_t* conf, uint8_t direction);
-#ifdef LUAT_USE_TJPGD
+
+// weak函数 可bsp单独适配硬件加速实现
 int lcd_draw_jpeg(luat_lcd_conf_t* conf, const char* path, int16_t x, int16_t y);
-#endif
+int lcd_jpeg_decode(luat_lcd_conf_t* conf, const char* path, luat_lcd_buff_info_t* buff_info);
+
 /*
  * csdk适配用
  */

+ 71 - 36
components/lcd/luat_lib_lcd.c

@@ -625,35 +625,35 @@ lcd.draw(20,30,220,30,buff)
 static int l_lcd_draw(lua_State* L) {
     int16_t x1, y1, x2, y2;
     int ret;
-    // luat_color_t *color = NULL;
-    luat_zbuff_t *buff;
+    luat_color_t *color = NULL;
+    
     x1 = luaL_checkinteger(L, 1);
     y1 = luaL_checkinteger(L, 2);
-    x2 = luaL_checkinteger(L, 3);
-    y2 = luaL_checkinteger(L, 4);
     if (lcd_dft_conf == NULL) {
       LLOGE("lcd not init");
       return 0;
     }
-    if (lua_isinteger(L, 5)) {
-        // color = (luat_color_t *)luaL_checkstring(L, 5);
-        luat_color_t color = (luat_color_t)luaL_checkinteger(L, 1);
-        ret = luat_lcd_draw(lcd_dft_conf, x1, y1, x2, y2, &color);
-    }
-    else if (lua_isuserdata(L, 5)) {
-        buff = luaL_checkudata(L, 5, LUAT_ZBUFF_TYPE);
-        luat_color_t *color = (luat_color_t *)buff->addr;
-        ret = luat_lcd_draw(lcd_dft_conf, x1, y1, x2, y2, color);
+    if (lua_isuserdata(L, 5)) {
+        luat_zbuff_t *zbuff = luaL_checkudata(L, 5, LUAT_ZBUFF_TYPE);
+		if (zbuff->width && zbuff->height){
+			x2 = x1+zbuff->width-1;
+			y2 = y1+zbuff->height-1;
+		}else{
+			x2 = luaL_checkinteger(L, 3);
+			y2 = luaL_checkinteger(L, 4);
+		}
+        color = (luat_color_t *)zbuff->addr;
     }
     else if(lua_isstring(L, 5)) {
-        luat_color_t *color = (luat_color_t *)luaL_checkstring(L, 5);
-        ret = luat_lcd_draw(lcd_dft_conf, x1, y1, x2, y2, color);
+		x2 = luaL_checkinteger(L, 3);
+		y2 = luaL_checkinteger(L, 4);
+        color = (luat_color_t *)luaL_checkstring(L, 5);
     }
     else {
         return 0;
     }
+    ret = luat_lcd_draw(lcd_dft_conf, x1, y1, x2, y2, color);
     lcd_auto_flush(lcd_dft_conf);
-    // int ret = luat_lcd_draw(lcd_dft_conf, x1, y1, x2, y2, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 1;
 }
@@ -1464,24 +1464,24 @@ static int l_lcd_drawxbm(lua_State *L){
     if (len != h*w1)return 0;
     
     if (lcd_dft_conf == NULL) {
-      LLOGE("lcd not init");
-      return 0;
+        LLOGE("lcd not init");
+        return 0;
     }
     luat_color_t* color_w = luat_heap_malloc(sizeof(luat_color_t) * w);
     for (size_t b = 0; b < h; b++){
-      size_t a = 0;
-      while (a < w){
-        for (size_t c = 0; c < 8; c++){
-          if (*data&(mask<<c)){
-            color_w[a]=FORE_COLOR;
-          }else{
-            color_w[a]=BACK_COLOR;
-          }
-          a++;
-          if (a == w)break;
+        size_t a = 0;
+        while (a < w){
+            for (size_t c = 0; c < 8; c++){
+                if (*data&(mask<<c)){
+                    color_w[a]=FORE_COLOR;
+                }else{
+                    color_w[a]=BACK_COLOR;
+                }
+                a++;
+                if (a == w)break;
+            }
+            data++;
         }
-        data++;
-      }
       luat_lcd_draw(lcd_dft_conf, x, y+b, x+w-1, y+b, color_w);
     }
     luat_heap_free(color_w);
@@ -1502,8 +1502,8 @@ lcd.showImage(0,0,"/luadb/logo.jpg")
 */
 int l_lcd_showimage(lua_State *L) {
     if (lcd_dft_conf == NULL) {
-      LLOGE("lcd not init");
-      return 0;
+        LLOGE("lcd not init");
+        return 0;
     }
     size_t size = 0;
     int ret = 0;
@@ -1511,14 +1511,48 @@ int l_lcd_showimage(lua_State *L) {
     int y = luaL_checkinteger(L, 2);
     const char* input_file = luaL_checklstring(L, 3, &size);
     if (memcmp(input_file+size-4, ".jpg", 5) == 0 || memcmp(input_file+size-4, ".JPG", 5) == 0 || memcmp(input_file+size-5, ".jpeg", 6) == 0 || memcmp(input_file+size-5, ".JPEG", 6) == 0){
-      ret = lcd_draw_jpeg(lcd_dft_conf, input_file, x, y);
-      lua_pushboolean(L, ret == 0 ? 1 : 0);
+        ret = lcd_draw_jpeg(lcd_dft_conf, input_file, x, y);
+        lua_pushboolean(L, ret == 0 ? 1 : 0);
     } else{
-      LLOGE("input_file not support");
-      lua_pushboolean(L, 0);
+        LLOGE("input_file not support");
+        lua_pushboolean(L, 0);
     }
     return 1;
 }
+
+int l_lcd_image2raw(lua_State *L) {
+    if (lcd_dft_conf == NULL) {
+        LLOGE("lcd not init");
+        return 0;
+    }
+    size_t size = 0;
+    int ret = 0;
+    luat_lcd_buff_info_t buff_info = {0};
+    const char* input_file = luaL_checklstring(L, 1, &size);
+    if (memcmp(input_file+size-4, ".jpg", 5) == 0 || memcmp(input_file+size-4, ".JPG", 5) == 0 || memcmp(input_file+size-5, ".jpeg", 6) == 0 || memcmp(input_file+size-5, ".JPEG", 6) == 0){
+        ret = lcd_jpeg_decode(lcd_dft_conf, input_file, &buff_info);
+        if(ret){
+            goto error;
+        }
+    } else{
+        LLOGE("input_file not support");
+        lua_pushboolean(L, 0);
+        return 1;
+    }
+    luat_zbuff_t *zbuff = (luat_zbuff_t *)lua_newuserdata(L, sizeof(luat_zbuff_t));
+	memset(zbuff,0,sizeof(luat_zbuff_t));
+    zbuff->addr = buff_info.buff;
+	zbuff->len = buff_info.len;
+	zbuff->width = buff_info.width;
+	zbuff->height = buff_info.height;
+	zbuff->bit = LUAT_LCD_COLOR_DEPTH;
+	// LLOGD("addr:%p len:%d width:%d height:%d bit:%d ",zbuff->addr,zbuff->len,zbuff->width,zbuff->height,zbuff->bit);
+	luaL_setmetatable(L, LUAT_ZBUFF_TYPE);
+    return 1;
+error:
+    return 0;
+}
+
 #endif
 
 /*
@@ -1890,6 +1924,7 @@ static const rotable_Reg_t reg_lcd[] =
     { "drawUTF8",   ROREG_FUNC(l_lcd_draw_utf8)},
 #endif
 #ifdef LUAT_USE_TJPGD
+    { "image2raw",    ROREG_FUNC(l_lcd_image2raw)},
     { "showImage",    ROREG_FUNC(l_lcd_showimage)},
 #endif
 #ifdef LUAT_USE_GTFONT

+ 87 - 0
components/lcd/luat_lib_lcd_jpg.c

@@ -122,4 +122,91 @@ LUAT_WEAK int lcd_draw_jpeg(luat_lcd_conf_t* conf, const char* path, int16_t x,
     }
 }
 
+static unsigned int decode_file_in_func (JDEC* jd, uint8_t* buff, unsigned int nbyte){
+    luat_lcd_buff_info_t *buff_info = (luat_lcd_buff_info_t*)jd->device;   /* Device identifier for the session (5th argument of jd_prepare function) */
+    if (buff) {
+        /* Read bytes from input stream */
+        return luat_fs_fread(buff, 1, nbyte, (FILE*)(buff_info->userdata));
+    } else {
+        /* Remove bytes from input stream */
+        return luat_fs_fseek((FILE*)(buff_info->userdata), nbyte, SEEK_CUR) ? 0 : nbyte;
+    }
+}
+
+static int decode_out_func (JDEC* jd, void* bitmap, JRECT* rect){
+    luat_lcd_buff_info_t *buff_info = (luat_lcd_buff_info_t*)jd->device;
+    uint16_t* tmp = (uint16_t*)bitmap;
+
+    // rgb高低位swap
+    // uint16_t count = (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1);
+    // for (size_t i = 0; i < count; i++){
+    //     if (lcd_dft_conf->endianness_swap)
+    //         buff_info->buff[buff_info->offset] = ((tmp[i] >> 8) & 0xFF)+ ((tmp[i] << 8) & 0xFF00);
+    //     else
+    //         buff_info->buff[buff_info->offset] = tmp[i];
+	// 	buff_info->offset++;
+    // }
+	uint16_t idx = 0;
+	for (size_t y = rect->top; y <= rect->bottom; y++){
+		uint16_t offset = y*buff_info->width + rect->left;
+		for (size_t x = rect->left; x <= rect->right; x++){
+			if (lcd_dft_conf->endianness_swap)
+				buff_info->buff[offset] = ((tmp[idx] >> 8) & 0xFF)+ ((tmp[idx] << 8) & 0xFF00);
+			else
+				buff_info->buff[offset] = tmp[idx];
+			offset++;idx++;
+		}
+	}
+	
+    // LLOGD("jpeg seg %dx%d %dx%d", rect->left, rect->top, rect->right, rect->bottom);
+    // 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));
+    return 1;    /* Continue to decompress */
+}
+LUAT_WEAK int lcd_jpeg_decode(luat_lcd_conf_t* conf, const char* path, luat_lcd_buff_info_t* buff_info){
+    JRESULT res;      /* Result code of TJpgDec API */
+    JDEC jdec;        /* Decompression object */
+    void *work = NULL;       /* Pointer to the decompressor work area */
+#if JD_FASTDECODE == 2
+    size_t sz_work = 3500 * 3; /* Size of work area */
+#else
+    size_t sz_work = 3500; /* Size of work area */
+#endif
+    FILE* fd = luat_fs_fopen(path, "r");
+    if (fd == NULL) {
+        LLOGW("no such file %s", path);
+		goto error;
+    }
+	buff_info->userdata = fd;
+	work = luat_heap_malloc(sz_work);
+	if (work == NULL) {
+		LLOGE("out of memory when malloc jpeg decode workbuff");
+		goto error;
+	}
+    res = jd_prepare(&jdec, decode_file_in_func, work, sz_work, buff_info);
+    if (res != JDR_OK) {
+        LLOGW("jd_prepare file %s error %d", path, res);
+        goto error;
+    }
+    buff_info->width = jdec.width;
+    buff_info->height = jdec.height;
+	buff_info->len = jdec.width*jdec.height*sizeof(luat_color_t);
+	buff_info->buff = luat_heap_malloc(buff_info->len);
+    res = jd_decomp(&jdec, decode_out_func, 0);
+    if (res != JDR_OK) {
+        LLOGW("jd_decomp file %s error %d", path, res);
+        goto error;
+    }
+    luat_heap_free(work);
+    luat_fs_fclose(fd);
+	return 0;
+error:
+	if (work){
+		luat_heap_free(work);
+	}
+	if (fd){
+		luat_fs_fclose(fd);
+	}
+	return -1;
+}
+
 #endif