使用Cairo向24位TFT屏绘制内容出现重复图像、颜色错误问题
问题解决方法
核心问题定位
你的问题由两个代码错误导致:
- 步长(stride)参数使用错误,是画面重复显示的根因
- 像素格式不匹配,是颜色显示错误的根因
具体修复方案
1. 修正步长参数
你调用cairo_image_surface_create_for_data时,最后一个步长参数错误使用了Cairo计算的理论值,正确的取值应该是Linux帧缓冲硬件的实际行长度,存储在fb_finfo.line_length字段中。
很多LCD硬件为了访问效率会将行长度对齐到4/8字节边界,和Cairo计算的理论值存在差异,步长不匹配会导致每行绘制内容错位,最终出现多份重复画面的问题。
同时建议将帧缓冲总大小的计算逻辑替换为:
device->fb_screensize = device->fb_finfo.line_length * device->fb_vinfo.yres;
避免理论计算值和实际硬件值不符的问题。
修正后的surface创建代码:
surface = cairo_image_surface_create_for_data(device->fb_data, CAIRO_FORMAT_RGB24, device->fb_vinfo.xres, device->fb_vinfo.yres, device->fb_finfo.line_length); // 替换为硬件实际行长度
2. 修复颜色错误
Cairo的CAIRO_FORMAT_RGB24格式本质是每像素占4字节,高8位无意义,剩下24位在小端系统上为BGR排列,和很多24位LCD的RGB排列、3字节无填充的存储格式不兼容。
你可以先打印LCD的像素位域参数确认硬件格式:
printf("R 偏移: %d, 位宽: %d\n", device->fb_vinfo.red.offset, device->fb_vinfo.red.length); printf("G 偏移: %d, 位宽: %d\n", device->fb_vinfo.green.offset, device->fb_vinfo.green.length); printf("B 偏移: %d, 位宽: %d\n", device->fb_vinfo.blue.offset, device->fb_vinfo.blue.length);
如果确认LCD是每像素3字节的真24位格式,Cairo原生格式不直接支持,需要做一层像素转换:
- 创建一个离屏的Cairo RGB24 surface完成所有绘制操作
- 逐像素将离屏surface的4字节BGRX格式转换为LCD需要的3字节RGB格式,再拷贝到帧缓冲内存中
如果是32位帧缓冲仅颜色顺序错误,也可以直接在绘制时交换RGB参数的顺序适配硬件格式。
内容的提问来源于stack exchange,提问作者Arun Kumar K S
相关产品推荐
相关产品推荐

