# Gifs generated with saveGif() only contain a single color

**URL:** https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954
**Category:** p5.js
**Created:** [December 1, 2022, 4:06am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954 "2022-12-01T04:06:16Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Kevin](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kevin/32/2297_2.png) [@Kevin](https://discourse.processing.org/u/Kevin)
#### Post date: [December 1, 2022, 4:06am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/1 "2022-12-01T04:06:16Z")

</div>

Hey friends, long time no see!

I’ve been pretty excited about the [`saveGif()`](https://p5js.org/reference/#/p5/saveGif) function, but I’m having trouble getting it to work as expected.

Here’s some code I’m trying:

```auto
let colors = ['red', 'yellow', 'orange', 'green', 'blue', 'purple'];

function setup() {
  createCanvas(400, 400);
  background(32);
  noSmooth();
}

function draw() {
  noStroke();
  fill(random(colors));
  circle(random(width), random(height), random(10, 20));
}

function mousePressed(){
  saveGif('test', 5);
}

```

[(View the sketch in the p5.js editor here)](https://editor.p5js.org/KevinWorkman/sketches/M6YoHohLl)

The screen fills up with randomly colored circles (I limited the colors in case the issue is related to the gif color palette limitations), and when I press the mouse, I expect a gif of those circles to be saved.

Here’s the GIF exported using a tool called [Screen to Gif](https://www.screentogif.com/):

![animation of randomly colored circles](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/1/5/155fdcb9299b96f08cbb53398d29dc1cd4555647.gif)

However, if I press my mouse to trigger the `saveGif()` function, I get something like this:

![animation of single-colored circles](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/0/b/0bcc07fbc54dea612ea014421174335d8e213aa9.gif)

The gif appears to only contain a single color, although I think maybe I have a mix of yellow and black circles. It might also be worth noting that it’s a _different_ color every time I click:

![animation of red circles](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/f/7/f794a763277c3bee7ac848345a02a596a41f6bba.gif)

The replies to the [tweet announcing this feature](https://twitter.com/p5xjs/status/1584251633218641920) seem to include a mix of folks with multi-colored gifs, and folks with gifs like mine.

I’ve tried both Firefox and Chrome on Windows, and Chrome on Android.

Can anybody help me understand what’s happening? Is this a known behavior of the `saveGif()` function? Can I do anything to make sure my gifs export correctly?

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 1, 2022, 8:04am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/2 "2022-12-01T08:04:45Z")

</div>

Hi @Kevin,

Hmmm! Never used the saveGif yet, but I’ve tested your code and have the same issue.  
Nevertheless, if I switch to WEBGL renderer, it seem to work better (ie. as expected !?) …

```auto
let colors = ['red', 'yellow', 'orange', 'green', 'blue', 'purple'];

function setup() {
  createCanvas(400, 400, WEBGL);
  background(32);
  noSmooth();
  noStroke();
}

function draw() {     
  fill(random(colors));
  circle(random(width)-width/2, random(height)-height/2, random(10, 20));
}

function mousePressed(){
  saveGif('test', 5);
}

```

Maybe you should raise an [issue on p5js github](https://github.com/processing/p5.js/issues) with your code example for clarification …

Cheers  
— mnse

---

<div class="post-metadata">

### Author: ![Kevin](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kevin/32/2297_2.png) [@Kevin](https://discourse.processing.org/u/Kevin)
#### Post date: [December 3, 2022, 5:57pm UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/3 "2022-12-03T17:57:00Z")

</div>

Thanks for the reply. Interestingly, if I switch to WEBGL I only see black, no circles.

**Edit:** It turns out that in WEBGL mode, all of my circles draw in the lower-right quadrant. If my screen magnification is set to 100%, then the GIF shows the circles in the lower-right quadrant.

![circles in lower-right quadrant](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/c/c/cc9d822f00947d314f46a778daba83e4a45fd256.gif)

If it’s set to 150% (the default), then I don’t see the circles in the saved gif.

![no cicles](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/4/3/43fd51c8db363b6afc425c132e5a0393190483bc.gif)

I filed a bug here: [Gifs generated with saveGif() only contain a single color · Issue #5881 · processing/p5.js · GitHub](https://github.com/processing/p5.js/issues/5881)

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 3, 2022, 6:29pm UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/4 "2022-12-03T18:29:59Z")

</div>

Hi @Kevin,

> [@Kevin](#):
>
> It turns out that in WEBGL mode, all of my circles draw in the lower-right quadrant.

That’s a normal behavior. This is because the origin (0,0) represents the center of the screen. If you want to change use the translate function to shift it back.

```auto
translate(-width/2,-height/2,0);

```

> **[Getting started with WebGL in p5](https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5)**
>
> p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Proces...

Cheers  
— mnse

---

<div class="post-metadata">

### Author: ![Kevin](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kevin/32/2297_2.png) [@Kevin](https://discourse.processing.org/u/Kevin)
#### Post date: [December 4, 2022, 12:22am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/5 "2022-12-04T00:22:34Z")

</div>

> [@mnse](#):
>
> That’s a normal behavior. This is because the origin (0,0) represents the center of the screen. If you want to change use the translate function to shift it back.

Ahh thanks for clearing that up!

Btw thanks to Dave Pagurek, looks like there’s a fix for the color bug:

> <https://github.com/processing/p5.js/issues/5881#issuecomment-1336246822>
>
> \### Most appropriate sub-area of p5.js?
> 
> \- \[\] Accessibility
> \- \[\] Color
> \- \[… \] Core/Environment/Rendering
> \- \[\] Data
> \- \[\] DOM
> \- \[\] Events
> \- \[\] Image
> \- \[\] IO
> \- \[\] Math
> \- \[\] Typography
> \- \[X\] Utilities
> \- \[\] WebGL
> \- \[\] Build Process
> \- \[\] Unit Testing
> \- \[\] Internalization
> \- \[\] Friendly Errors
> \- \[\] Other (specify if possible)
> 
> \### p5.js version
> 
> 1.5.0
> 
> \### Web browser and version
> 
> Chrome 107.0.5304.107
> 
> \### Operating System
> 
> Windows
> 
> \### Steps to reproduce this
> 
> I originally posted this in the Processing forum: https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954
> 
> I’ve been pretty excited about the \[\`saveGif()\`\](https://p5js.org/reference/#/p5/saveGif) function, but I’m having trouble getting it to work as expected.
> 
> Here’s some code I’m trying:
> 
> \`\`\`
> let colors = \['red', 'yellow', 'orange', 'green', 'blue', 'purple'\];
> 
> function setup() {
> createCanvas(400, 400);
> background(32);
> noSmooth();
> }
> 
> function draw() {
> noStroke();
> fill(random(colors));
> circle(random(width), random(height), random(10, 20));
> }
> 
> function mousePressed(){
> saveGif('test', 5);
> }
> \`\`\`
> 
> \[(View the sketch in the p5.js editor here.)\](https://editor.p5js.org/KevinWorkman/sketches/M6YoHohLl)
> 
> The screen fills up with randomly colored circles (I limited the colors in case the issue is related to the gif color palette limitations), and when I press the mouse, I expect a gif of those circles to be saved.
> 
> Here’s the GIF exported using a tool called \[Screen to Gif\](https://www.screentogif.com/):
> 
> !\[animation of randomly colored circles
> \](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/1/5/155fdcb9299b96f08cbb53398d29dc1cd4555647.gif)
> 
> However, if I press my mouse to trigger the saveGif() function, I get something like this:
> 
> !\[animation of single-colored circles\](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/0/b/0bcc07fbc54dea612ea014421174335d8e213aa9.gif)
> 
> The gif appears to only contain a single color, although I think maybe I have a mix of yellow and black circles. It might also be worth noting that it’s a different color every time I click:
> 
> !\[animation of red circles\](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/f/7/f794a763277c3bee7ac848345a02a596a41f6bba.gif)
> 
> The replies to the \[tweet announcing this feature\](https://twitter.com/p5xjs/status/1584251633218641920) seem to include a mix of folks with multi-colored gifs, and folks with gifs like mine.
> 
> I’ve tried both Firefox and Chrome on Windows, and Chrome on Android. I've also tried switching to WEBGL mode, which seems to fix the problem for other folks, but I just see black in the recorded gif in WEBGL mode.
> 
> \*\*Edit:\*\* It turns out that in WEBGL mode, all of my circles draw in the lower-right quadrant. If my screen magnification is set to 100%, then the GIF shows the circles in the lower-right quadrant.
> 
> !\[circles in lower-right quadrant\](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/c/c/cc9d822f00947d314f46a778daba83e4a45fd256.gif)
> 
> If it's set to 150% (the default), then I don't see the circles in the saved gif.
> 
> !\[no circles\](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/4/3/43fd51c8db363b6afc425c132e5a0393190483bc.gif)
> 
> Can anybody help me understand what’s happening? Is this a known behavior of the \`saveGif()\` function? Can I do anything to make sure my gifs export correctly?

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [December 4, 2022, 1:01am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/6 "2022-12-04T01:01:50Z")

</div>

> [@Kevin](#):
>
> , looks like there’s a fix for the color bug

According to its bug pull explanation: 🐛

> <https://github.com/processing/p5.js/pull/5883>
>
> There are a few palette-related changes in here:
> 
> \### 1. The palette for gifs …was based only on the first frame
> Resolves https://github.com/processing/p5.js/issues/5881
> 
> When building the list of colors to quantize into a palette, we accidentally were adding the first frame over and over instead of all the frames of the gif. It now sends all the frames' colors into quantization. I didn't notice this when looking at the original PR, oops!
> 
> Input sketch: https://editor.p5js.org/davepagurek/sketches/wZWa8l9jh
> \<table\>
> \<tr\>\<th\>Before\</th\>\<th\>After\</th\>\</tr\>
> \<tr\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464666-ef2b77ef-b51f-4b34-9843-5e258e6514bf.gif" /\>
> \</td\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464675-0cbe0974-ad09-4adc-8264-d7297b6ab3f6.gif" /\>
> \</td\>
> \</tr\>
> \</table\>
> 
> \### 2. Some elements left trails in gifs
> Resolves https://github.com/processing/p5.js/issues/5882
> 
> To determine what frames are unchanged between frames of gifs, we were comparing colors in the original frames. Unfortunately, the same colors in the input frames don't necessarily map to the same output frame color depending on the ordering of colors in the frames, which I'll go into a bit later. If we instead apply the gif palette first, and then check for a difference in the palette colors, we don't see any more trails. Unfortunately, this reveals some flickering caused by that nondeterminism I mentioned:
> 
> Input sketch: https://editor.p5js.org/davepagurek/sketches/ANZ-YhpXA
> \<table\>
> \<tr\>\<th\>Before\</th\>\<th\>Broken in a different way 🥲\</th\>\</tr\>
> \<tr\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464790-200c6ae1-9fc0-44ab-9ee6-729d2a8a1c9c.gif" /\>
> \</td\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464942-0f77991f-d046-424a-baff-9b6e2355693d.gif" /\>
> \</td\>
> \</tr\>
> \</table\>
> 
> The \`applyPalette\` method from the gif encoding library we use, for the sake of speed, caches the palette color so it doesn't have to check again when it encounters the same color. However, the cache key is not the original color, but instead a bit-reduced version of the color (presumably also for speed/memory.) Unfortunately, this means that multiple input colors get put into the same cache key, and not all of those input colors necessarily correspond to the same palette color.
> 
> To avoid this issue, I've stopped using \`applyPalette\` from the library, and wrote a new version. It's mostly based on the library's code, but:
> \- it caches colors based on the original input to avoid the flickering issue
> \- it also uses the same cache for all frames rather than resetting it each frame, hopefully yielding better performance for sketches that share a lot of colors between frames
> 
> Now, finally, the output looks more expected! I've kept the change I made to compare the gif palette colors rather than the source colors because, even though the original method should still work with the fixed palette application, comparing the palette involves 1/4 the number of comparisons.
> 
> Input sketch: https://editor.p5js.org/davepagurek/sketches/ANZ-YhpXA
> \<table\>
> \<tr\>\<th\>Before\</th\>\<th\>After\</th\>\</tr\>
> \<tr\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464790-200c6ae1-9fc0-44ab-9ee6-729d2a8a1c9c.gif" /\>
> \</td\>
> \<td\>
> \<img src="https://user-images.githubusercontent.com/5315059/205464793-6c801756-af8b-4a44-ac1c-94c7ec9a2080.gif" /\>
> \</td\>
> \</tr\>
> \</table\>
> 
> \#### PR Checklist
> \- \[x\] \`npm run lint\` passes
> \- \[\] \[Inline documentation\] is included / updated
> \- \[\] \[Unit tests\] are included / updated
> 
> I haven't added unit tests for these because exporting a gif seems a bit heavy of an operation for a unit test. I can add a manual test if you think that would be helpful though!

This fix is gonna increase the gif file’s size even for sketches that didn’t have this bug b/c it won’t use a cached palette anymore. 🎨

Perhaps they should maintain the old palette cache buggy behavior as an extra { option } 3rd parameter for sketches that don’t need this fix and prefer a smaller gif file. 🤔

---

<div class="post-metadata">

### Author: ![Kevin](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kevin/32/2297_2.png) [@Kevin](https://discourse.processing.org/u/Kevin)
#### Post date: [December 4, 2022, 11:56pm UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/7 "2022-12-04T23:56:15Z")

</div>

> [@GoToLoop](#):
>
> This fix is gonna increase the gif file’s size

How much of a size increase is this going to cause?

If the size increase is too large, I could see a few other options, including modifying the documentation to explain that your first frame should contain all of the colors you’ll need in your palette.

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [December 5, 2022, 12:03am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/8 "2022-12-05T00:03:26Z")

</div>

> [@Kevin](#):
>
> How much of a size increase is this going to cause?

No idea! I only know that less usage of palettes the lesser the gif’s file size. 🤷‍♂️

It was just an advice to keep the old behavior via the 3rd parameter, which is an object argument that customizes the behavior of the function. 💡

---

<div class="post-metadata">

### Author: ![Kevin](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kevin/32/2297_2.png) [@Kevin](https://discourse.processing.org/u/Kevin)
#### Post date: [December 5, 2022, 12:25am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/9 "2022-12-05T00:25:30Z")

</div>

I left a comment over in the PR: [Fix palette generation bugs in saveGif() by davepagurek · Pull Request #5883 · processing/p5.js · GitHub](https://github.com/processing/p5.js/pull/5883#issuecomment-1336568819)

---

<div class="post-metadata">

### Author: ![davepagurek](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/davepagurek/32/17535_2.png) [@davepagurek](https://discourse.processing.org/u/davepagurek)
#### Post date: [December 5, 2022, 1:14am UTC](https://discourse.processing.org/t/gifs-generated-with-savegif-only-contain-a-single-color/39954/10 "2022-12-05T01:14:33Z")

</div>

Hey everyone! I added a reply in the PR, but I’ll also add it here. tl;dr the palette size should be the same as before if you didn’t have this issue with your first frame not having all the colors 🙂

> If your gif only had one color on the first frame, this will probably increase the file size as now the gif’s palette will include the whole animation’s colours, but for other sketches, I think the file size will remain the same. The caching I was mentioning happens when mapping input colors (uncompressed, from the original sketch) to the 256-color gif palette. With or without caching, it still gets mapped to the same palette size; the cache is just there to remember what palette color an input color mapped to so that we don’t have to check again. The old code compressed the input colors a little in order to make a cache key, and the new code doesn’t. This means that, while constructing the gif, the cache JS object will use more browser memory than before, but since that isn’t part of the outputted gif, the file size should be effectively the same.
