
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
p5.grain is a p5.js library for conveniently applying grain and texture overlays to artworks.
p5.grain is a p5.js library for conveniently applying film grain, seamless texture overlays, and manipulate pixels to achieve nostalgic and artistic effects in p5.js sketches and artworks.
Ideal for deterministic generative artworks, p5.grain ensures consistent film grain effects with each reload. It's perfect for platforms like fxhash, where generative artworks should use a deterministic approach to randomness.
The initial release of the library was accompanied by the article "All About That Grain" co-authored by Gorilla Sun and Joseph Miclaus. Since then, p5.grain has been regularly updated to further enhance its functionality, performance and ease of use.
Download the latest version from Releases and embed either the full version (p5.grain.js or p5.grain.min.js) or the lite version (p5.grain.lite.js or p5.grain.lite.min.js) in your project's HTML file after loading p5.js but before loading your sketch code.
<script src="./lib/p5.min.js"></script>
<!-- insert after p5.js -->
<script src="./lib/p5.grain.min.js"></script>
<script src="./sketch.js"></script>
Use the full version of p5.grain (p5.grain.js or p5.grain.min.js) while working on your sketch. This version includes error and warning reporting to help with debugging, and therefore has a larger file size. Once your sketch is final and you’re confident that no p5.grain–related errors or warnings can occur, you may want to switch to the lite version (p5.grain.lite.js or p5.grain.lite.min.js).
| File | Size | Purpose | Errors & Warnings |
|---|---|---|---|
p5.grain.js | ~ 44.3 kB | development | Yes (can be turned off) |
p5.grain.lite.js | ~ 29.2 kB | development | No |
p5.grain.min.js | ~ 13.4 kB | production | Yes (can be turned off) |
p5.grain.lite.min.js | ~ 5.6 kB | production | No |
The first step is to set up p5.grain according to your project's needs in the setup function of your sketch.
Use this setup for p5 sketches that do not need to use deterministic randomness.
function setup() {
p5grain.setup();
}
Use this setup for p5 sketches that need to use deterministic randomness.
Simply set the seed value for the random function using randomSeed(). In the example below, the seed value 16 (one million) is used, but you can choose any seed value you like:
function setup() {
randomSeed(1e6);
p5grain.setup();
}
$fx.rand() for randomness (recommended)In most cases, you will use $fx.rand() as the single source of randomness for your generative project. In this case, you simply have to configure p5.grain to also use $fx.rand() as the underlying source of randomness:
function setup() {
p5grain.setup({ random: $fx.rand });
// Use `$fx.rand()` for all randomness in your fxhash project.
}
Note: Please refer to the fxhash API reference for further information.
random for randomnessAlthough this method is not used that often for fxhash projects, you can use p5's random function as the single source of randomness for your generative project too. To achieve this, you'll need to use $fx.rand() once to generate an initial deterministic number for computing the seed value for random.
In the example below, a seed value is computed by multiplying $fx.rand() with a number of your choice. In this case, 16 (one million) is used, but you can choose any number you like:
function setup() {
randomSeed($fx.rand() * 1e6);
// noiseSeed($fx.rand() * 1e6); // <-- when using noise()
p5grain.setup();
// Now you can use `random()` for all randomness in your project, but it's still recommended that you stick to `$fx.rand()`.
}
Note: Please refer to the fxhash API reference for further information.
p5.grain currently supports the techniques: pixel manipulation, texture overlay and SVG filter. WebGL shader technique is planned for the future. Stay tuned!
Depending on how your artwork is created and whether you want to animate texture overlays, you would use p5.grain methods within the setup or draw functions of your sketch.
The best way to get you started with a technique is to check out the provided standalone examples. There is an example for each technique currently supported by the library.
Go to the standalone examples:
Here are a few examples of a basic implementation for each respective technique. All the examples below showcase how to use p5.grain in global mode and non-deterministically.
function setup() {
p5grain.setup();
// draw something...
applyMonochromaticGrain(42);
// applyChromaticGrain(42);
}
The next example demonstates modifying the artwork's pixels using the tinkerPixels(callback) function. Here the red channel of each pixel is set to a random value between 0 and 255:
function setup() {
p5grain.setup();
// draw something...
// set the red channel of each pixel to a random value between 0 and 255
tinkerPixels((index, total) => {
pixels[index] = random(0, 255); // red channel
});
}
If you only want to loop over pixels without changing them, you can use loopPixels:
loopPixels((index, total) => {
// read-only mode
// ...
});
Alternatively, you can use tinkerPixels in read-only mode:
tinkerPixels((index, total) => {
// read-only mode
// ...
}, false); // <-- shouldUpdate = false
let textureImage;
function preload() {
textureImage = loadImage('./assets/texture.jpg');
}
function setup() {
p5grain.setup();
// draw something...
textureOverlay(textureImage);
}
Note: the texture is rendered directly onto the canvas.
let textureImage;
function preload() {
textureImage = loadImage('./assets/texture.jpg');
}
function setup() {
p5grain.setup();
}
function draw() {
// draw something...
textureOverlay(textureImage, { animate: true });
}
Note: the texture is rendered directly onto the canvas.
For more concrete use cases, please have a look at the provided examples.
Errors and warnings can be disabled only when using the full version of p5.grain (p5.grain.js or p5.grain.min.js). The lite version (p5.grain.lite.js or p5.grain.lite.min.js) does not handle errors or warnings. (see Which file should I use?)
Initially, p5.grain will attempt to extend p5.js core functionality by registering new functions. If a function cannot be registered because the function name is already in use, p5.grain will log a warning with a suggestion of an alternative usage. You can prevent warnings to be logged by passing ignoreWarnings: true to the config object when setting up p5.grain.
When using p5.grain functions, the library validates the parameters passed to the respective functions, and error messages are thrown in case of invalid parameters to attract attention during development. You can prevent errors to be thrown by passing ignoreErrors: true to the config object when setting up p5.grain.
When your sketch is final and you've made sure that p5.grain-related errors or warnings cannot occur, you may use the lite version (p5.grain.lite.js or p5.grain.lite.min.js) instead of manually ignoring errors and warnings as shown below, since errors and warnings are not handled in the lite version of p5.grain.
function setup() {
// ignore warnings and errors
p5grain.setup({
ignoreWarnings: true,
ignoreErrors: true,
});
}
p5.grain supports both global and instance mode. You can read more about p5.js global and instance modes here.
All examples from above showcase p5.grain usage in p5's global mode.
In order to use p5.grain on a specific p5.js instance, you can pass the respective instance to the p5grain.setup function. Since p5.grain functions are registered to p5.prototype, you can call registered p5.grain functions directly on your p5.js instance. Here's how to use p5.grain in p5's instance mode:
let myp5 = new p5((sketch) => {
sketch.setup = () => {
// configure p5.grain to be used on a specific p5.js instance
p5grain.setup({ instance: sketch });
// draw something...
// example: apply monochromatic grain
sketch.applyMonochromaticGrain(42);
}
});
To better understand how p5.grain works in instance mode, please have a look at the provided examples.
Note: p5.grain is still in the initial development phase and the API can still change. Always review the release notes.
The library initializes the global p5grain variable to a new P5Grain instance. You can directly access the properties and functions below from the p5grain variable. The library also attempts to register all p5.grain functions except setup with p5.js by adding them to p5.prototype. This way, instead of calling, for example, p5grain.applyMonochromaticGrain(42), you can conveniently call applyMonochromaticGrain(42), although the former is also possible.
p5.grain exposes the following properties and functions:
| Property | Type | Description |
|---|---|---|
version | String | Holds the p5.grain version in SemVer format. |
ignoreWarnings | Boolean | Specifies whether warnings should be ignored. (default: false)Note: not available in the lite version. |
ignoreErrors | Boolean | Specifies whether errors should be ignored. (default: false)Note: not available in the lite version. |
| Method | Description |
|---|---|
setup([config]) | Setup and configure p5.grain features. |
applyMonochromaticGrain(amount, [shouldUpdateAlpha], [pg]) | Apply monochromatic grain. |
applyChromaticGrain(amount, [shouldUpdateAlpha], [pg]) | Apply chromatic grain. |
tinkerPixels(callback, [shouldUpdate], [pg]) | Loop through pixels and call the given callback function for every pixel. Pixels are manipulated depending on the given callback function, unless read-only mode is enabled. |
loopPixels(callback, [pg]) | Loop through pixels and call the given callback function for every pixel without updating them (read-only mode). |
textureOverlay(textureImage, config) | Blend the given texture image onto the canvas. The texture is repeated along the horizontal and vertical axes to cover the entire canvas or context. |
textureAnimate(textureElement, config) | Animate the given texture element by randomly shifting its background position. |
p5grain.setup([config])Setup and configure p5.grain features.
| Parameter | Type | Description |
|---|---|---|
config | Object | (optional) Config object to configure p5grain features. |
config.random | function | (optional) The random function that should be used for e.g. pixel manipulation, texture animation, etc. Here you could use a custom deterministic random function (e.g. $fx.rand()). (default: p5's random function) |
config.randomMode | String | (optional) Specifies the mode of the internal random function. Either float for floating-point numbers or int for integers. (default: float) |
config.instance | Object | (optional) Reference to a p5.js instance. Read how to use p5.grain with p5.js instance mode here. |
config.ignoreWarnings | Boolean | (optional) Specifies whether warnings should be ignored. (default: false)Note: not available in the lite version. |
config.ignoreErrors | Boolean | (optional) Specifies whether errors should be ignored. (default: false)Note: not available in the lite version. |
Configure p5.grain to use $fx.rand() as the internal random function:
function setup() {
p5grain.setup({ random: $fx.rand });
}
randomModeConfigure the internal random function to generate integers:
function setup() {
p5grain.setup({ randomMode: 'int' });
}
Configure the internal random function to generate floating-point numbers:
function setup() {
p5grain.setup({ randomMode: 'float' });
}
Note: randomMode is float by default, so you only need to do the above if you have previously configured randomMode to something other than float and you now need to generate random floating-point numbers again.
Make sure you’ve read the section on Ignoring errors and warnings. It explains how to suppress errors and warnings in the full version of p5.grain:
function setup() {
p5grain.setup({
ignoreErrors: true,
ignoreWarnings: true,
});
}
applyMonochromaticGrain(amount, [shouldUpdateAlpha], [pg])Apply monochromatic grain.
This function generates one random value per pixel. The random value ranges from -amount to +amount. Each generated random value is added to every RGB(A) pixel channel.
| Parameter | Type | Description |
|---|---|---|
amount | Number | The amount of granularity that should be applied. |
shouldUpdateAlpha | Boolean | (optional) Specifies whether the alpha channel should also be modified. (default: false)Note: modifying the alpha channel could have unintended consequences. Only use if you are confident in what you are doing. |
pg|img | p5.Graphics|p5.Image | (optional) The offscreen graphics buffer or image whose pixels should be manipulated. Note: When using an offscreen graphics buffer, use the usual syntax pg.applyMonochromaticGrain(amount, shouldUpdateAlpha). Only in case p5.Graphics.applyMonochromaticGrain could not be registered, use the alternative syntax p5grain.applyMonochromaticGrain(amount, shouldUpdateAlpha, pg).Note: When using an image, use the usual syntax img.applyMonochromaticGrain(amount, shouldUpdateAlpha). Only in case p5.Image.applyMonochromaticGrain could not be registered, use the alternative syntax p5grain.applyMonochromaticGrain(amount, shouldUpdateAlpha, img). |
applyChromaticGrain(amount, [shouldUpdateAlpha], [pg])Apply chromatic grain.
This function generates one random value per pixel channel. The random values range from -amount to +amount. Each generated random value is added to the respective RGB(A) channel of the pixel.
| Parameter | Type | Description |
|---|---|---|
amount | Number | The amount of granularity that should be applied. |
shouldUpdateAlpha | Boolean | (optional) Specifies whether the alpha channel should also be modified. (default: false)Note: modifying the alpha channel could have unintended consequences. Only use if you are confident in what you are doing. |
pg|img | p5.Graphics|p5.Image | (optional) The offscreen graphics buffer whose pixels should be manipulated. Note: When using an offscreen graphics buffer, use the usual syntax pg.applyChromaticGrain(amount, shouldUpdateAlpha). Only in case p5.Graphics.applyChromaticGrain could not be registered, use the alternative syntax p5grain.applyChromaticGrain(amount, shouldUpdateAlpha, pg).Note: When using an image, use the usual syntax img.applyChromaticGrain(amount, shouldUpdateAlpha). Only in case p5.Image.applyChromaticGrain could not be registered, use the alternative syntax p5grain.applyChromaticGrain(amount, shouldUpdateAlpha, img). |
tinkerPixels(callback, [shouldUpdate], [pg])Loop through pixels and call the given callback function for every pixel. Pixels are manipulated depending on the given callback function, unless read-only mode is enabled.
The callback function provides two arguments:
index: the current pixel indextotal: the total indexes countRead-only mode: updating pixels can be by-passed by setting the shouldUpdate argument to false. It is however recommended to use loopPixels if you only want to loop through pixels.
| Parameter | Type | Description |
|---|---|---|
callback | Function | The callback function that should be called on every pixel. |
shouldUpdate | Boolean | (optional) Specifies whether the pixels should be updated. (default: true) |
pg|img | p5.Graphics|p5.Image | (optional) The offscreen graphics buffer whose pixels should be manipulated. Note: When using an offscreen graphics buffer, use the usual syntax pg.tinkerPixels(callback, shouldUpdate). Only in case p5.Graphics.tinkerPixels could not be registered, use the alternative syntax p5grain.tinkerPixels(callback, shouldUpdate, pg).Note: When using an image, use the usual syntax img.tinkerPixels(callback, shouldUpdate). Only in case p5.Image.tinkerPixels could not be registered, use the alternative syntax p5grain.tinkerPixels(callback, shouldUpdate, img). |
loopPixels(callback, [pg])Loop through pixels and call the given callback function for every pixel without updating them (read-only mode).
In contrast to the tinkerPixels function, no pixel manipulations are performed with loopPixels. In other words loopPixels has the same effect as using tinkerPixels in read-only mode.
The callback function provides two arguments:
index: the current pixel indextotal: the total indexes count| Parameter | Type | Description |
|---|---|---|
callback | Function | The callback function that should be called on every pixel. |
pg|img | p5.Graphics|p5.Image | (optional) The offscreen graphics buffer whose pixels should be manipulated. Note: When using an offscreen graphics buffer, use the usual syntax pg.loopPixels(callback). Only in case p5.Graphics.loopPixels could not be registered, use the alternative syntax p5grain.loopPixels(callback, pg).Note: When using an image, use the usual syntax img.loopPixels(callback). Only in case p5.Image.loopPixels could not be registered, use the alternative syntax p5grain.loopPixels(callback, img). |
textureOverlay(textureImage, [config], [pg])Blend the given texture image onto the canvas.
The texture is repeated along the horizontal and vertical axes to cover the entire canvas (or context).
| Parameter | Type | Description |
|---|---|---|
texture | p5.Image|p5.Graphics | The texture image to blend over. |
config | Object | (optional) Config object to configure the texture overlay. |
config.width | Number | (optional) The width the texture image should have. (default: textureImage.width) |
config.height | Number | (optional) The height the texture image should have. (default: textureImage.height) |
config.mode | Constant | (optional) The blend mode that should be used to blend the texture over the canvas. Either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN, ADD or NORMAL. (default: MULTIPLY) |
config.reflect | Boolean | (optional) Specifies whether the given texture image should reflect horizontally and vertically, in order to provide seamless continuity. (default: false) |
config.animate | Boolean| Object | (optional) Specifies whether the given texture image should be animated. (default: false) |
config.animate.atFrame | Number | (optional) When animation is activated, the frame at which the texture should be shifted. When atFrame is not specified, the texture is shifted every 2nd frame. (default: 2) |
config.animate.amount | Number | (optional) When animation is activated, the maximum amount of pixels by which the texture should be shifted. The actual amount of pixels which the texture is shifted by is generated randomly. When no amount is specified, the minimum of the main canvas width or height is used. (default: min(width, height)) |
pg | p5.Graphics | (optional) The offscreen graphics buffer onto which the texture image should be drawn. Note: When using an offscreen graphics buffer, use the usual syntax pg.textureOverlay(textureImage, config). Only in case p5.Graphics.textureOverlay could not be registered, use the alternative syntax p5grain.textureOverlay(textureImage, config, pg). |
textureAnimate(textureElement, [config])Animate the given texture element by randomly shifting its background position.
| Parameter | Type | Description |
|---|---|---|
textureElement | HTMLElement| SVGElement| p5.Element | The texture element to be animated. |
config | Object | (optional) Config object to configure the texture animation. |
config.atFrame | Number | (optional) The frame at which the texture should be shifted. When atFrame is not specified, the texture is shifted every 2nd frame. (default: 2) |
config.amount | Number | (optional) The maximum amount of pixels by which the texture should be shifted. The actual amount of pixels which the texture is shifted by is generated randomly. When no amount is specified, the minimum of the main canvas width or height is used. (default: min(width, height)) |
If you need help or have questions about using p5.grain, you can find support through the following channels:
Are you considering contributing to p5.grain? Check out our contributing guidelines.
p5.grain is MIT licensed.
If you find p5.grain useful, we’d love for you to share it! Mentioning the library in your project description, tutorials, or social media posts helps others discover it and benefit from it. Thanks for spreading the word and showing your appreciation! 🙏
FAQs
p5.grain is a p5.js library for conveniently applying grain and texture overlays to artworks.
We found that p5.grain demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.