c - 使用 Xlib 生成 Perlin 噪声

标签 c image xlib screensaver perlin-noise

我正在尝试将云添加到 Xscreensaver。我喜欢“等 ionic ”云的外观,所以我试图在 Xscreensaver 的背景上绘制一个基于 perlin 噪声的云。我有创建一个数组的代码,该数组具有构成柏林噪声的颜色值。我所需要做的就是从该数组创建一个图像并将其设置为该 Xscreensaver 中的背景。

如何从这个数组生成图像?我研究过使用纯 Xlib,但这是一项艰巨的任务。因此,如果有一种方法可以使用 Cairo 从数组中生成图像,那就太好了。此外,数组中的值介于 0 和 1 之间。

最佳答案

Cairo 函数是 cairo_image_surface_create_for_data() , 但将数据放入适当的布局中以供 Cairo 读取可能有点令人生畏。内存图像格式的详细信息(描述 here )在 cairo.h 头文件本身(在注释中),而不是手册。

另一个陷阱是:确保使用cairo_format_stride_for_width()获取行的大小,因为可能存在您无法(不需要)自己计算的填充要求。

尝试 CAIRO_FORMAT_A8CAIRO_FORMAT_A1 可能很诱人,因为这是一个 1 位深的图像;但我发现 1 位图像更容易使用 CAIRO_FORMAT_RGB24 并将红绿蓝值设置为 0 或 255。A* 格式影响 alpha channel ,而不是图像数据通道,因此使用它时,您仍然需要另一个 RGB 数据源。不透明 nothing 与透明 nothing 一样不可见。此外,位的排列取决于底层机器的字节顺序,因此直接使用 32 位值(如果你愿意,你可以使用 uint32_t,但是你的 printf 格式说明符会变得很糟糕;所以我坚持使用 long)。如果您要移动整个整数值,那么数据的字节序自然会反射(reflect)机器的字节序。

这是来自 cairo.h 的相关信息:

/**
 * cairo_format_t:
 * @CAIRO_FORMAT_INVALID: no such format exists or is supported.
 * @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with
 *   alpha in the upper 8 bits, then red, then green, then blue.
 *   The 32-bit quantities are stored native-endian. Pre-multiplied
 *   alpha is used. (That is, 50% transparent red is 0x80800000,
 *   not 0x80ff0000.) (Since 1.0)
 * @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with
 *   the upper 8 bits unused. Red, Green, and Blue are stored
 *   in the remaining 24 bits in that order. (Since 1.0)
 * @CAIRO_FORMAT_A8: each pixel is a 8-bit quantity holding
 *   an alpha value. (Since 1.0)
 * @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding
 *   an alpha value. Pixels are packed together into 32-bit
 *   quantities. The ordering of the bits matches the
 *   endianess of the platform. On a big-endian machine, the
 *   first pixel is in the uppermost bit, on a little-endian
 *   machine the first pixel is in the least-significant bit. (Since 1.0)
 * @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity
 *   with red in the upper 5 bits, then green in the middle
 *   6 bits, and blue in the lower 5 bits. (Since 1.2)
 * @CAIRO_FORMAT_RGB30: like RGB24 but with 10bpc. (Since 1.12)
 *
 * #cairo_format_t is used to identify the memory format of
 * image data.
 *
 * New entries may be added in future versions.
 *
 * Since: 1.0
 **/
typedef enum _cairo_format {
    CAIRO_FORMAT_INVALID   = -1,
    CAIRO_FORMAT_ARGB32    = 0,
    CAIRO_FORMAT_RGB24     = 1,
    CAIRO_FORMAT_A8        = 2,
    CAIRO_FORMAT_A1        = 3,
    CAIRO_FORMAT_RGB16_565 = 4,
    CAIRO_FORMAT_RGB30     = 5
} cairo_format_t;

我的 example code在另一个答案中是一个非常糟糕的例子。但就是这样,因为我写的时候根本找不到任何例子,所以... ex nihilo nihil。它尝试使用已知为大端字节序的源数据来打包适当的数据数组,并且可能是 1 位、2 位、4 位或 8 位深。哎呀,它甚至还有无辜的小声明

         run(st);

它递归地调用整个解释器,这对于将 longjmperror 机制获取到解释器的正确 实例来说是 hell 。这是一个使用 cairo_image_surface_create_for_data() 的非常糟糕的例子。但是...有人给我看一个更好的。请!


这是一个更简单的示例的说明。我还没有测试过它,但我认为这是一种更简单的方法来满足您的需求。

#include <stdint.h> /* uint32_t */

uint32_t datasamp(double d) { // convert floating point to rgb-byte-field integer
    uint32_t u;
    u = d * 255; // [0.0 .. 1.0] -> [0 .. 255] 
    return u<<16 | u<<8 | u; // r = g = b = u  0x00rrggbb 
}

// samp is a 2D double array
// double samp[hgt][wid];    
uint32_t *imagedata(int wid, int hgt, double *samp){ 
    int stride; 
    uint32_t *data;
    int i,j;
    stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wid);
    data = malloc(stride*hgt*sizeof(uint32_t));  //use stride instead of width
    for (i=0; i < hgt; i++) {
        for (j=0; j < wid; j++) {
            data[i*stride + j] =    // use stride for data row width
                datasamp(samp[i*wid + j]);  // use wid as normal for source array
        }       
    }
    return data;
}

返回的数据将适合传递给 cairo_image_surface_create_for_data。重要的是使用 stride 作为行宽,即使源数据的排列方式不同(这里只有 wid 宽)。

哦,这是一种反向抛光的“应用程序匈牙利语”,我在这里将其用于命名约定。所以 imagedata 表示“图像 <-- 数据”。 datasamp 表示“数据 <-- samp”。

关于c - 使用 Xlib 生成 Perlin 噪声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16313336/

相关文章:

c - 从链表中删除选择的节点

c - C 中意外的位移行为

html - 如何显示图像的特定部分?

python - 使用 python xlib 进行选择性记录?

c - 结构 tm : Where year = 70 mon = 1 mday = 1 does not return 0 seconds? 上的 timegm

c - 使用 C 中的 printf 打印 * 相应的数字

image - glTexImage2D 与宽度/高度相关的段错误

javascript - 交响乐 2 :image paths in javascript file with assetic

c - X 子结构重定向弄乱了工具/菜单栏

C - 如何读取屏幕像素的颜色(快速)? (在 Windows 中)