From 7d54145e56dcb39430362719a528aff6eebe2edc Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sat, 19 Mar 2022 13:20:15 +0100 Subject: [PATCH] Record "seed" when generating images as well For reproducibility --- test/randtilegen.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/test/randtilegen.c b/test/randtilegen.c index 2eccf6b2..3c855e4e 100644 --- a/test/randtilegen.c +++ b/test/randtilegen.c @@ -22,25 +22,25 @@ #include #include +FILE *rngRecorder; // File to which the random bytes will be read uint32_t randBits = 0; // Storage for bits read from the input stream but not yet used uint8_t randCount = 0; // How many bits are currently stored in the above -size_t nbRandBytes = 0; static uint32_t getRandomBits(uint8_t count) { - // Trying to read one more byte with `randCount` at least this high will drop some bits - // If the count is no higher than that limit, then the loop will exit without reading more bytes + // Trying to read one more byte with `randCount` at least this high will drop some bits! + // If the count is no higher than that limit, then the loop is guaranteed to exit without + // reading more bytes. assert(count <= sizeof(randBits) * 8 + 1); // Read bytes until we have enough bits to serve the request while (count > randCount) { int data = getchar(); if (data == EOF) { - fprintf(stderr, "Exit after reading %zu bytes\n", nbRandBytes); exit(0); } randBits |= (uint32_t)data << randCount; randCount += 8; - ++nbRandBytes; + fputc(data, rngRecorder); } uint32_t result = randBits & (((uint32_t)1 << count) - 1); @@ -49,6 +49,14 @@ static uint32_t getRandomBits(uint8_t count) { return result; } +/** + * Flush any remaining bits in the RNG storage + */ +static void flushRng(void) { + randCount = 0; + randBits = 0; +} + /** * Expand a 5-bit color component to 8 bits with minimal bias */ @@ -203,10 +211,17 @@ int main(int argc, char **argv) { } } - char filename[maxBasenameLen + 25]; + char filename[maxBasenameLen + sizeof("65535.png")]; for (uint16_t i = 0;; i++) { // 65k images ought to be enough for (int index = 1; index < argc; index++) { - sprintf(filename, "%s%" PRIu16 ".png", argv[index], i); + int len = sprintf(filename, "%s%" PRIu16 ".rng", argv[index], i); + rngRecorder = fopen(filename, "wb"); + if (!rngRecorder) { + perror("RNG fopen"); + return 1; + } + + filename[len - 3] = 'p'; // `.rng` -> `.png` FILE *img = fopen(filename, "wb"); if (!img) { perror("PNG fopen"); @@ -227,10 +242,15 @@ int main(int argc, char **argv) { return 1; } + // Ensure that image generation starts on byte boundaries + // (This is necessary so that all involved random bits are recorded in the `.rng` file) + flushRng(); + png_init_io(png, img); generate_random_image(png, pngInfo); png_destroy_write_struct(&png, &pngInfo); fclose(img); + fclose(rngRecorder); } if (i == UINT16_MAX) {