|
| 1 | +#include <stdlib.h> |
| 2 | +#include <stdint.h> |
| 3 | +#include <string.h> |
| 4 | +#include <stdio.h> |
| 5 | +#include <gif_lib.h> |
| 6 | + |
| 7 | +#define WIDTH 8192 |
| 8 | +#define HEIGHT 8192 |
| 9 | + |
| 10 | +static uint64_t seed = 42; |
| 11 | + |
| 12 | +__attribute__((no_sanitize("integer"))) |
| 13 | +static int psdrand(void) { |
| 14 | + seed = 6364136223846793005ULL * seed + 1; |
| 15 | + return seed >> 33; |
| 16 | +} |
| 17 | + |
| 18 | +static void encode(const char *path, GifColorType *colors, int numColors, uint8_t *img) { |
| 19 | + int error; |
| 20 | + int mapSize = 1; |
| 21 | + while (mapSize < numColors) mapSize *= 2; |
| 22 | + |
| 23 | + GifFileType *gif = EGifOpenFileName(path, false, &error); |
| 24 | + ColorMapObject *cmap = GifMakeMapObject(mapSize, NULL); |
| 25 | + memcpy(cmap->Colors, colors, numColors * sizeof(GifColorType)); |
| 26 | + |
| 27 | + EGifSetGifVersion(gif, true); |
| 28 | + EGifPutScreenDesc(gif, WIDTH, HEIGHT, 8, 0, cmap); |
| 29 | + EGifPutImageDesc(gif, 0, 0, WIDTH, HEIGHT, false, NULL); |
| 30 | + |
| 31 | + for (int y = 0; y < HEIGHT; ++y) |
| 32 | + EGifPutLine(gif, img + y * WIDTH, WIDTH); |
| 33 | + |
| 34 | + GifFreeMapObject(cmap); |
| 35 | + EGifCloseFile(gif, &error); |
| 36 | +} |
| 37 | + |
| 38 | +int main(int argc, char **argv) { |
| 39 | + if (argc != 2) { |
| 40 | + fprintf(stderr, "usage: %s <stripe|gradient|noise|solid>\n", argv[0]); |
| 41 | + return 1; |
| 42 | + } |
| 43 | + |
| 44 | + GifColorType palette256[256]; |
| 45 | + for (int i = 0; i < 256; ++i) { |
| 46 | + palette256[i].Red = i; palette256[i].Green = i; palette256[i].Blue = i; |
| 47 | + } |
| 48 | + |
| 49 | + GifColorType palette3[3] = {{0xFF,0,0},{0,0xFF,0},{0,0,0xFF}}; |
| 50 | + GifColorType palette4[4] = {{0xFF,0,0},{0,0xFF,0},{0,0,0xFF},{0xFF,0xFF,0}}; |
| 51 | + uint8_t *img = malloc(WIDTH * HEIGHT); |
| 52 | + |
| 53 | + if (strcmp(argv[1], "stripe") == 0) { |
| 54 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 55 | + img[i] = (i % WIDTH) / 4 % 3; |
| 56 | + encode("/dev/null", palette3, 3, img); |
| 57 | + |
| 58 | + } else if (strcmp(argv[1], "gradient") == 0) { |
| 59 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 60 | + img[i] = (i % WIDTH) * 256 / WIDTH; |
| 61 | + encode("/dev/null", palette256, 256, img); |
| 62 | + |
| 63 | + } else if (strcmp(argv[1], "noise") == 0) { |
| 64 | + seed = 42; |
| 65 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 66 | + img[i] = psdrand() % 256; |
| 67 | + encode("/dev/null", palette256, 256, img); |
| 68 | + |
| 69 | + } else if (strcmp(argv[1], "solid") == 0) { |
| 70 | + memset(img, 0, WIDTH * HEIGHT); |
| 71 | + encode("/dev/null", palette3, 3, img); |
| 72 | + |
| 73 | + } else if (strcmp(argv[1], "checker") == 0) { |
| 74 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 75 | + img[i] = (((i % WIDTH) + (i / WIDTH)) & 1); |
| 76 | + encode("/dev/null", palette3, 3, img); |
| 77 | + |
| 78 | + } else if (strcmp(argv[1], "dither") == 0) { |
| 79 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 80 | + img[i] = ((i % WIDTH) + (i / WIDTH) * 7) % 256; |
| 81 | + encode("/dev/null", palette256, 256, img); |
| 82 | + |
| 83 | + } else if (strcmp(argv[1], "fewnoise") == 0) { |
| 84 | + seed = 42; |
| 85 | + for (int i = 0; i < WIDTH * HEIGHT; ++i) |
| 86 | + img[i] = psdrand() % 4; |
| 87 | + encode("/dev/null", palette4, 4, img); |
| 88 | + |
| 89 | + } else { |
| 90 | + fprintf(stderr, "unknown pattern: %s\n", argv[1]); |
| 91 | + free(img); |
| 92 | + return 1; |
| 93 | + } |
| 94 | + |
| 95 | + free(img); |
| 96 | + return 0; |
| 97 | +} |
0 commit comments