代码之家  ›  专栏  ›  技术社区  ›  Williham Totland

生成中等有趣的图像

c
  •  22
  • Williham Totland  · 技术社区  · 15 年前

    迄今为止的故事:

    曾几何时,我决定努力减少我(当然也是)众多计算机上的循环浪费,并着手在一个特定的环境中生成图像 适度 有趣的时尚;使用PRNG和一些聪明的数学来创建图像,总的来说, 类似于 某物

    至少,这是计划。事实证明,聪明的数学需要成为聪明的数学家;这个我不是。

    温和地 有趣的;可能类似于城市网格:

    City grids, maybe? http://totlandweb.info/imggen.out.png

    这也意味着一种挑战;我想我已经制定了一些完全武断和同样可选的规则:

    1. 阻止样本编译的错误。

    2. 提供的示例没有,哦!告诉我,我来修理。:)

    3. 这个方法应该是可选的,不需要从 你的友好邻里数学图书馆,并在整体上采用(P)RNG作为它的

    4. 剪线(分别表示不应在上方和下方进行编辑的剪线), 有一个声明,大意是你需要在序言中特别补充什么。

    5. 编辑: 有时很容易忘记,人们在互联网上无法阅读我的 图像的生成,除了对结果进行评价外,还选择了最好的

    代码需要C编译器和libpng来编译;我并不完全相信MinGW编译器提供了必要的东西,但如果它没有提供,我会感到惊讶。对于Debian,您需要libpng dev包,对于Mac OS X,您需要XCode工具。。

    源代码可以是 downloaded here .

    大量代码涌入!

    // compile with gcc -o imggen -lpng imggen.c
    // optionally with -DITERATIONS=x, where x is an appropriate integer
    // If you're on a Mac or using MinGW, you may have to fiddle with the linker flags to find the library and includes.
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <png.h>
    
    #ifdef ITERATIONS
    #define REPEAT
    #endif // ITERATIONS
    
    // YOU MAY CHANGE THE FOLLOWING DEFINES
    #define WIDTH 320
    #define HEIGHT 240
    
    // YOU MAY REPLACE THE FOLLOWING DEFINES AS APPROPRIATE
    #define INK 16384
    
    void writePNG (png_bytepp imageBuffer, png_uint_32 width, png_uint_32 height, int iteration) {
      char *fname;
      asprintf(&fname, "out.%d.png", iteration);
    
      FILE *fp = fopen(fname, "wb");
      if (!fp) return;
      png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      png_infop  info_ptr = png_create_info_struct(png_ptr);
      png_init_io(png_ptr, fp);
      png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, PNG_FILTER_NONE);
      png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
      png_set_IHDR(png_ptr, info_ptr, width, height, 8,
                   PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
      png_set_rows(png_ptr, info_ptr, imageBuffer);
      png_set_invert_mono(png_ptr); /// YOU MAY COMMENT OUT THIS LINE
      png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
      png_destroy_write_struct(&png_ptr, &info_ptr);
      fclose(fp);
      free(fname);
    }
    
    int main (int argc, const char * argv[]) {
      png_uint_32 height = HEIGHT, width = WIDTH;
    
    
      int iteration = 1;
    #ifdef REPEAT
      for (iteration = 1; iteration <= ITERATIONS; iteration++) {
    #endif // REPEAT  
    
        png_bytepp imageBuffer = malloc(sizeof(png_bytep) * height);
        for (png_uint_32 i = 0; i < height; i++) {
          imageBuffer[i] = malloc(sizeof(png_byte) * width);
          for (png_uint_32 j = 0; j < width; j++) {
            imageBuffer[i][j] = 0;
          }
        }    
    
        /// CUT ACROSS THE DASHED LINES
        /// -------------------------------------------
        /// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED
    
        int ink = INK;
        int x = rand() % width, y = rand() % height;
    
        int xdir = (rand() % 2)?1:-1;
        int ydir = (rand() % 2)?1:-1;
    
        while (ink) {
          imageBuffer[y][x] = 255;
          --ink;
          xdir += (rand() % 2)?(1):(-1);
          ydir += (rand() % 2)?(1):(-1);
          if (ydir > 0) {
            ++y;
          } else if (ydir < 0) {
            --y;
          }
          if (xdir > 0) {
            ++x;
          } else if (xdir < 0) {
            --x;
          }
          if (x == -1 || y == -1 || x == width || y == height || x == y && x == 0) {
            x = rand() % width; y = rand() % height;
            xdir = (rand() % 2)?1:-1;
            ydir = (rand() % 2)?1:-1;
          }
        }
    
        /// NO EDITING BELOW THIS LINE
        /// -------------------------------------------
    
        writePNG(imageBuffer, width, height, iteration);
    
        for (png_uint_32 i = 0; i < height; i++) {
          free(imageBuffer[i]);
        }    
        free(imageBuffer);
    #ifdef REPEAT
      }
    #endif // REPEAT
      return 0;
    }
    

    注: 虽然这个问题严格来说似乎不是“可以回答的”;我仍然相信它能给出某种“正确”的答案。大概

    狩猎愉快。

    编辑(再次): here here .

    6 回复  |  直到 14 年前
        1
  •  10
  •   mctylr    15 年前

    Fractals Mandelbrot joke ,对不起)。

    Fractal images 倾向于让人想起现实世界的地理环境。特别地 IFS 分形可以用于相当真实的计算 plants trees ,和 terrain .

    fractal.c


    补充:

    Context-free Jared Tarbell 有一个由程序生成的一些精彩图像的相关画廊。 Aza Algorithm Ink

    第二次添加:

    代数或计算艺术的另一种主要形式是 Cellular automaton (CA),例如(John) Conway's Game of Life ,因 1970 Scientific American 文章作者马丁加德纳。随着stephenwolfram的自传,CA被重新介绍给公众 A New Kind of Science

    与分形有关的是 chaotic systems ,或非线性动态系统,如果你想听起来聪明。它们可以在物理系统上建模,比如 weather forecasting strange attractor (和 SA ).

        2
  •  2
  •   Brian    15 年前

    这种策略根本不支持直线。

        3
  •  2
  •   J. Polfer    15 年前

    美学

    我觉得很有趣。

        4
  •  1
  •   bta    15 年前

    取一个网格(用正方形、六边形或你有的东西来构建),在上面生成一个点的随机场。现在,检查所有可能的方法,使用网格后面的线连接固定的点集。用相似的主题(例如树叶)拍摄图片片段,并将其转换为“线条艺术”样式,将其缩小为轮廓。对于每一组几个点,在你的轮廓图库中寻找一个可以连接这些点的(或者至少靠近一点,这可能需要旋转、镜像等)。你会发现有无数种可能的输出,但如果做得正确,你可以结束许多看起来像树叶(即使他们是'新'类型的树叶,从来没有见过)!

        5
  •  1
  •   ezpz    15 年前

    你可以给行为添加一些琐碎的状态,而不是直接的随机性。例如,与其选择 x y 做基于 P 哪里 P 本质上是 rand % 2

    two-state http://img121.imageshack.us/img121/9018/twostate.png

    1 表示“保持当前路径”和 0 Q 你控制改变方向的频率。添加状态会增加复杂性,但是您可能会得到一些比较有趣的结果,这些结果的值是经过仔细选择的 P .

        6
  •  0
  •   Williham Totland    15 年前

    本着彻底打破我自己(无可否认是武断的规则)的精神,我已经走在前面,自己创造了一个答案!

    这段代码使用了一些非常简单的bezier曲线代码,我昨晚把它们拼凑在一起,虽然答案没有那么有趣,但仍然有点有趣。贝塞尔的代码可以找到 here here .

    除了编辑剪切字段,我还添加了,

    #include "bezier.h"
    

    没有这条线它就不能很好地工作

    /// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED
    
    Bezier *path = newBezier(newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height));
    
    float t;
    Point *point = NULL;
    
    for (t = 0.0; t <= 1.0; t += 0.00000006) {
      point = bezierPoint(path, t, point);
    
      int32_t x = point->x, y = point->y;
    
      if (x >= 0 && x < width && y >= 0 && y < height)
        imageBuffer[y][x] = 255;
    }
    
    destroyPoint(point);
    
    /// NO EDITING BELOW THIS LINE