Pseudorandom number generator image

From Rosetta Code
Revision as of 15:28, 21 March 2021 by MaiconSoft (talk | contribs) (Added Delphi example)
Pseudorandom number generator image is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Write a program that creates an image from a Pseudorandom Number Generator (PRNG) algorithm's output. The image can have the following dimensions:

  1. 250px by 250px : If the algorithm requires the use of prime numbers, use 8-15 bit primes.
  2. 500px by 500px : If the algorithm requires the use of prime numbers, use 8-15 bit primes.
  3. 1000px by 1000px : If the algorithm requires the use of prime numbers, use 8-32 bit primes.
  4. 1500px by 1500px : If the algorithm requires the use of prime numbers, use 16-64 bit primes.
Possible Output

https://www.random.org/analysis/randbitmap-rdo.png

https://ibb.co/ZJPS16j

See also
  •   Blum Blum Shub [1].
  •   Blum-Micali Algorithm: [2].
  •   Linear congruential generator [3].

Delphi

<lang Delphi> program Pseudorandom_number_generator_image;

{$APPTYPE CONSOLE}

uses

 System.SysUtils,
 vcl.Graphics,
 Vcl.Imaging.PngImage;

type

 TRGBTriple = packed record
   b: Byte;
   g: Byte;
   r: Byte;
 end;
 PRGBTripleArray = ^TRGBTripleArray;
 TRGBTripleArray = array[0..999] of TRGBTriple;

function Noise(cWidth, cHeight: Integer; Color: boolean = True): TBitmap; const

 Seed = 2147483647;

var

 Pixels: PRGBTripleArray;

begin

 RandSeed := Seed;
 Result := TBitmap.Create;
 with Result do
 begin
   SetSize(cWidth, cHeight);
   PixelFormat := pf24bit;
   for var row := 0 to cHeight - 1 do
   begin
     Pixels := ScanLine[row];
     for var col := 0 to cWidth - 1 do
     begin
       if Color then
       begin
         Pixels[col].r := random(255);
         Pixels[col].g := random(255);
         Pixels[col].b := random(255);
       end
       else
       begin
         var Gray := Round((0.299 * random(255)) + (0.587 * random(255)) + (0.114
           * random(255)));
         Pixels[col].r := Gray;
         Pixels[col].g := Gray;
         Pixels[col].b := Gray;
       end;
     end;
   end;
 end;

end;

const

 cWidth = 1000;
 cHeight = 1000;

begin

 // Color noise
 var bmp := Noise(cWidth, cHeight);
 bmp.SaveToFile('randbitmap-rdo.bmp');
 // to Png
 with TPngImage.create do
 begin
   Assign(bmp);
   SaveToFile('randbitmap-rdo.png');
   free;
 end;
 bmp.Free;
 // Gray noise
 bmp := Noise(cWidth, cHeight, False);
 bmp.SaveToFile('randbitmap-rdo_g.bmp');
 // to Png
 with TPngImage.create do
 begin
   Assign(bmp);
   SaveToFile('randbitmap-rdo_g.png');
   free;
 end;
 bmp.Free;

end.</lang>

Output:

randbitmap-rdo.png.

Go

The math/rand package uses a custom algorithm attributed to D.P.Mitchell and J.A.Reeds. It doesn't need to be seeded by a prime number. Typically (as here) the seed is generated from the current time.

The image is saved to a .png file which can then be viewed with a utility such as EOG. <lang go>package main

import (

   "image"
   "image/color"
   "image/png"
   "log"
   "math/rand"
   "os"
   "time"

)

func main() {

   rand.Seed(time.Now().UnixNano())
   img := image.NewNRGBA(image.Rect(0, 0, 1000, 1000))
   for x := 0; x < 1000; x++ {
       for y := 0; y < 1000; y++ {
           col := color.RGBA{uint8(rand.Intn(256)), uint8(rand.Intn(256)), uint8(rand.Intn(256)), 255}
           img.Set(x, y, col)
       }
   }
   fileName := "pseudorandom_number_generator.png"
   imgFile, err := os.Create(fileName)
   if err != nil {
       log.Fatal(err)
   }
   defer imgFile.Close()
   if err := png.Encode(imgFile, img); err != nil {
       imgFile.Close()
       log.Fatal(err)
   }

}</lang>

Java

