You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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对齐要求的格式,具体步骤如下:

  1. 计算XCB要求的对齐后每行字节数:
// 按4字节边界对齐计算每行字节数
int xcb_pitch = ((ft_bitmap.width * 8 + 31) / 32) * 4;
  1. 创建对齐后的缓冲区,复制原数据并补全空白字节:
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);
}
  1. 修改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);
  1. 最后记得释放临时缓冲区:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:05:03