图片显示 XImage与Pixmap(2).md

sin 2021-10-14 AM 1131℃ 0条

XImage与Pixmap的差别

XImagePixmap都是Xlib的数据结构,并且都和图片有关,我们首先分析一下他们之间的区别。

XImage的数据结构在xlib.h中定义

/*
 * Data structure for "image" data, used by image manipulation routines.
 */
typedef struct _XImage {
    int width, height;      /* size of image */
    int xoffset;        /* number of pixels offset in X direction */
    int format;         /* XYBitmap, XYPixmap, ZPixmap */
    char *data;         /* pointer to image data */
    int byte_order;     /* data byte order, LSBFirst, MSBFirst */
    int bitmap_unit;        /* quant. of scanline 8, 16, 32 */
    int bitmap_bit_order;   /* LSBFirst, MSBFirst */
    int bitmap_pad;     /* 8, 16, 32 either XY or ZPixmap */
    int depth;          /* depth of image */
    int bytes_per_line;     /* accelarator to next line */
    int bits_per_pixel;     /* bits per pixel (ZPixmap) */
    unsigned long red_mask; /* bits in z arrangement */
    unsigned long green_mask;
    unsigned long blue_mask;
    XPointer obdata;        /* hook for the object routines to hang on */
    struct funcs {      /* image manipulation routines */
    struct _XImage *(*create_image)(
        struct _XDisplay* /* display */,
        Visual*     /* visual */,
        unsigned int    /* depth */,
        int     /* format */,
        int     /* offset */,
        char*       /* data */,
        unsigned int    /* width */,
        unsigned int    /* height */,
        int     /* bitmap_pad */,
        int     /* bytes_per_line */);
    int (*destroy_image)        (struct _XImage *);
    unsigned long (*get_pixel)  (struct _XImage *, int, int);
    int (*put_pixel)            (struct _XImage *, int, int, unsigned long);
    struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
    int (*add_pixel)            (struct _XImage *, long);
    } f;
} XImage;

Pixmap的数据结构在X.h中定义

typedef XID Pixmap;

从定义我们就能得知,Pixmap是一个简单的句柄。而XImage是一个完整的数据结构。Pixmap是存储在Server端,我们通过句柄操作。而XImage是存储在客户端,我们可以随意操作。

Pixmap操作函数

手册了解,操作Pixmap有如下方法

我画了一张简单的图来解释

png

XImage操作函数

手册了解,操作XImage数据结构有如下方法

Example

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <math.h>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

void test_or_die(int rc)
{
    // #define Success           0    /* everything's okay */
    // #define BadRequest       1    /* bad request code */
    // #define BadValue       2    /* int parameter out of range */
    // #define BadWindow       3    /* parameter not a Window */
    // #define BadPixmap       4    /* parameter not a Pixmap */
    // #define BadAtom           5    /* parameter not an Atom */
    // #define BadCursor       6    /* parameter not a Cursor */
    // #define BadFont           7    /* parameter not a Font */
    // #define BadMatch       8    /* parameter mismatch */
    // #define BadDrawable       9    /* parameter not a Pixmap or Window */
    // #define BadAccess      10    /* depending on context:
    //             - key/button already grabbed
    //             - attempt to free an illegal
    //               cmap entry
    //            - attempt to store into a read-only
    //               color map entry.
    //            - attempt to modify the access control
    //               list from other than the local host.
    //            */
    // #define BadAlloc      11    /* insufficient resources */
    // #define BadColor      12    /* no such colormap */
    // #define BadGC          13    /* parameter not a GC */
    // #define BadIDChoice      14    /* choice not in range or already used */
    // #define BadName          15    /* font or color name doesn't exist */
    // #define BadLength      16    /* Request length incorrect */
    // #define BadImplementation 17    /* server is defective */

    // #define FirstExtensionError    128
    // #define LastExtensionError    255
    switch (rc)
    {
    case Success:
        printf("rc=%d Success\n", rc);
        return;
    case BadRequest:
        printf("rc=%d BadRequest\n", rc);
        break;
    case BadValue:
        printf("rc=%d BadValue\n", rc);
        break;
    default:
        printf("rc=%d Unknown error\n", rc);
        break;
    }
    exit(1);
}

void setimage(Display *X, Window win, GC gc)
{
    XImage *ximage;
    int depth = DefaultDepth(X, 0);
    int width, height, n;
    int rc;
    unsigned char *idata;
    unsigned char *buffer;

    idata = stbi_load("wld.jpg", &width, &height, &n, 0);
    buffer = malloc(width * height * 4);

    for (int i = 0; i < width * height; i++)
    {
        buffer[i * 4] = idata[i * 3 + 2];
        buffer[i * 4 + 1] = idata[i * 3 + 1];
        buffer[i * 4 + 2] = idata[i * 3];
        buffer[i * 4 + 3] = 0;
    }
    stbi_image_free(idata);

    ximage = XCreateImage(X, DefaultVisual(X, 0), depth, ZPixmap,
                          0, (char *)buffer, width, height, 32, 0);
    rc = XPutImage(X, win, gc, ximage, 0, 0, 0, 0, width, height);
    test_or_die(rc);

    free(buffer);
}

int main()
{
    Display *X;
    Window win;
    GC gc;
    XSetWindowAttributes attributes;
    XKeyEvent event;

    X = XOpenDisplay(NULL);

    attributes.background_pixel = 0x4433ff;
    attributes.border_pixel = 0x3344ff;

    win = XCreateWindow(X,
                        XRootWindow(X, 0),
                        0, 0, 556, 720,
                        15,
                        DefaultDepth(X, 0),
                        InputOutput,
                        DefaultVisual(X, 0),
                        CWBackPixel | CWBorderPixel,
                        &attributes);

    XDefineCursor(X, win, XCreateFontCursor(X, XC_right_side));

    XSelectInput(X, win, KeyPressMask | ExposureMask);

    gc = XCreateGC(X, win, 0, NULL);

    XMapWindow(X, win);
    while (1)
    {
        XNextEvent(X, (XEvent *)&event);
        switch (event.type)
        {
        case Expose:
            setimage(X, win, gc);
            break;
        case KeyPress:
        {
            XFreeGC(X, gc);
            XCloseDisplay(X);
            exit(0);
        }
        break;

        default:
        {
            printf("%p\n", &event);
        }
        break;
        }
    }
    return 0;
}

我们看到图片显示正确!

png

这里需要注意一个点:颜色!

颜色

stbi_load加载图片数据到内存中,内存布局是 R G B, 每一个是一个unsigned char。

XCreateImage函数接收的内存数据是

png

所以,我们需要做一个转换。

标签: none

非特殊说明,本博所有文章均为博主原创。

评论啦~