ref: 7d54145e56dcb39430362719a528aff6eebe2edc
parent: e753b62d1ace56de6f83e058f834c867dbf46476
author: ISSOtm <eldredhabert0@gmail.com>
date: Sat Mar 19 09:20:15 EDT 2022
Record "seed" when generating images as well For reproducibility
--- a/test/randtilegen.c
+++ b/test/randtilegen.c
@@ -22,13 +22,14 @@
#include <stdlib.h>
#include <string.h>
+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
@@ -35,12 +36,11 @@
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);
@@ -50,6 +50,14 @@
}
/**
+ * 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
*/
static uint8_t _5to8(uint8_t five) {
@@ -203,10 +211,17 @@
}
}
- 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 @@
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) {