# p5.Image is fuzzy

**URL:** https://discourse.processing.org/t/p5-image-is-fuzzy/23395
**Category:** Coding Questions
**Created:** [August 20, 2020, 5:46pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395 "2020-08-20T17:46:27Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Hapiel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hapiel/32/10226_2.png) [@Hapiel](https://discourse.processing.org/u/Hapiel)
#### Post date: [August 20, 2020, 5:46pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/1 "2020-08-20T17:46:27Z")

</div>

As soon as a p5.Graphics element gets stored in a p5.Image element, it gets a bit fuzzier. Some smoother anti alias I think.  
The effect is subtle, but visible to me.

Is there a way to prevent this?

I’m trying to make a small drawing app which I can use to try out all the brushes I might make with p5. I wrote an undo function which uses p5.Images to store previous states of the image. I wish those states could be stored in a lossless format, is that possible?  
Or is there a way to do what I did by copying p5.Graphics objects? I haven’t yet worked out how…  
My current version: [https://editor.p5js.org/hapiel/sketches/rROK3rm\_F](https://editor.p5js.org/hapiel/sketches/rROK3rm_F)

---

<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: [August 20, 2020, 6:01pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/2 "2020-08-20T18:01:28Z")

</div>

> [@Hapiel](#):
>
> Or is there a way to do what I did by copying p5.Graphics objects?

> **[reference | p5.js](https://p5js.org/reference/#/p5.Image/get)**
>
> p5.js a JS client-side library for creating graphic and interactive experiences, based on the core principles of Processing.

---

<div class="post-metadata">

### Author: ![Hapiel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hapiel/32/10226_2.png) [@Hapiel](https://discourse.processing.org/u/Hapiel)
#### Post date: [August 20, 2020, 6:04pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/3 "2020-08-20T18:04:39Z")

</div>

I originally used `get()` instead of `myImg.copy`, it is even still in the file (see line 118). So line 112 to 116 can be replaced with line 120. But then I copy everything that is on screen, and I want to only copy a single layer, which is `layerDraw` or stored in my object as `layer`.

I tried `layer.get()` but that doesn’t seem to work?

EDIT: Of course that didn’t work, because as usual, I forgot the keyword ‘this’. But now that it does work (locally, haven’t updated the editor file), it still produces fuzzy images…

EDIT2: also using get() I can’t reuse my old ‘add background’ system (112 - 115), so I would have to rewrite a bit if I want to use get I guess?

---

<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: [August 20, 2020, 6:21pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/4 "2020-08-20T18:21:02Z")

</div>

> [@Hapiel](#):
>
> I tried `layer.get()` but that doesn’t seem to work?

- I confess I’ve never used method **get()** on p5.js.
- On Processing PGraphics is a subclass of class PImage and everything works as expected.
- However for unknown reasons p5js devs took a wrong turn for not doing the same for p5.Graphics & p5.Image.
- Regardless, **get()** creates a clone, which is wasteful for most cases.
- Best technique is to transfer the _pixels[]_ content to another 1, which avoids unnecessary cloning:  
[reference | p5.js](http://p5js.org/reference/#/p5.Image/pixels)

---

<div class="post-metadata">

### Author: ![Hapiel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hapiel/32/10226_2.png) [@Hapiel](https://discourse.processing.org/u/Hapiel)
#### Post date: [August 20, 2020, 8:20pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/5 "2020-08-20T20:20:01Z")

</div>

I just tried to replace my copy function with pixels. It makes the code a bit longer, but it kinda works

```auto
    this.layer.loadPixels();
    this.img[this.img.length - 1].loadPixels();

    for (let i = 0; i < this.layer.pixels.length; i++) {
      this.img[this.img.length - 1].pixels[i] = this.layer.pixels[i];
      
    }
    // this.img[this.img.length - 1].pixels = this.layer.pixels;

    this.img[this.img.length - 1].updatePixels();

```

Why does the for loop work, but the simple line that I commented out does not? Don’t they do the same thing?

EDIT: I just discovered that I have to clone an array by saying `array1 = [...array2];` or `array1 = array2.splice();`, but neither work here too…  
`this.img[this.img.length - 1].pixels = [...this.layer.pixels];`

Anyway, I can’t add a background to this, because the way I add the background is by adding it to a picture, and then copying the drawing on top. But the whole copying function is what gives the fuzzyness… 😕  
I’m still confused as to how to solve this. Perhaps I can add the background in another place (and then double check if this pixel swapping actually solves the fuzzyness )

EDIT: found a place to enter the background. All works now, except that I have this rather wasteful for loop in my code…

---

<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: [August 20, 2020, 8:31pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/6 "2020-08-20T20:31:57Z")

</div>

> [@Hapiel](#):
>
> Don’t they do the same thing?

No! The loop is dealing w/ the indexed contents of the arrays.

While the single assignment you’re making 2 properties pointing to the same array.

---

<div class="post-metadata">

### Author: ![Hapiel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hapiel/32/10226_2.png) [@Hapiel](https://discourse.processing.org/u/Hapiel)
#### Post date: [August 20, 2020, 8:45pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/7 "2020-08-20T20:45:41Z")

</div>

I think all is sorted now, this is the final(ish) version:  
[https://editor.p5js.org/hapiel/sketches/D8U0fLVc8](https://editor.p5js.org/hapiel/sketches/D8U0fLVc8)

Thank you @GoToLoop for pointing me towards pixels!

I still wonder if the for loop at 115 can be replaced with something like at 119 (wouldn’t that be faster?), other than that I’m super happy with it, 😃

---

<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: [August 20, 2020, 8:52pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/8 "2020-08-20T20:52:42Z")

</div>

> [@Hapiel](#):
>
> , except that I have this rather wasteful for loop in my code…

I like to cache values in local variables: 😉

```auto
const { layer, img } = this, lastImg = img[img.length - 1];
layer.loadPixels(), lastImg.loadPixels();

const { pixels: src } = layer, { pixels: dst } = lastImg, { length: len } = src;
for (let i = 0; i < len; dst[i] = src[i++]);
lastImg.updatePixels();

```

---

<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: [August 20, 2020, 9:29pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/9 "2020-08-20T21:29:41Z")

</div>

> [@Hapiel](#):
>
> EDIT: I just discovered that I have to clone an array by saying `array1 = [...array2];` or `array1 = array2.splice();` , but neither work here too…  
> `this.img[this.img.length - 1].pixels = [...this.layer.pixels];`

The statement above creates a new [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) w/ the contents of `layer.pixels[]` and replaces `img[-1].pixels[]` w/ that.

However that is a big mistake, b/c _pixels[]_ is expected to be of datatype Uint8ClampedArray, not some vanilla Array as you’re doing there:

> **[reference | p5.js](https://p5js.org/reference/#/p5/pixels)**
>
> p5.js a JS client-side library for creating graphic and interactive experiences, based on the core principles of Processing.

> Description: [Uint8ClampedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) containing the values for all the pixels in the display window.

Moreover, typed arrays don’t have the method [**splice()**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice); so definitely `array1 = array2.splice();` won’t work!

So you should just access the indexed content and refrain from reassigning _pixels[]_ w/ your own array.

Most you can do is replace the loop w/ the typed array’s method **set()**:

> **[TypedArray.prototype.set() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/set)**
>
> The set() method of TypedArray instances stores multiple values in the typed
> array, reading input values from a specified array.

```auto
const { layer, img } = this, lastImg = img[img.length - 1];
layer.loadPixels(), lastImg.loadPixels();

lastImg.pixels.set(layer.pixels);
lastImg.updatePixels();

```

---

<div class="post-metadata">

### Author: ![Hapiel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hapiel/32/10226_2.png) [@Hapiel](https://discourse.processing.org/u/Hapiel)
#### Post date: [August 20, 2020, 11:23pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/10 "2020-08-20T23:23:54Z")

</div>

Thanks for all the info, you’ve been very helpful.

In the end, I just discovered that after all the modifications I made, and introducing a clear() before displaying the new content on screen, I got rid of the fuzzy lines too. Turns out I could use get() after all, and never needed to use anything as complex as copying the pixel data.

Silly me for looking in the wrong place, but at least it is now al working smooth! And with the get() replacing the for loop it can handle waaaay larger canvasses!

---

<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: [August 20, 2020, 11:42pm UTC](https://discourse.processing.org/t/p5-image-is-fuzzy/23395/11 "2020-08-20T23:42:05Z")

</div>

> [@Hapiel](#):
>
> And with the **get()** replacing the for loop it can handle waaaay larger canvasses!

Take notice that each **get()** creates a new HTMLCanvasElement, which is not a light object btW:

> **[HTMLCanvasElement - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement)**
>
> The HTMLCanvasElement interface provides properties and methods for manipulating the layout and presentation of elements. The HTMLCanvasElement interface also inherits the properties and methods of the HTMLElement interface.

Depending on how many of them are created each **draw()** iteration, the sketch can even crash some mobile devices:

> [@Is noise too much for mobile devices to handle in p5js?](https://discourse.processing.org/t/is-noise-too-much-for-mobile-devices-to-handle-in-p5js/23048):
>
> Hello Forum slight_smile I am working on a visualizer project for mobile devices and I found a great example of clouds using noise on Open Processing. It works good on laptops and crashes on mobile devices. Are noise operations too much for phones to display? Here’s the sketch: [https://www.openprocessing.org/sketch/666329](https://www.openprocessing.org/sketch/666329)

Mutating already existing _pixels[]_ saves memory and can be more performant.