Following implementation generates images from java.util.Random(uses linear congruential generator [4].) and Blum Blum Shub Algorithm with least significant bit method and even bit parity method[5]. <lang Java> import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.math.BigInteger; import java.security.SecureRandom; import java.util.Random; import java.util.Scanner; /*

  • Numbers to try:
  • p = 11 or BigInteger.probablePrime(BIT1_LENGTH, rand)
  • q = 23 or BigInteger.probablePrime(BIT_LENGTH, rand)
  • seed = 3 or BigInteger.probablePrime(BIT_LENGTH,rand)
  • */

public class csprngBBS {

   public static Scanner input = new Scanner(System.in);
   private static final String fileformat = "png";
   private static String bitsStri = "";
   private static String parityEven = "";
   private static String leastSig = "";
   private static String randomJavaUtil = "";
   private static int width = 0;
   private static int BIT_LENGTH = 0;
   private static final Random rand = new SecureRandom();
   private static BigInteger p = null; // 11
   private static BigInteger q = null; // 23
   private static BigInteger m = null;
   private static BigInteger seed = null; // 3
   private static BigInteger seedFinal = null;
   private static final Random randMathUtil = new SecureRandom();
   public static void main(String[] args) throws IOException {
       System.out.print("Width: ");
       width = input.nextInt();
       System.out.print("Bit-Length: ");
       BIT_LENGTH = input.nextInt();
       System.out.print("Generator format: ");
       String useGenerator = input.next();
       p = BigInteger.probablePrime(BIT_LENGTH, rand);
       q = BigInteger.probablePrime(BIT_LENGTH, rand);
       m = p.multiply(q);
       seed = BigInteger.probablePrime(BIT_LENGTH,rand);
       seedFinal = seed.add(BigInteger.ZERO);
       if(useGenerator.contains("parity") && useGenerator.contains("significant")) {
           findLeastSignificant();
           findBitParityEven();
           createImage(parityEven, "parityEven");
           createImage(leastSig, "significant");
       }
       if(useGenerator.contains("parity") && !useGenerator.contains("significant")){
           findBitParityEven();
       }
       if(useGenerator.contains("significant") && !useGenerator.contains("parity")){
           findLeastSignificant();
           createImage(leastSig, "significant");
       }
       if(useGenerator.contains("util")){
           findRandomJava(randMathUtil);
           createImage(randomJavaUtil, "randomUtilJava");
       }
   }
   public static void findRandomJava(Random random){
       for(int x = 1; x <= Math.pow(width, 2); x++){
           randomJavaUtil += random.nextInt(2);
       }
   }
   public static void findBitParityEven(){
       for(int x = 1; x <= Math.pow(width, 2); x++) {
           seed = seed.pow(2).mod(m);
           bitsStri = convertBinary(seed);
           char[] bits = bitsStri.toCharArray();
           int counter = 0;
           for (char bit : bits) {
               if (bit == '1') {
                   counter++;
               }
           }
           if (counter % 2 != 0) {
               parityEven += "1";
           } else {
               parityEven += "0";
           }
       }
   }
   public static void findLeastSignificant(){
       seed = seedFinal;
       for(int x = 1; x <= Math.pow(width, 2); x++){
           seed = seed.pow(2).mod(m);
           leastSig += bitsStri.substring(bitsStri.length() - 1);
       }
   }
   public static String convertBinary(BigInteger value){
       StringBuilder total = new StringBuilder();
       BigInteger two = BigInteger.TWO;
       while(value.compareTo(BigInteger.ZERO) > 0){
           total.append(value.mod(two));
           value = value.divide(two);
       }
       return total.reverse().toString();
   }
   public static void createImage(String useThis, String fileName) throws IOException {
       int length = csprngBBS.width;
       // Constructs a BufferedImage of one of the predefined image types.
       BufferedImage bufferedImage = new BufferedImage(length, length, 1/*BufferedImage.TYPE_INT_RGB*/);
       // Create a graphics which can be used to draw into the buffered image
       Graphics2D g2d = bufferedImage.createGraphics();
       for (int y = 1; y <= length; y++) {
           for (int x = 1; x <= length; x++) {
               if (useThis.startsWith("1")) {
                   useThis = useThis.substring(1);
                   g2d.setColor(Color.BLACK);
                   g2d.fillRect(x, y, 1, 1);
               } else if (useThis.startsWith("0")) {
                   useThis = useThis.substring(1);
                   g2d.setColor(Color.WHITE);
                   g2d.fillRect(x, y, 1, 1);
               }
           }
           System.out.print(y + "\t");
       }
       // Disposes of this graphics context and releases any system resources that it is using.
       g2d.dispose();
       // Save as file
       File file = new File("REPLACEFILEPATHHERE" + fileName + "." + fileformat);
       ImageIO.write(bufferedImage, fileformat, file);
   }

} </lang>

