# Image() is slow, are there any alternatives?

**URL:** <https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146>\
**Category:** Coding Questions\
**Created:** [April 25, 2020, 7:51pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146 "2020-04-25T19:51:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 25, 2020, 7:51pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/1 "2020-04-25T19:51:09Z")

</div>

I am rendering about 1024 images, they have to be scaled up, I store the scaled-up version so it is a bit faster. these images are covering the whole screen, and I would like to get at least 60 fps when rendering this. Is there any faster way, because as soon as I remove the image() from my nested for loops, it runs 60 fps, so this is because of image().

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/3a5aa78d62697032e239822825cd615c31c9014f.png)

I am rendering all these tiles, and it is slowing me down. (yes I am only rendering the ones on the screen)

---

<div class="post-metadata">

**Author:** ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)\
**Post date:** [April 25, 2020, 8:53pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/2 "2020-04-25T20:53:00Z")

</div>

You could render small chunks of your map to `PGraphics` objects and display those instead of all images.

[Take a look at the reference.](https://processing.org/reference/PGraphics.html)

---

<div class="post-metadata">

**Author:** ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)\
**Post date:** [April 25, 2020, 9:16pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/3 "2020-04-25T21:16:58Z")

</div>

I wrote a small example program that you should just be able to run. Doesn’t seem to make that much of a difference after all, but see for yourself:

```auto
int chunkSizePixels;
PImage source;
PGraphics[][] chunks;

void setup() {
  size(1000, 700);

  source = loadImage("https://opengameart.org/sites/default/files/images/grass_test_2.png");
  source.resize(32, 32);
  int imgWidth = source.width, imgHeight = source.height;

  chunkSizePixels = int(width / float(4));
  chunks = new PGraphics[ceil(width / float(chunkSizePixels))][ceil(height / float(chunkSizePixels))];

  for (int i = 0; i < chunks.length; i++)
    for (int j = 0; j < chunks[i].length; j++) {
      PGraphics chunk = chunks[i][j] = createGraphics(chunkSizePixels, chunkSizePixels);
      chunk.beginDraw();

      for (int k = 0; k < ceil(chunkSizePixels / float(imgWidth)); k++)
        for (int m = 0; m < ceil(chunkSizePixels / float(imgHeight)); m++)
          chunk.image(source, k * imgWidth, m * imgHeight);

      chunk.endDraw();
    }
}

void draw() {
  background(0); 

  long start = millis(); 

  for (int i = 0; i < ceil(width / float(source.width)); i++)
    for (int j = 0; j < ceil(height / float(source.height)); j++)
      image(source, i * source.width, j * source.height); 

  // for (int i = 0; i < chunks.length; i++)
  // for (int j = 0; j < chunks[i].length; j++)
  // image(chunks[i][j], i * chunkSizePixels, j * chunkSizePixels);

  println(millis() - start);
}

```

---

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 25, 2020, 9:37pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/4 "2020-04-25T21:37:40Z")

</div>

Any idea why making chunks out of images makes it faster?

---

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 25, 2020, 10:08pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/5 "2020-04-25T22:08:08Z")

</div>

Another problem with this is I have seen that if any blocks change, it might not work. Also, the map is quite big, so updating these would probably not be efficient. Also, it seems that if I make the tiles get called from a class it slows down furthermore.

The Way I tried doing it was like this:

```auto
  for (int i = 0; i < MapWidth; i++) {
    for (int j = 0; j < MapHeight; j++) {
        for (int k = 0; k < blocks.size(); k++) {
          blocks.get(k).display((i*Width)+X, (j*Height)+Y, tile, extraMapData[i][j]);
          //blocks.get(k).special((i*Width)+X, (j*Height)+Y, Width, Height, tile, extraMapData[i][j]);
        }
    }
}

```

* * *

