Munashedov

Naive Voronoi to P6 netpbm

Apr 20th, 2023
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.43 KB | None | 0 0
  1. // Naive Voronoi generation writing out to P6 netpbm image.
  2.  
  3. #include <limits.h>
  4. #include <stdint.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <time.h>
  8.  
  9. // Good random number generator xoroshiro64** 1.0
  10. // Written in 2018 by David Blackman and Sebastiano Vigna ([email protected])
  11. static inline uint32_t rotl(const uint32_t x, int k) {
  12.     return (x << k) | (x >> (32 - k));
  13. }
  14.  
  15. static uint32_t s[2];
  16.  
  17. uint32_t next(void) {
  18.     const uint32_t s0 = s[0];
  19.     uint32_t s1 = s[1];
  20.     const uint32_t result = rotl(s0 * 0x9E3779BB, 5) * 5;
  21.  
  22.     s1 ^= s0;
  23.     s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9); // a, b
  24.     s[1] = rotl(s1, 13); // c
  25.  
  26.     return result;
  27. }
  28. // End xoroshiro64** 1.0
  29.  
  30. // Width and height of the Voronoi texture to be generated.
  31. #define height 512
  32. #define width 512
  33. #define NODE_COUNT 192
  34.  
  35. typedef struct {
  36.     int x;
  37.     int y;
  38. } Node;
  39.  
  40. Node nodes[NODE_COUNT] = {0};
  41.  
  42. typedef struct {
  43.     uint8_t r;
  44.     uint8_t g;
  45.     uint8_t b;
  46. } Pixel;
  47.  
  48. Pixel palette[NODE_COUNT] = {0};
  49.  
  50. int main() {
  51.     // Set the seed for the RNG
  52.     time_t t;
  53.     time(&t);
  54.     s[0] = (uint32_t)t;
  55.     s[1] = (uint32_t)(t >> 32);
  56.    
  57.     // Allocate a pixel buffer to hold the image data.
  58.     size_t nbytes = width * height * sizeof(Pixel);
  59.     Pixel *pixels = calloc(width * height, sizeof(pixels[0]));
  60.     if (!pixels) {
  61.         fprintf(stderr, "ERROR: Failed to allocate %lu bytes for image buffer %d x %d\n", nbytes, width, height);
  62.         return 1;
  63.     }
  64.    
  65.     // Generate colors and node positions.
  66.     int colorStep = 256 / NODE_COUNT;
  67.     for (int i = 0; i < NODE_COUNT; ++i) {
  68.         palette[i] = (Pixel){0, colorStep * i, colorStep * i >> 1};
  69.         nodes[i].x = next() % width;
  70.         nodes[i].y = next() % height;
  71.     }
  72.  
  73.     // Iterate over each pixel in the buffer.
  74.     for (int y = 0; y < height; ++y) {
  75.         for (int x = 0; x < width; ++x) {
  76.             int closest = 0;
  77.             int distance = INT_MAX;
  78.             // Find the index of the closest Node.
  79.             for (int i = 0; i < NODE_COUNT; ++i) {
  80.                 int dx = nodes[i].x - x;
  81.                 int dy = nodes[i].y - y;
  82.                 int distance_new = dx*dx + dy*dy;
  83.                 if (distance_new < distance) {
  84.                     closest = i;
  85.                     distance = distance_new;
  86.                 }
  87.             }
  88.             // Set the current pixel's color to the color of the closest Node.
  89.             pixels[y * width + x] = palette[closest];
  90.         }
  91.     }
  92.     // Write out the pixel data into the P6 netpbm image format.
  93.     FILE *file = fopen("output.pbm", "wb");
  94.     fprintf(file, "P6 %d %d 255 ", width, height);
  95.     fwrite(pixels, sizeof(char), nbytes, file);
  96.     fclose(file);
  97.    
  98.     return 0;
  99. }
  100.  
Add Comment
Please, Sign In to add comment