Julia

Julia uses the Mersenne Twister algorithm for its default rand() function. That algorithm uses over 600 32-bit ints to represent its internal state, rather than just a product of two or three primes. <lang julia>using FileIO, ImageIO

save("randombw.png", rand(Float16, 1000, 1000)) </lang>

Perl

Perl unified the PRNG with its own internal drand48() implementation on all platforms since v5.20.0. Without a manual srand, Perl by default source the seed from "/dev/urandom" if it is available so there shouldn't be any prime prerequisite. <lang perl>use strict; use warnings; use GD;

my $img = new GD::Image(500, 500, 1);

for my $y(0..500) {

       for my $x(0..500) {
               my $color = $img->colorAllocate(rand 256, rand 256, rand 256);
               $img->setPixel($x, $y, $color);
       }

}

open F, "image500.png"; print F $img->png;</lang> image500.png (sample image, offsite)

Phix

Library: Phix/pGUI

<lang Phix>-- demo\rosetta\Pseudorandom_number_generator_image.exw include pGUI.e

IupOpen() integer w=250, h=w sequence bw = repeat(0,w*h) for x=0 to w-1 do

   for y=0 to h-1 do
       if rand(2)=2 then bw[x*h+y+1] = 255 end if
   end for

end for Ihandle image = IupImage(w,h,bw) object res = IupSaveImage(image,"bw.png","PNG") IupClose()</lang>

PicoLisp

<lang PicoLisp>(seed (in "/dev/urandom" (rd 8))) (out "image.pbm"

  (prinl "P1")
  (prinl 500 " " 500)
  (do 500
     (do 500
        (prin (if (rand T) 1 0)) )
     (prinl) ) )</lang>

Raku

MoarVM uses Mersenne Twister as its PRNG but a prime seeder is not mandatory. <lang perl6># 20200818 Raku programming solution

use Image::PNG::Portable;

srand 2⁶³ - 25; # greatest prime smaller than 2⁶³ and the max my system can take

my @data = < 250 500 1000 1500 >;

@data.map: {

  my $o = Image::PNG::Portable.new: :width($_), :height($_);
  for ^$_ X ^$_ -> @pixel { # about 40% slower if split to ($x,$y) or (\x,\y)
     $o.set: @pixel[0], @pixel[1], 256.rand.Int, 256.rand.Int, 256.rand.Int
  }
  $o.write: "image$_.png" or die;

}</lang>

Output:
file image*.png
image1000.png: PNG image data, 1000 x 1000, 8-bit/color RGBA, non-interlaced
image1500.png: PNG image data, 1500 x 1500, 8-bit/color RGBA, non-interlaced
image250.png:  PNG image data, 250 x 250, 8-bit/color RGBA, non-interlaced
image500.png:  PNG image data, 500 x 500, 8-bit/color RGBA, non-interlaced

image500.png (sample image, offsite)

Wren

Library: DOME

Wren's 'random' module uses the 'Well equidistributed long-period linear' (WELL512a) PRNG which doesn't need to be seeded with a prime number. It is in fact seeded from a sequence of 16 numbers but, if less are provided, the others are generated automatically. Typically (as here) the seed is generated from the current time. <lang ecmascript>import "dome" for Window import "graphics" for Canvas, Color import "random" for Random

class Game {

   static init() {
       Window.title = "Pseudorandom Number Generator Image"
       Window.resize(1000, 1000)
       Canvas.resize(1000, 1000)
       var r = Random.new() // generates seed from current time
       for (x in 0...1000) {
           for (y in 0...1000) {
               var c = Color.rgb(r.int(256), r.int(256), r.int(256))
               Canvas.pset(x, y, c)
           }
       }
   }
   static update() {}
   static draw(dt) {}

}</lang>