```auto
class Block {

  //Note: all hitbox related things are done in the Player class.

  int id;
  boolean cammo;
  boolean solid;
  PImage img;
  PImage[] animatedLooks;
  ArrayList<String> mods = new ArrayList<String>();
  ArrayList<PImage> modimgs = new ArrayList<PImage>();

  Block(PImage looks, int id) {
    img = looks;
    this.id = id;
  }
  Block(PImage[] looks, int id) {
    animatedLooks = looks;
    this.id = id;
  }

  Block(boolean invisible, int id) {
    this.cammo = invisible;
    this.id = id;
  }

  void display(int x, int y, int id, String mods) {

    if (id == this.id) {
      if (!cammo) {
        if (img != null) {
          image(img, x, y);
        } else {
          image(animateOffset(animatedLooks, x, y), x, y, BlockSize, BlockSize);
        }
      } else {
        //grab neighboring block
      }
    } else {
      for (int i = 0; i < blocks.size(); i++) {
        if (blocks.get(i).getId() == id) {
          blocks.get(i).display(x, y, id, mods);
        }
      }
    }
  }

  void addMod(String str, PImage img) {
    mods.add(str);
    modimgs.add(img);
  }
  void setSolid(boolean s) {
    solid = s;
  }

  int getId() {
    return id;
  }
}

```

blocks is an ArrayList of these block types. The array list is only as long as the number of block types in the game. Some reason this is way slower than directly for looping it and using an if statement, and then displaying it like this:

```auto
  for (int i = 0; i < MapWidth; i++) {
    for (int j = 0; j < MapHeight; j++) {
        switch(tile) {
        case 1:
            image(grass, (i*Width)+X, (j*Height)+Y);
          break;
        ....
    } 
}

```

I want to use the other method so its easier to add blocks to the game, but for some reason, it slows it down a lot.

---

<div class="post-metadata">

**Author:** ![tony](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tony/32/949_2.png) [@tony](https://discourse.processing.org/u/tony)\
**Post date:** [April 26, 2020, 4:11am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/6 "2020-04-26T04:11:23Z")

</div>

Just theorizing, but there is probably some overhead with `image()`. Given that you can pass image anything from a png to a jpeg to an svg, there are probably checks.

If you’re _really_ curious, you might try digging through the source:

> <https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/core/PImage.java>

---

<div class="post-metadata">

**Author:** ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)\
**Post date:** [April 26, 2020, 12:26pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/7 "2020-04-26T12:26:59Z")

</div>

I’m also pretty sure it has something to do with the overhead of `image(...)`.

If you have certain blocks that change very often you could either keep those as seperate images or draw over the existing chunks. It’s not like you would have to redraw the entire chunk, but rather only the tile that changed.

---

<div class="post-metadata">

**Author:** ![Schred](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/schred/32/13146_2.png) [@Schred](https://discourse.processing.org/u/Schred)\
**Post date:** [April 26, 2020, 12:34pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/8 "2020-04-26T12:34:24Z")

</div>

> [@KevinWho](#):
>
> The Way I tried doing it was like this:
> 
> ```auto
> for (int i = 0; i < MapWidth; i++) {
> for (int j = 0; j < MapHeight; j++) {
> for (int k = 0; k < blocks.size(); k++) {
> blocks.get(k).display((i*Width)+X, (j*Height)+Y, tile, extraMapData[i][j]);
> //blocks.get(k).special((i*Width)+X, (j*Height)+Y, Width, Height, tile, extraMapData[i][j]);
> }
> }
> }
> 
> ```

You have an extra loop in there. For each tile in your map, you are drawing every block in your list, meaning every one is drawn `MapWidth * MapHeight` times.

Do it like this instead:

```auto
for (int i = 0; i < MapWidth; i++) {
  for (int j = 0; j < MapHeight; j++) {
     // This logic of course wouldn't be needed if you stored the images in a 2D array
    Block block = blocks.get(i * MapHeight + j);
    block.display((i * Width) + X, (j * Height) + Y, tile, extraMapData[i][j]);
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [April 26, 2020, 2:31pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/9 "2020-04-26T14:31:02Z")

</div>

I might add that you should use image() command only with three parameters, never with 5.

5 is resizing the image but that should be done beforehand in setup(). Same is for all loadImage() (or other making of an image).

Chrisir

---

<div class="post-metadata">

**Author:** ![behreajj](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@behreajj](https://discourse.processing.org/u/behreajj)\
**Post date:** [April 26, 2020, 3:28pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/10 "2020-04-26T15:28:22Z")

</div>

Hi @Chrisir,

> you should use image() command only with three parameters, never with 5

Has this been tested across renderers? In `PGraphics`, [image](https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/core/PGraphics.java#L3813) with three parameters defers to `imageImpl` which _may_ be overridden and implemented differently by sub-classes. The Java AWT renderer’s implementation [here](https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/awt/PGraphicsJava2D.java#L1573) overrides its parent’s [implementation](https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/core/PGraphics.java#L3900). I’m guessing that `image`’s default arguments are such that expensive operations are not triggered (perhaps [here](https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/awt/PGraphicsJava2D.java#L1583)?) . Far as I can tell, the OpenGL renderer [doesn’t](https://github.com/processing/processing/blob/0ac37bca1d0c7c12667a9c0628fba63b31c1f135/core/src/processing/opengl/PGraphicsOpenGL.java#L3255) override the parent.

I believe that hypothetically you could override the AWT implementation in a sub-class, but I haven’t done enough research to see if there’s another way to approach dynamic tinting and resizing an image. EDIT: or if you’d have access to all the fields that `JAVA2D` accesses in that function.

Best,  
Jeremy

PS, take a guess how Processing handles default font rendering with `textMode` `MODEL`.

---

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 26, 2020, 5:22pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/11 "2020-04-26T17:22:40Z")

</div>

Thanks for leading me in the right direction, all I needed to do was remove the the k for loop, and replace blocks.get(k) with blocks.get(0), because in the block class it loops through them. It appears I was drawing everything about 8 times.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 27, 2020, 5:21am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/12 "2020-04-27T05:21:45Z")

</div>

> [@behreajj](#):
>
> Has this been tested across renderers?

I believe so. The basic idea here is that the last two arguments in the 5-arg image are for scaling. Scaling every frame is incredibly wasteful if you can instead scale once at setup and then repeatedly display with no scaling (3-arg) – regardless of the implementation. Without magic caching, scaling will always be worse than not.

Here’s a simple example if you want to play with testing different renderers. Press space to switch between 5-arg and 3-arg image(). On my 2016 laptop, that switches the simple sketch between 60fps and ~25 fps.

```auto
PImage img;
PImage img2;
int w = 20;
int h = 20;

boolean mode;

void setup() {
  size(640, 640);
  img = loadImage("https://upload.wikimedia.org/wikipedia/commons/2/2e/Processing_3_logo.png");
  img2 = img.copy();
  img2.resize(width/w, height/h);
}
void draw() {
  for (int r=0; r<h; r++) {  
    for (int c=0; c<w; c++) {
      int x = r*height/h;
      int y = c*width/w;
      if(!mode){
        image(img2, x, y);
      } else {
        image(img, x, y, width/w, height/h);
      }
    }
  }
  println(frameRate);
}

void keyReleased() {
  mode = !mode;
}

```

---

<div class="post-metadata">

**Author:** ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)\
**Post date:** [April 27, 2020, 10:11am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/13 "2020-04-27T10:11:32Z")

</div>

> [@jeremydouglass](#):
>
> Scaling every frame is incredibly wasteful if you can instead scale once at setup and then repeatedly display with no scaling (3-arg) – regardless of the implementation. Without magic caching, scaling will always be worse than not.

Very much depends on the renderer. Using `P2D` or `P3D` it’s basically free. The OP really would be better with `P2D` here.

And for tile maps, you really want the nine argument version of `image()`!

---

<div class="post-metadata">

**Author:** ![behreajj](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@behreajj](https://discourse.processing.org/u/behreajj)\
**Post date:** [April 27, 2020, 10:25am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/14 "2020-04-27T10:25:48Z")

</div>

Hi @jeremydouglass,

Odd, I get the opposite results: with `P2D` there is no significant dip in frame rate. But I’m not an expert in profiling, and there are a lot of differences between machines which could account for that. Maybe the caching is done elsewhere in the OpenGL renderer code.

> regardless of the implementation

I agree that a general approach is to do as many operations on `PImage` in setup as possible regardless of renderer. But I think there’s room for nuance here, within the AWT implementation there’s plenty of commented out code where the devs have tried different ways to do the magic. Anyways, I was curious because I’ve been tinkering with a library that subclasses a few renderers. Sounds like a rabbit hole I’m not inclined to wander down, though.

Thanks!  
Jeremy

---

<div class="post-metadata">

**Author:** ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)\
**Post date:** [April 27, 2020, 10:30am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/15 "2020-04-27T10:30:15Z")

</div>

> [@behreajj](#):
>
> Maybe the caching is done elsewhere in the OpenGL renderer code.

There is no need for caching in OpenGL renderer code, because of the way OpenGL works - textures are scaled on the GPU (_effectively_ for free). If anything caching is likely to cause a problem. AWT can theoretically do hardware accelerated scaling of images too, but this is unlikely to kick in with the way Processing uses it, and is also somewhat OS dependent.

---

<div class="post-metadata">

**Author:** ![behreajj](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@behreajj](https://discourse.processing.org/u/behreajj)\
**Post date:** [April 27, 2020, 10:34am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/16 "2020-04-27T10:34:19Z")

</div>

Thanks for the insights, @neilcsmith.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 27, 2020, 4:47pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/17 "2020-04-27T16:47:18Z")

</div>

> [@behreajj](#):
>
> there’s room for nuance here

> [@neilcsmith](#):
>
> textures are scaled on the GPU ( _effectively_ for free)

That is what I’m seeing on that test sketch when I plug in P2D.

100000 tiles on a 2000x2000 image:

1. 60fps – P2D – img(f, x, y)
2. 60fps – P2D – img(f, x, y, w, h) ← !!!
3. 15fps – JAVA2D – img(f, x, y)
4. 2fps – JAVA2D – img(f, x, y, w, h)

So the avoid-5-arg advice is actually quite Java2D specific. I should not have discounted “magic caching.” Of course, this simple test is for a single image at exactly size – probably the best possible case scenario. Results might vary if you have many different tiles – I just haven’t tried. But the overall picture seems pretty clear.

---

<div class="post-metadata">

**Author:** ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)\
**Post date:** [April 27, 2020, 5:13pm UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/18 "2020-04-27T17:13:22Z")

</div>

> [@jeremydouglass](#):
>
> Results might vary if you have many different tiles – I just haven’t tried.

To work with tiles you should normally use one image with all the tiles in it and the 9 argument variant of `image(..)` to draw with -

`image(source, xPosition, yPosition, width, height, srcX1, srcY1, srcX2, srcY2);`

Switching images (textures) is slower, at least with OpenGL.

Unfortunately, `Java2D` is using `BufferedImage` as the target by the look of it (sure it used `BufferStrategy` or `VolatileImage` at one point), which means that drawing is never GPU accelerated. Also try with `smooth(0)` if you haven’t, which should improve performance, but not quality(!), of `Java2D`.

---

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 28, 2020, 12:10am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/19 "2020-04-28T00:10:04Z")

</div>

what is the nine argument version?

---

<div class="post-metadata">

**Author:** ![KevinWho](https://avatars.discourse-cdn.com/v4/letter/k/dbc845/32.png) [@KevinWho](https://discourse.processing.org/u/KevinWho)\
**Post date:** [April 28, 2020, 12:38am UTC](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146/20 "2020-04-28T00:38:17Z")

</div>

Why is that when I put P2D in the size(), it is 200% faster, but everything looks awful. The text is blurry, buttons are blurry, even some images look blurry. Some of the tiles look the same like this, is there any way I could apply P2D rendering on only these images?

I have tried  
buffer = createGraphics(x, y, P2D);  
this does not seem like it’s giving me more frames.

[Next page](https://discourse.processing.org/t/image-is-slow-are-there-any-alternatives/20146.md?page=2)
