#c #linux #x11 #xlib #xcb
Вопрос:
Я работаю с X11 XCB api.
Когда я пытаюсь создать окно и создать xcb_image_t
структуру xcb_image_create_native
, оно возвращается NULL
, если только выделенный мной массив пикселей не имеет точно такого же размера, как массив пикселей для созданного мной окна.
Ниже приведен самый маленький пример, который я мог бы привести. Если я изменю все экземпляры «ширина» и «высота», чтобы они были равны «window_width» и «window_height», программа будет работать идеально, однако, если я изменю «ширину и высоту» на что-либо другое, xcb_image_create_native
вернется NULL
.
Я компилирую gcc и связываюсь с -lxcb -lxcb-image
.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
int main(void)
{
// Just setting up the window
int window_width = 480;
int window_height = 480;
xcb_connection_t *c = xcb_connect(NULL, NULL);
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
xcb_drawable_t window = screen->root;
xcb_gcontext_t gcontext = xcb_generate_id(c);
uint32_t gc_values[] = { screen->black_pixel, 1};
uint32_t gc_mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
xcb_create_gc(c,
gcontext,
window,
gc_mask,
gc_values);
window = xcb_generate_id(c);
uint32_t window_values[] = { screen->white_pixel, XCB_EVENT_MASK_EXPOSURE };
uint32_t window_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
xcb_create_window(c,
XCB_COPY_FROM_PARENT,
window,
screen->root,
0,
0,
window_width,
window_height,
10,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
window_mask,
window_values);
xcb_map_window(c, window);
int byte_depth = screen->root_depth/8;
int width = 50;
int height = 50;
int bytes = byte_depth * width * height;
// The part that messes up.
void *base = malloc(bytes);
uint8_t *data = (uint8_t *)base;
// This function always returns NULL unless width amp; height are the same as window_width amp; window height
xcb_image_t *image = xcb_image_create_native(c,
width,
height,
XCB_IMAGE_FORMAT_XY_PIXMAP,
screen->root_depth,
base,
bytes,
data);
if (!image)
{
fprintf(stderr, "No imagen");
}
else
{
xcb_image_put(c,
window,
gcontext,
image,
0, 0,
0);
}
sleep(2);
return 0;
}
Возможно ли вообще создать изображение XCB с размером, отличным от размера окна? И если да, то что я делаю не так?
Я также попытался выяснить, что происходит не так, посмотрев исходный код xcb_image.c, и хотя я смог разобраться в основах происходящего, я не понимаю этого достаточно, чтобы понять, как это работает таким образом.
https://opensource.apple.com/source/X11libs/X11libs-60/xcb-util/xcb-util-0.3.6/image/xcb_image.c.auto.html
https://code.woboq.org/qt5/include/xcb/xcb_image.h.html
Я действительно ценю любую помощь.
Ответ №1:
Вы уверены, что выделяете достаточно байтов? Как правило, в библиотеке изображений начало линий сканирования должно быть выровнено по 32-битной границе. Это означает, что если длина (в байтах) строки сканирования не делится на 4, вам необходимо добавить заполнение.
Глядя на исходный код xcb, похоже, что xcb_image требуется достаточно места, чтобы чередовать пиксели в один бит на линию сканирования, а затем добавлять отступы для правильного выравнивания.
Это немного усложняет вычисления размера, но приводит к тому, что 24-битное изображение размером 480×480 не требует заполнения, а 24-битное изображение размером 50×50 требует в общей сложности 2100 байт заполнения.
К счастью, чтобы избежать всего этого, вы можете позволить xcb выделить правильный размер для данных изображения. Просто позвони xcb_image_create_native
с base=NULL
, bytes=0
и data=NULL
. Затем вы можете найти указатель на выделенные данные изображения в image->data
Не забудьте позвонить xcb_image_destroy(image)
, когда закончите. Это будет free
как image->data
и image