pgmrnoise – a more random (or less repeatable) pgmnoise

Update: If you have a recent NetPBM, this is fixed.
I’d previously alluded that netpbm’s pgmnoise wasn’t as random as it could be if you called it several times in quick succession. Nerdy discussion after the break, but here’s a (perhaps slightly linux-centric) alternative:

# pgmrnoise - a more random pgmnoise; limited to 8-bit images
# created by scruss on Sun Oct 12 19:36:37 EDT 2008

echo P5
echo $1 $2
echo 255
dd if=/dev/urandom bs=$1 count=$2 2> /dev/null

I just pasted the shell text in there; you’ll need to save it as a file. It works the same way as pgmnoise:

 pgmrnoise width height > noise.pgm

It is limited as written to 8 bit-per-pixel output, but is a fairly trivial edit to make it 16 or more bits.

Try the following test:

 for f in `seq 1 10`; do pgmnoise 64 64 | md5sum -b -; done | sort -u

What it does is take the fingerprint of the output of pgmnoise run 10 times. In theory, you should get 10 different fingerprints. In practice, you might get two – and that’s only if the script happens to run over the clock’s one second boundary.

The problem arises from how netpbm initializes its pseudorandom number generator. If you look in the utility functions in lib/libpm.c, you’ll see:

unsigned int
pm_randseed(void) {
    return time(NULL) ^ getpid();

This is called many times in the netpbm codebase, including in the setup for pgmnoise. It returns an integer seed, being the current time in seconds XOR the process ID. So if it’s called twice in the same clock second with the same process id, it’ll return the same seed.

This won’t be much of a problem for most users (I, uh, promise I’m not needing this for an unnamed cryptographic escapade, no really I’m not). The perl docs have had a warning about using this type of seed for a while, so maybe we should use something a little more high-resolution, like the output of gettimeofday.

(Thanks to Bryan, the NetPBM maintainer, for showing me I was running an old version but looking at new source code.)

Leave a comment

Your email address will not be published. Required fields are marked *