0

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);
}
Mike B
  • 1,522
  • 1
  • 14
  • 24

1 Answers1

2

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().

Community
  • 1
  • 1
David Duncan
  • 1,225
  • 8
  • 14
  • Nope, [arralloc](https://code.google.com/p/messagepassing/source/browse/trunk/arralloc.c) uses the idea of dope-vectors, i.e. index vectors into a large data block. Seems like those EPCC codes are everywhere on the Internet nowadays :) – Hristo Iliev Nov 27 '12 at 11:55
  • Thanks a lot for link and info! While the gist of the answer remains the same, I've substantially trimmed it down, mostly to remove inaccuracies related to assumptions about the memory layout of the arralloc() result. – David Duncan Nov 27 '12 at 17:07