How To: Make a 2D wave simulation Part 4


Image generation

The simplest image format you can use is in PGM format. Short for Portable GrayMap format, it's a simple image format where the pixel values are stored raw, great for readily writing values into a file and representing them as they are!
A .pgm file has the below form:

P5
width height
max value
{{data}}

That means, we can write the array next of width ROW = 128 and height COL = 128 into an image by simply writing
P5
128 128
255
{{all array values here!}}

Image generation in C

Below I'll provide a simple function that creates a frame pgm image and writes data on it from an array. Note, I'm using an integer passed by reference, in order to have a frame counter that is dynamically incremented.

#include <stdio.h>

#define ROW 128
#define COL 128
#define SIZE ROW*COL
#define EXP 12
#define ONE 0x1000

int mulf(int a, int b) {
  int res = a * b;
  //for a right bit shift, you have to handle the cases where result is negative
  if (res < 0) return -(-res >> EXP);
  return res >> EXP;
}

const int c2 = 0x110;
void compute_next(int *next, int *curr, int *prev) {
  for (int x=ROW; x<SIZE-ROW; x+=ROW) {
    for (int y=1; y<ROW-1; y++) {
      int dt = 2*curr[x+y] - prev[x+y];
      int ds = 4*curr[x+y] - curr[(x+1)+y] - curr[(x-1)+y] - curr[x+(y+ROW)] - curr[x+(y-ROW)];
      next[x+y] = dt - mulf(ds, c2);
    }
  }
  //edge along y=0
  for (int x=0; x<SIZE; x+=ROW) next[x] = 0;
  //edge along y=ROW-1
  for (int x=ROW-1; x<SIZE; x+=ROW) next[x] = 0;
  //edge along x=0
  for (int y=0; y<ROW; y++) next[y] = 0;
  //edge along x=SIZE-ROW
  for (int y=SIZE-ROW; y<SIZE; y++) next[y] = 0;
}

void generate_pgm(int *array, int *pgmidx) {
  char filename[16];
  sprintf(filename, "./frames/frame%03d.pgm", *pgmidx);
  FILE *fd = fopen(filename, "wb+);
  fprintf(fd, "P5\n%d %d\n255\n", ROW, COL);
  for (int i=0; i<SIZE; i++) {
    int temp = 0x7f + mulf(0x7f, array[i]);
    if(temp > 0xff) temp = 0xff;
    if(temp < 0) temp = 0;
    fputc(temp, fd);
  }
  *pgmidx = *pgmidx + 1;
  fclose(fd);
}

Now finally in the next page, we're gonna put everything together!


Previous page Back Next page