generativepy.nparray module

By Martin McBride, 2020-11-25
Tags: nparray numpy
Categories: generativepy generative art


The nparray module provides the ability to paint bitmap images and save them as either PNG images or frames.

The module is similar to the bitmap module. However, in this module images are stored as NumPy arrays, rather than PIL images. Images are stored in the same format as that used for frames.

Images are stored as 1 byte per colour, in Grey, RGB or RGBA colour space. The data is stored as a 3 dimension NumPy array, with a dtype of np.uint8. The shape of the array is [height, width, channels] where width and height are the image dimensions in pixels, and channels is 1 (Grey), 3 (RGB), or 4 (RGBA). Note the swapping of width and height, because NumPy stores data by row then column. There is more detail in the section on frames.

NumPy doesn't offer the same image processing facilities as PIL, but is has advantages in some situations:

  • NumPy is very good for arithmetic operations on pixel data.
  • It is also a good choice if you want to perform multiple operations on individual pixels (as happens, for example, in certain fractal algorithms).
  • It interfaces more easily with certain libraries such as SciPy and opencv.

You can also store save and load NumPy arrays to file, in NumPy's own format. This just stores the data in a raw format, rather than a standard image format. This can be useful for storing intermediate calculations.

make_nparray

Used to create a single PNG image.

generativepy.nparray.make_nparray(outfile, paint, pixel_width, pixel_height, channels=3)
Parameter Type Description
outfile String The path and filename for the output PNG file. It should end in '.png'.
paint Function A drawing function object, see below.
pixel_width int The width of the image that will be created, in pixels.
pixel_height int The height of the image that will be created, in pixels.
channels int The number of colour channels. 1 for greyscale, 3 for RGB, 4 for RGBA

make_nparray creates a NumPy array object, then calls the user supplied paint function to fill the array.

The paint function must have the following signature:

paint(image, pixel_width, pixel_height, frame_no, frame_count)
Parameter Type Description
image array A NumPy array object that the paint function should work on.
pixel_width int The width of the image in pixels. This is the same value as the width parameter in make_nparray.
pixel_height int The height of the image in pixels. This is the same value as the height parameter in make_nparray.
frame_no int The number of the current frame.
frame_count int The total number of frames.

frame_no and frame_count only apply to functions that create a sequence of images. The make_nparray function only ever creates one image, so the frame_no will always be 0 and the frame_count will always be 1.

make_nparrays

Used to create a sequence of PNG images. These can be combined into an animated GIF or video.

generativepy.nparray.make_nparrays(outfile, paint, pixel_width, pixel_height, count, channels=3)
Parameter Type Description
outfile String The path and filename for the output PNG file. It should end in '.png'.
paint Function A drawing function object, see below.
pixel_width int The width of the image that will be created, in pixels.
pixel_height int The height of the image that will be created, in pixels.
count int The total number of images that will be created.
channels int The number of colour channels. 1 for greyscale, 3 for RGB, 4 for RGBA

make_nparray creates a PIL Image object, then calls the user supplied paint function to fill the image.

The outfile parameter should be a base filepath. For example:

C:/temp/image

In this case the files will be created in the folder C:/temp, and their names will be based on the base name "image":

image00000000.png
image00000001.png
image00000002.png
etc

Once the images have been created, you can use an external program to convert them into an animated GIF or movie.

The paint function has the same signature as for make_nparray. In this case though, it will be called count times. The frame_count will always be set to count, and the frame_no will increment each time draw is called. You can use the frame_no value to draw a different image each time, to create animation.

make_nparray_frame

Used to create a single PNG image.

generativepy.nparray.make_nparray_frame(paint, pixel_width, pixel_height, channels=3, out=None)
Parameter Type Description
paint Function A drawing function object, see below.
pixel_width int The width of the image that will be created, in pixels.
pixel_height int The height of the image that will be created, in pixels.
channels int The number of colour channels. 1 for greyscale, 3 for RGB, 4 for RGBA.
out numpy Optionally, an existing numpy array to use for the output.

This works in a similar way to make_nparray, but instead of saving the image to a file, it returns a frame.

Normally this function will create a new array based on the pixel_width, pixel_height and channels parameters, with a type of np.uint8.

If you provide a numpy array as the out parameter, the function will use that array instead of creating a new one. The array must have a shape of:

(pixel_height, pixel_width, channels)

But it can have any integer type.

make_nparray_frames

Used to create a sequence of PNG images. These can be combined into an animated GIF or video.

generativepy.nparray.make_nparray_frames(paint, pixel_width, pixel_height, count, channels=3)
Parameter Type Description
paint Function A drawing function object, see below.
pixel_width int The width of the image that will be created, in pixels.
pixel_height int The height of the image that will be created, in pixels.
count int The total number of images that will be created.
channels int The number of colour channels. 1 for greyscale, 3 for RGB, 4 for RGBA

This works in a simlar way to make_nparrays, but instead of saving the images to a set of files, it returns a lazy sequence of frames.

save_nparray

Save a NumPy array to file.

generativepy.nparray.save_nparray(outfile, array)
Parameter Type Description
outfile String The path and filename for the output file.
array NumPy array An array containing the data.

