Take triangle from image onto display

Hey all,

I’m trying to merge two images in a marching squares shape. In some cases, that would mean I need to extract a triangle from one of the images (a small rectangular isoceles triangle). I did find How to copy a triangle out of an image - Processing 2.x and 3.x Forum (from 2016), but this changes an image which I do not want, as this would execute a few times a frame, meaning lots of rebuilding of rather large images, even though the triangles are a few dozen pixels in size. Besides copying the pixels over manually, which sounds painful to do, I can’t think of any way to do this nicely and efficiently.

Additional info; this is for a live background through Processing Android, meaning I’d prefer for it to be as efficient as possible.

1 Like

Perhaps looking into these sections of the reference can help you.

PShape and vertex as well texture commands can help you create your triangles.

It is difficult to assess your intentions without a clearer formulation. Perhaps you could share what code you have already composed?

Best,
JS

As JSGauthier said, use the image you want to read from as a texture and render it onto a triangle. Set the texture coordinates to read from the triangular part of the image you want to sample.

@JsGauthier For sure. The idea is to use marching squares, which I already coded but a simpler version. I have a function to render a cell in a specific position, here’s the simpler version:

void renderPiece(int x, int y, int state) {
  if (state < 11 && state != 7 && state != 9) {
    fill(0);
  } else {
    fill(255);
  }
  rect(x, y, S, S);
  if (state < 11 && state != 7 && state != 9) {
    fill(255);
  } else {
    fill(0);
    state = 15-state;
  }
  
  switch (state) {
    case 1:
      triangle(x, y+HS, x+HS, y+S, x, y+S);
      break;
    case 2:
      triangle(x+S, y+S, x+S, y+HS, x+HS, y+S);
      break;
    case 3:
      rect(x, y+HS, S, HS);
      break;
    case 4:
      triangle(x+HS, y, x+S, y, x+S, y+HS);
      break;
    case 5:
      triangle(x+HS, y, x+S, y, x+S, y+HS);
      triangle(x, y+HS, x+HS, y+S, x, y+S);
      break;
    case 6:
      rect(x+HS, y, HS, S);
      break;
    case 8:
      triangle(x, y, x+HS, y, x, y+HS);
      break;
   }
}

state is made up of four bits, 2³ being top left point, 2² top right, 2¹ bottom right, 2⁰ being bottom left.
The code works as follows; half of the marching squares cases are just inverted other cases. Specifically, states 0111, 1001, and everything above state 1011. Therefore, what I do is I draw the background of the square (inverted or not), then set the fill to the right color and switch the inverted states to the original, then treat all of the 8 remaining cases.

Here is the already slightly modified but incomplete image version:

  void renderPiece(int x, int y, int state) {
    if (state < 11 && state != 7 && state != 9) {
      copy(filtered, x, y, S, S, x, y, S, S);
    } else {
      copy(unfiltered, x, y, S, S, x, y, S, S);
      state = 15-state;
    }
    
    switch (state) {
      case 1:
        triangle(x, y+HS, x+HS, y+S, x, y+S);
        break;
      case 2:
        triangle(x+S, y+S, x+S, y+HS, x+HS, y+S);
        break;
      case 3:
        rect(x, y+HS, S, HS);
        break;
      case 4:
        triangle(x+HS, y, x+S, y, x+S, y+HS);
        break;
      case 5:
        triangle(x+HS, y, x+S, y, x+S, y+HS);
        triangle(x, y+HS, x+HS, y+S, x, y+S);
        break;
      case 6:
        rect(x+HS, y, HS, S);
        break;
      case 8:
        triangle(x, y, x+HS, y, x, y+HS);
        break;
     }
  }

this is the code that needs to be changed, but here’s the method where it’s called from as context:

void marchingSquares() {
  int pX = 0;
  int pY = 0;
  for (int x = 0; x < W; x++) {
    pY = 0;
    for (int y = 0; y < H; y++) {
      if (changed[x+1][y+1]) {
        renderPiece(pX, pY, ((map[x][y] ? 1 : 0) << 3) | ((map[x+1][y] ? 1 : 0) << 2) | ((map[x+1][y+1] ? 1 : 0) << 1) | (map[x][y+1] ? 1 : 0));
      }
      pY += S;
    }
    pX += S;
  }
}

@scudly That would work, after a bit of testing! How fast is it, though?

1 Like

GPUs are designed to render textured triangles as fast as possible. The only trade-off is in how often your source image (texture) is changing relative to how many triangles you are drawing. Sending a changing texture to the GPU every frame if you’re only drawing one or two small triangles is probably not worth it. If you have a fixed image that you can send once and then render thousands to millions of triangles from it, it’ll be as fast as you could possibly want.

The image never changes, but since this is for a phone background there’s no GPU. Still, seems like this is as efficient I can make it, thanks!

All smart phone processors contain a GPU. It’s what renders the interface.

Well, it’s integrated into the CPU normally (on phones), right?

Yes. And it has hardware support for rendering textured triangles. In parallel. In GPU dedicated memory.

Oh, fair enough. Thanks!

I don’t know if this could help you, but in the past I programmed a Kaleidoscope in APDE.
It took a triangle out of an camera image and multiplicated by 6 in real time.

Looking at the source code I see I used a static triangle, generated at setup, as mask, so I’m unsure you can use it. Also I use a high-end cellphone, a Samsung Note 8.