# SDui-LVGL
**Repository Path**: Biz-Spring_0/SDui-LVGL
## Basic Information
- **Project Name**: SDui-LVGL
- **Description**: 嵌入式AI画板 SDui-LVGL is a drawing board program based on the LVGL graphics framework, utilizing the stable diffusion API to call a remote server for text-to-image and image-to-image generation.
- **Primary Language**: C
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 5
- **Created**: 2024-06-05
- **Last Updated**: 2024-06-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# SDui-LVGL
------------------------------------------------
**请前往 https://github.com/Jiong-Ge/SDui-LVGL 查看**
------------------------------------------------
SDui-LVGL is a drawing board program based on the LVGL graphics framework, utilizing the stable diffusion API to call a remote server for text-to-image and image-to-image generation. This was my undergraduate thesis project, which has now concluded, so I intend to open-source it.
The principle behind it is roughly as follows: first, the canvas buffer is extracted and converted to BASE64 encoding. Based on user-selected prompts, generation modes, and network control types within the interface, it synthesizes JSON. Then, the image content is filled into appropriate locations and sent to either a local or remote server, with reception involving the inverse operation.
I’ve only been learning Linux for six months, and I haven’t previously worked with LVGL on any projects, so this code may appear rudimentary. However, with your efforts, it can improve.
## 1. 项目说明
本项目的前身是作为我的本科毕业设计,如今已经结束了相关流程,因此开源了此工程。
项目想法起源于各大平台都有调用 stableDiffusion API 的功能实现绘图,但是在嵌入式平台中却没有找到类似的项目(公开的),由于本人对于 Linux 和 LVGL 的认知尚浅,因此想通过本项目提升技术。也因此,本项目有很多地方的代码并不高明,仅作为抛砖引玉的作用,也希望各位大佬可以迭代出更强大的版本!
对于项目的作用,大概在数位屏上比较贴切吧?(雾)
### 开发套件
屏幕分辨率为`800x480`,开发板为鲁班猫2(无所谓的),使用WSL+VScode开发,WSL也承担了交叉编译,在`makefile`中使用`sshpass`自动补全密码(美滋滋)。
对于屏幕触摸的标志位,单点触控和多点触控是不一样的,各位需要通过`evtest`获知自己的标志位是怎么样的。
如果想移植到单片机,那么各种回调函数和涉及linux相关的内容都需要改写。
### 基础界面
基础界面(直接选择风格和提示词进行文生图)
图生图
图生图
带控制网的文生图
带控制网的文生图
开发界面
调试界面
PS:左下角黑色的小方块其实是光标,我在另一款开源的C++贪吃蛇中见到过使用printf方式隐藏的方式,但是忘了,后续补上
### 大致流程
只有一个屏幕,其他所有控件都是以活动屏幕为父对象创建的,并且简单粗暴地用全局变量保存各对象的句柄、标志位等。经过我的测试,发送到服务器的图片允许使用BMP格式(文件较大),但返回时只能为PNG格式(需要自己解码)。
画板部分套用了百问网的接口,其他按钮、下拉菜单、进图条、复选框为自己开发。画板初始化时需要制定一个缓存作为画布保存内容的空间,因此我们可以在缓存上做文章。通过Linux的文件IO、系统编程、网络编程等操作:
1. 将缓存变换为BMP格式的图片,再通过BASE64编码放在一旁备用(A);
2. 根据下拉菜单和复选框的内容,条件合成JSON内容(主要是提示词、各种设置、控制网等,你在WEBui上能看到的,JSON上都是可调的),其中也包含要填入图像数据的地方(B);
3. 将A和B数据进行组合,一般在JSON中有三个位置可以插入图像:最外部的`init_image`(基础图像)、在控制网中的`mask`(遮罩)和`input_image`(控制网输入图像)等;
4. 对于buffer->BMP的过程,LVGL的色彩通道顺序是BGR,而BMP的色彩通道顺序为RGB,因此只需要采用经典合成文件头+信息头+色彩顺序的方式,即可得到BMP图像
5. 对于PNG->BMP的过程,我采用调用其他第三方程序的方式实现(偷懒了):使用`sprintf`合成指令,用`system`执行。但不知道为什么,我采用这种方式得到的BMP文件虽然不是调色板模式,但却有调色板的无效数据,因此需要额外更改偏移位才可以正常读取内容(代码中有体现);
6. 服务器通讯刚开始使用了`Curl`库,但编译文件多了好多,我也仅仅是进行UDP通信(SD服务器会报,但兼容),因此一咬牙还是自己手搓了套接字通讯。
7. 接受流程大致为发送流程的逆操作;
8. TODU ...
### 代码逻辑解释
TODU. ..
## 2. 工程前期准备
### 百问网画板接口
如果您阅读过百问网的相关代码,您会发现“**画板**”部分非常的相像:
- 百问网LVGL中文文档:[什么是Lvgl? — 百问网LVGL中文教程手册文档 1.0 文档 (100ask.net)](https://lvgl.100ask.net/7.11/documentation/01_intro/intro.html)
- 百问网画板接口:[src/lv_100ask_sketchpad · 韦东山/lv_lib_100ask - 码云 - 开源中国 (gitee.com)](https://gitee.com/weidongshan/lv_lib_100ask/tree/master/src/lv_100ask_sketchpad)
关于画板中的色轮(颜色选择器),默认会触发长按选择色相时,跳转到饱和度选择,非常影响体验,参考正点原子的LVGL教程:[第45讲 部件篇-色环部件_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1CG4y157Px?p=45&vd_source=00fe280cdfc4a645876630b6c032bf30)的解释,添加以下代码可以屏蔽相关跳转:
`lv_colorwheel_set_mode_fixed(cw, true);`
### SD接口
我为了图方便,直接使用**秋葉aaaki**的整合包:[秋葉aaaki的个人空间-秋葉aaaki个人主页-哔哩哔哩视频 (bilibili.com)](https://space.bilibili.com/12566101?spm_id_from=333.788.0.0)
API 方面,如今已经有 v3 版本的接口,但是我使用的本地 SD 只有 v1 的版本。如果您在各大提供 post 等测试的平台看过 v3 接口的具体内容,其实具体细节的变化并不大,因此可以先研究最初始的,也可以触类旁通。
具体的 v1 接口示范:`http://你的IP:你的端口/docs`
网上也有相关的说明文档:
- (v1) 很详细:[全网最全stable diffusion webui API调用示例,包含controlneth和segment anything的API](https://blog.csdn.net/Python_anning/article/details/135269356)
- (v1) 有实操:[stable diffusion 远端跑图—— Api基础知识掌握](https://zhuanlan.zhihu.com/p/624042359)
- (v2):[stable diffusion API 调用,超级详细代码示例和说明](https://juejin.cn/post/7265666505101164603) | [AI绘画专栏之 SDXL controlnet API教程(36)](https://cloud.tencent.com/developer/article/2359971)
### LVGL框架移植
LVGL库:[lvgl/lvgl: Embedded graphics library to create beautiful UIs for any MCU, MPU and display type. (github.com)](https://github.com/lvgl/lvgl)
LVGL 框架版本选择:本文撰写时已经有 `9.0.0` 版本,而互联网上很多文章可能还在用 `8.3.x` 甚至是 `7.x.x`,此时并不需要惊慌,因为很多接口是通用的。当你使用一个函数,如果你的编译器会提供自动补全,而且有弹出相关的参数定义,那么您输入的函数大概率是可以使用的。但是不同版本的函数对参数的定义可能会不一样,因此这部分需要各位大佬自行解决。
前文提到我使用了百问网的画板接口,它并不兼容我的 `9.x.x` 版本,但是有取巧的方法:网上提供的接口为了稳定性,会在对应的头文件中加入版本控制的宏判断语句,对应的宏在框架的 有记录。因此我们只需要删除掉相关的接口判断语句即可,如果编译不通过再继续找问题。
对于LVGL调用硬件的方式:你可以把自己屏幕驱动中的画点函数,注册到LVGL框架中;也可以使用SDL(如在Win中模拟)、Frame Buffer(如Linux)等方式。
## 3. 常用的命令和项目依赖
### 命令
- 截图:`fbgrab -d /dev/fb0 /home/cat/play/1.png`
- 关闭图形显示:`systemctl set-default multi-user.target`
- 打开图形显示:`systemctl set-default graphical.target`
### 依赖库
- **imagemagick**(处理 PNG 和 BMP 转换)
- 安装:`sudo apt install imagemagick`
- 用法:
- PNG转BMP:`sprintf(command, "convert %s %s", input, output);`
- **coreutils**(负责 BASE64 与文件的转换)
- 安装:`sudo apt install coreutils`
- 用法:
- 编码到文件:`sprintf(base64_decode, "base64 -d %s > %s", input, output);`
- 文件到编码:`sprintf(command, "base64 -w 0 %s > %s", bmp_file, base_name);`
TODO ...