Skip to content

[p5.js 2.0+ Bug Report]: tint() has no effect on images in 2D mode (states.tint is a p5.Color but read as an array → globalAlpha = NaN) #8910

@shibomb

Description

@shibomb

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • WebGPU
  • p5.strands
  • Build process
  • Unit testing
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

p5.js version

2.3.0 (also reproduces on @latest)

Web browser and version

Arc Version 1.150.1 (81866) Chromium Engine Version 149.0.7827.103

Operating system

MacOSX

Steps to reproduce this

Steps:

tint() has no effect on images in 2D mode. Both alpha tinting
(tint(255, alpha)) and color tinting are silently ignored — the image is
always drawn fully opaque and untinted. The official reference example for
tint() does not work either.

Snippet:

see https://beta.p5js.org/reference/p5/tint/
or this snippet:

let img;
function setup() {
  createCanvas(200, 200);
  img = createImage(100, 100);
  img.loadPixels();
  for (let i = 0; i < img.pixels.length; i += 4) {
    img.pixels[i] = 255;           // R
    img.pixels[i + 3] = 255;       // A
  }
  img.updatePixels();
}
function draw() {
  background(220);
  tint(255, 50);     // expect ~20% opacity
  image(img, 50, 50);
  noTint();
}

Expected vs actual

  • Expected: a faint (~20% opacity) red square.
  • Actual: a fully opaque red square. tint(255, 0) does not hide the
    image either, and color tints (e.g. tint(255, 0, 0)) have no effect.

Root cause (from reading the bundled source)

  • tint() stores a p5.Color object:
    this._renderer.states.setValue('tint', this.color(...args)).
  • The 2D renderer's _getTintedImageCanvas() treats states.tint as a
    numeric array: it reads this.states.tint[3] / 255 and
    this.states.tint.slice(0, 3), and branches on
    this.states.tint[0] < 255 || ....
  • A p5.Color instance has no numeric indices and no .slice(), so
    states.tint[3] is undefinedctx.globalAlpha = NaN, which the canvas
    ignores → the image is drawn at full opacity. For color tints, every
    states.tint[i] < 255 is undefined < 255 === false, so the color branch
    is never entered. Net result: tint() is a no-op for images.

A fix would convert the stored color to an RGBA array before use in
_getTintedImageCanvas() (e.g. via the color's level/_array accessor), or
store the tint as an array in the tint() setter.

I'm happy to open a PR if that helps.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions