Search code examples
cimagedynamicmpiallocation

Dynamic Allocation 2d array in C difference with a simple 2d array Mpi


I have a MPI program for image processing (pgm file) in MPI C and I use Dynamic allocation for a 2D Array as follows.

float **masterbuf;
masterbuf = arralloc(sizeof(float), 2, M, N);

When I use

float masterbuf[M][N];

the image that the program gives looks fine.

The problem is that when I use dynamic allocation the image loses some pixels in its left side. So these missing pixels create a black line. It's like the image has been shifted 2 pixels right. I don't do any other operations to the image, just read it and print it again.

The function that I use to write the image is:

void pgmwrite(char *filename, void *vx, int nx, int ny)
{
  FILE *fp;

  int i, j, k, grey;

  float xmin, xmax, tmp, fval;
  float thresh = 255.0;

  float *x = (float *) vx;

  if (NULL == (fp = fopen(filename,"w")))
  {
    fprintf(stderr, "pgmwrite: cannot create <%s>\n", filename);
    exit(-1);
  }

  printf("Writing %d x %d picture into file: %s\n", nx, ny, filename);

  /*
   *  Find the max and min absolute values of the array
   */

  xmin = fabs(x[0]);
  xmax = fabs(x[0]);

  for (i=0; i < nx*ny; i++)
  {
    if (fabs(x[i]) < xmin) xmin = fabs(x[i]);
    if (fabs(x[i]) > xmax) xmax = fabs(x[i]);
  }

  if (xmin == xmax) xmin = xmax-1.0;

  fprintf(fp, "P2\n");
  fprintf(fp, "# Written by pgmwrite\n");
  fprintf(fp, "%d %d\n", nx, ny);
  fprintf(fp, "%d\n", (int) thresh);

  k = 0;

  for (j=ny-1; j >=0 ; j--)
  {
    for (i=0; i < nx; i++)
    {
      /*
       *  Access the value of x[i][j]
       */

      tmp = x[j+ny*i];

      /*
       *  Scale the value appropriately so it lies between 0 and thresh
       */

      fval = thresh*((fabs(tmp)-xmin)/(xmax-xmin))+0.5;
      grey = (int) fval;

      fprintf(fp, "%3d ", grey);

      if (0 == (k+1)%16) fprintf(fp, "\n");

      k++;
    }
  }

  if (0 != k%16) fprintf(fp, "\n");
  fclose(fp);
}

Solution

  • Your two definitions of masterbuf may both create 2D arrays, but they don't do so in the same way. The function arralloc() creates space for data and pointers--not just data as with the simple static array definition. What this works out to mean is that in pgmwrite(), while x[i][j] will return the same result regardless of the method used, x[i] will mean two different things because of the pointer involvement.

    It's worth noting that you'll be given a clue by the compiler as to the problem should you change void *vx in the prototype to float *vx. Since you're immediately and unconditionally casting this void * to a float *, it'd be much better practice to do this anyhow.

    (2nd edit:) Also, if interested, check out this response. It shows how to index using two dimensions into a single malloc'd block, without arralloc().