XCB调用xcb_put_image_checked()遇Length错误(代码16)求助
解决XCB PutImage长度错误(错误码16)的问题
问题描述
使用Freetype光栅化8位深度位图,在XCB的8位深度pixmap上渲染时,xcb_put_image_checked()返回错误码16(Length)、主码72(PutImage)。已确认位图尺寸匹配(pitch=7、rows=7、width=7),无填充,pixmap与位图深度一致,尝试调整长度参数仍失败。
问题原因
XCB的Z_PIXMAP格式要求每扫描线的字节数必须对齐到4字节边界(longword对齐),而Freetype输出的位图pitch为7(未对齐),直接传入会导致XCB判定缓冲区长度不符合要求。
解决方案
需要将Freetype的位图数据转换为符合XCB对齐要求的格式,具体步骤如下:
- 计算XCB要求的对齐后每行字节数:
// 按4字节边界对齐计算每行字节数 int xcb_pitch = ((ft_bitmap.width * 8 + 31) / 32) * 4;
- 创建对齐后的缓冲区,复制原数据并补全空白字节:
uint8_t *xcb_buffer = malloc(xcb_pitch * ft_bitmap.rows); if (!xcb_buffer) { logmsg(INFO, "failed to allocate xcb buffer"); return; } for (int i = 0; i < ft_bitmap.rows; i++) { // 复制当前行的有效数据 memcpy(xcb_buffer + i * xcb_pitch, ft_bitmap.buffer + i * ft_bitmap.pitch, ft_bitmap.width); // 补0填充到对齐后的长度 memset(xcb_buffer + i * xcb_pitch + ft_bitmap.width, 0, xcb_pitch - ft_bitmap.width); }
- 修改
xcb_put_image_checked()调用,使用对齐后的缓冲区和长度:
cookie = xcb_put_image_checked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, gc, ft_bitmap.width, ft_bitmap.rows, 0, 0, 0, 8, xcb_pitch * ft_bitmap.rows, xcb_buffer);
- 最后记得释放临时缓冲区:
free(xcb_buffer);
修改后的完整测试函数
void testing() { FT_Library library; char *fonts[] = {"DejaVuSans"}; FT_Init_FreeType(&library); /* custom function that loads faces from font config patterns proven to work in this instance */ xcb_drw_face_t *ft = xcb_drw_faces_load(library,fonts,1); if (!ft) { logmsg(INFO,"could not load face"); FT_Done_FreeType(library); return; } FT_Load_Char(ft->face,'a',FT_LOAD_RENDER|FT_LOAD_FORCE_AUTOHINT); FT_Bitmap ft_bitmap = ft->face->glyph->bitmap; logmsg(INFO,"pitch = %i | rows = %i | width = %i",ft_bitmap.pitch,ft_bitmap.rows,ft_bitmap.width); /* pitch = 7 | rows = 7 | width = 7 */ // 计算XCB要求的对齐后每行字节数 int xcb_pitch = ((ft_bitmap.width * 8 + 31) / 32) * 4; uint8_t *xcb_buffer = malloc(xcb_pitch * ft_bitmap.rows); if (!xcb_buffer) { logmsg(INFO, "failed to allocate xcb buffer"); xcb_drw_faces_free(ft); FT_Done_FreeType(library); return; } // 转换为对齐后的缓冲区 for (int i = 0; i < ft_bitmap.rows; i++) { memcpy(xcb_buffer + i * xcb_pitch, ft_bitmap.buffer + i * ft_bitmap.pitch, ft_bitmap.width); memset(xcb_buffer + i * xcb_pitch + ft_bitmap.width, 0, xcb_pitch - ft_bitmap.width); } xcb_void_cookie_t cookie; xcb_generic_error_t *error; xcb_pixmap_t pixmap = xcb_generate_id(c); cookie = xcb_create_pixmap_checked(c,8,pixmap,screen.data->root,screen.data->width_in_pixels,screen.data->height_in_pixels); if (xcb_request_check(c,cookie)) { logmsg(INFO,"could not create pixmap"); free(xcb_buffer); xcb_drw_faces_free(ft); FT_Done_FreeType(library); return; } xcb_gcontext_t gc = xcb_generate_id(c); cookie = xcb_create_gc_checked(c,gc,pixmap,0,0); if (xcb_request_check(c,cookie)) { logmsg(INFO,"could not create gc"); xcb_free_pixmap(c,pixmap); free(xcb_buffer); xcb_drw_faces_free(ft); FT_Done_FreeType(library); return; } cookie = xcb_put_image_checked(c,XCB_IMAGE_FORMAT_Z_PIXMAP,pixmap,gc,ft_bitmap.width,ft_bitmap.rows,0,0,0,8,xcb_pitch * ft_bitmap.rows,xcb_buffer); if ((error = xcb_request_check(c,cookie))) { logmsg(INFO,"could not put image on pixmap | err %i | maj %i | min %i",error->error_code,error->major_code,error->minor_code); free(error); } free(xcb_buffer); xcb_drw_faces_free(ft); xcb_free_pixmap(c,pixmap); xcb_free_gc(c,gc); FT_Done_FreeType(library); return; }
内容的提问来源于stack exchange,提问作者archer
相关产品推荐
相关产品推荐

