16

I am generating random data and trying to convert it to a PNG image using :

head -c 1MB < /dev/urandom | hexdump -e '16/1 "_x%02X"' | sed 's/_/\\/g; s/\\x  //g; s/.*/    "&"/' | tr -d "\"" | display -depth 8 -size 1000x1000+0 rgb:-

This command always shows a greyish image with some RGB pixels. What am I doing wrong ?

My final goal is to generate at least one image with random data.

jasonwryan
  • 71,734
  • 34
  • 193
  • 226
pxoto
  • 173
  • 1
  • 1
  • 4
  • Define "random." The visual average of a bunch of random RGB values will tend toward grey, after all. – Wildcard Jun 14 '16 at 02:20
  • That is what I thought, but I could not confirm this theory since every picture looks almost the same. – pxoto Jun 14 '16 at 02:22
  • 15 years ago I did something similar in Basic (Chipmunk Basic, to be specific). I had a small graphics window and kept outputting a pixel of random color to random location. The result was a constantly changing picture that still looked essentially the same the whole time—like color static on an old fashioned TV. It's not really grey, but [color static](http://i.stack.imgur.com/9QjJ8.jpg). – Wildcard Jun 14 '16 at 02:26
  • I have managed to generate some static but the images are mostly still gray. – pxoto Jun 14 '16 at 03:15

1 Answers1

25

Firstly, you need to feed display RGB:- raw bytes, not an encoded hex string like you're building with that hexdump | sed | tr pipeline.

Secondly, you aren't giving it enough bytes: you need 3 bytes per pixel, one for each colour channel.

This does what you want:

mx=320;my=256;head -c "$((3*mx*my))" /dev/urandom | display -depth 8 -size "${mx}x${my}" RGB:-

To save directly to PNG, you can do this:

mx=320;my=256;head -c "$((3*mx*my))" /dev/urandom | convert -depth 8 -size "${mx}x${my}" RGB:- random.png

Here's a typical output image:

RGB image generated from /dev/urandom


If you'd like to make an animation, there's no need to create and save individual frames. You can feed a raw byte stream straight to ffmpeg / avconv, eg

mx=320; my=256; nframes=100; dd if=/dev/urandom bs="$((mx*my*3))" count="$nframes" | avconv -r 25 -s "${mx}x${my}" -f rawvideo -pix_fmt rgb24 -i - random.mp4
PM 2Ring
  • 6,553
  • 2
  • 27
  • 32
  • 1
    Stream `/dev/urandom` straight to `ffmpeg` - a genius idea! – Ryan Amaral Jul 30 '21 at 08:03
  • 1
    @Ryan Thanks! It seems to be popular, going by the votes. :) You might like [this answer](https://unix.stackexchange.com/a/324210/88378) and the linked [Myths about /dev/urandom article](http://www.2uo.de/myths-about-urandom/). BTW, if you want fast, high quality random numbers, please see [the PCG family](https://www.pcg-random.org/). – PM 2Ring Jul 30 '21 at 08:28
  • Thank you for sharing those resources @pm-2ring! A quick note: I found useful changing the output name for something different every time. Changing from `random.png` ​to `random$(date +%Y%m%d%H%M%S).png` does the trick for me. – Ryan Amaral Jul 30 '21 at 12:27