save_nparray stores a NumPy array object to file, using NumPy's own format. The file can be re-loaded using load_nparray.

array can be any type of NumPy array. It can be a frame (which is just a NumPy array in a particular format), but it can also be any other type of NumPy array.

load_nparray

Load a NumPy array from file.

generativepy.nparray.save_nparray(infile)
Parameter Type Description
infile String The path and filename for the input file.

save_nparray loads a NumPy array object from file, using NumPy's own format. It returns the NumPy array.

The file can contain any type of NumPy array. If the data is of the correct format for a frame, the data can be used with any functions that accept frame data (for example the save_frame function in the movies module). However, this function doesn't check compatibility, it will just load whatever type of data is in the file.

make_npcolormap

Create a colour map.

generativepy.nparray.make_npcolormap(length, colors, bands=None, channels=3)
Parameter Type Description
length int Number of entries in the map
colors list of Color objects The colours to make the map, there must be at least 2
bands list of numbers The relative size of each band of colours
channels int 3 for RGB, 4 for RGBA

A colormap is a list of colours stored as a NumPy array. By default the colours are stored as 3 byte RGB values, with each colour taking a value 0 to 255.

Here is a very simple colormap:

map = make_npcolormap(8, [Color('black'), Color('red')])

This creates a map of 8 colours, that gradually change from black (RGB value [0, 0, 0]) to red (RGB value [255, 0, 0]). The colour changes gradually between those values

[[  0   0   0]   # black
 [ 36   0   0]
 [ 72   0   0]
 [109   0   0]
 [145   0   0]
 [182   0   0]
 [218   0   0]
 [255   0   0]] # red

Here is a more advanced version:

map = make_npcolormap(12, [Color('black', 0), Color('red', 0.5), Color('white', 1)], [1, 2], channels=4)

Here we are creating a list of 12 colours. We have set channels to 4, so we will create an RGBA colour map, that is 4 bytes per colour with the last byte representing transparency.

There are 3 items in the colour list, so the colours will change from transparent black (RGBA value [0, 0, 0, 0]) to 50% opaque red (RGBA value [255, 0, 0, 255]) to fully opaque white (RGBA value [255, 255, 255, 255]).

We have also included a band parameter of [1, 2]. This gives the relative length of each band, so the first transition from black to red should take half as many steps as the second transition from red to white.

Here is the output. this time each colour has 4 components. The transition from black to red takes 4 steps, the transition from red to white takes 8 steps.

[[  0   0   0   0]   # black
 [ 85   0   0  42]
 [170   0   0  85]
 [255   0   0 127]   # red
 [255   0   0 127]
 [255  36  36 145]
 [255  72  72 163]
 [255 109 109 182]
 [255 145 145 200]
 [255 182 182 218]
 [255 218 218 236]
 [255 255 255 255]] # white

Notice that the number of bands is always one less than the number of colours.

apply_npcolormap

Apply a colour map to a monochrome image.

generativepy.nparray.apply_npcolormap(out, counts, npcolormap)
Parameter Type Description
out NumPy array Output array to receive colour data
counts NumPy array Input array, monochrome image
npcolormap colormap A colormap

Applies a colormap.

This takes a monochrome image, counts, and uses the npcolormap to convert each grayscale pixel into a colour. Each pixel is stored in the corresponding element of the out array.

Typically counts will be a NumPy array of shape (height, width, 1), and some integer data type.

out will normally be an empty array of shape (height, width, 3) and type np.uint8. The colormap will convert each integer value in counts into an RGB value that gets stored in out.

Scaler class

The Scaler class defined in the bitmap module can also be used with the nparray class.

See also

If you found this article useful, you might be interested in the book NumPy Recipes or other books by the same author.

Join the PythonInformer Newsletter

Sign up using this form to receive an email when new content is added:

Popular tags

2d arrays abstract data type alignment and angle animation arc array arrays bar chart bar style behavioural pattern bezier curve built-in function callable object chain circle classes clipping close closure cmyk colour combinations comparison operator comprehension context context manager conversion count creational pattern data science data types decorator design pattern device space dictionary drawing duck typing efficiency ellipse else encryption enumerate fill filter font font style for loop formula function function composition function plot functools game development generativepy tutorial generator geometry gif global variable gradient greyscale higher order function hsl html image image processing imagesurface immutable object in operator index inner function input installing iter iterable iterator itertools join l system lambda function latex len lerp line line plot line style linear gradient linspace list list comprehension logical operator lru_cache magic method mandelbrot mandelbrot set map marker style matplotlib monad mutability named parameter numeric python numpy object open operator optimisation optional parameter or pandas partial application path pattern permutations pie chart pil pillow polygon pong positional parameter print product programming paradigms programming techniques pure function python standard library radial gradient range recipes rectangle recursion reduce regular polygon repeat rgb rotation roundrect scaling scatter plot scipy sector segment sequence setup shape singleton slice slicing sound spirograph sprite square str stream string stroke structural pattern subpath symmetric encryption template tex text text metrics tinkerbell fractal transform translation transparency triangle truthy value tuple turtle unpacking user space vectorisation webserver website while loop zip zip_longest