Skip to content

saveGif issue when used with translucent background #5924

@meiamsome

Description

@meiamsome

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build Process
  • Unit Testing
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

p5.js version

1.5.0

Web browser and version

Firefox 108.0

Operating System

Linux, Mac

Steps to reproduce this

Steps:

  1. Create a sketch that uses a translucent background and then use saveGif
  2. The call to saveGif reuslts in the canvas being cleared due to pixelDensity call here:
    this.pixelDensity(1);
  3. The resulting GIF starts without the faded past frames, resulting in a jump:
    test
    Compared to how the GIF should look:
    testFix

Snippet:

Example sketch that saves two gifs, one with the bug (test.gif) and one using the workaround of overriding pixelDensity (testFix.gif)

p5.js Web Editor link

function setup() {
  createCanvas(100, 100);
  angleMode(DEGREES);
  background(0, 0, 0, 255);
  pixelDensity(1);
}

function draw() {
  background(0, 0, 0, 25);
  
  color(255, 255, 255);
  const angle = 10 * frameCount % 360;
  circle(50 + 25 * sin(angle), 50 + 25 * cos(angle), 10);
  
  // Wait for a full rotation before saving a gif:
  if (frameCount === 36) {
    setTimeout(
      () => saveGif(
        'test.gif', 
        36,
        {
          delay: 0,
          units: 'frames',
        },
      ),
      0,
    );
  }
  if (frameCount === 108) {
    // Override pixelDensity to prevent the canvas being cleared
    p5.instance.pixelDensity = () => {};
    setTimeout(
      () => saveGif(
        'testFix.gif', 
        36,
        {
          delay: 0,
          units: 'frames',
        },
      ),
      0,
    )
  }
}

Suggestions

  1. It might be worth changing saveGif to not override the pixelDensity of the current sketch, which would require more complicated maths for the buffers but prevents the change
  2. It might be worth having an option on saveGif to render n frames before starting the recording. This option might be useful anyway, as you'd be able to rewrite the sketch above to something like:
function setup() {
  createCanvas(100, 100);
  angleMode(DEGREES);
  background(0, 0, 0, 255);
  pixelDensity(1);
  noLoop();
  setTimeout(
    () => saveGif(
      'test.gif', 
      36,
      {
        delay: 0,
        // Wait for a full rotation before saving a gif:
        preamble: 36,
        units: 'frames',
      },
    ),
    0,
  );
}

function draw() {
  background(0, 0, 0, 25);
  
  color(255, 255, 255);
  const angle = 10 * frameCount % 360;
  circle(50 + 25 * sin(angle), 50 + 25 * cos(angle), 10);
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions