Thread: Double-linked list error in image smoothing program

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    3

    Double-linked list error in image smoothing program

    I am doing an assignment that takes in a binary file written in fortran that has two dimensions (int) and an array of numbers (float). If the number is 0 it is a "cold" pixel and if it is >= 1000 it is considered "hot". It is a CDC image. These bad pixels should be replaced with an average of the ones around them. Here is the code:


    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    /* Prototypes */
    void getdimensions(FILE *fd, int *rows, int *cols);
    void countbadpixels(int *rows, int *cols, float **oldimage, int *coldct, int *hotct);
    void findbadlocs(int *rows, int *cols, float **oldimage, int *coldct, int *hotct, int **coldloc, int **hotloc);
    float **smoothbadpixels(int *rows, int *cols, float **oldimage, int *coldct, int *hotct, int **coldloc, int **hotloc);
    void smoothoverall(int *rows, int *cols, float **newimage);
    void storeformatted(int *rows, int *cols, float **newimage);
    /*NOTE: This unformatted file has been made to be compatible with Fortran READ/WRITE statements */
    void storeunformatted(int *rows, int *cols, float **newimage);
    void storebadpixels(int *coldct, int *hotct, int **coldloc, int **hotloc, float **oldimage);
    
    int main()
    {
      FILE *fd;
      char filename[50], buff[4];
      int i, j, *rows, *cols, *coldct, *hotct, **coldloc, **hotloc;
      float **oldimage, **newimage;
      /* Allocate integer pointers */
      rows = (int *)malloc(sizeof(int));
      cols = (int *)malloc(sizeof(int));
      coldct = (int *)malloc(sizeof(int));
      hotct = (int *)malloc(sizeof(int));
    
      /* Request filename and get old image */
      printf("Enter filename: ");
      scanf("%s",filename);
      fd=fopen(filename,"rb");
      if (fd==NULL)
      { printf("Error opening file.\n");
        exit(-1);}
      getdimensions(fd,rows,cols);
      
      oldimage=(float **)malloc(sizeof(float *)*(*rows));
      for(i=0;i<*cols;i++)
        oldimage[i]=(float *)malloc(sizeof(float)*(*cols));
      printf("%dx%d\n",*rows,*cols);
      fread(buff,4,1,fd);
      for(j=0;j<*cols;j++)
      { for(i=0;i<*rows;i++)
          fread(&oldimage[i][j],sizeof(float),1,fd);}
      printf("A(3,3)=%f\n",oldimage[4][4]);
      fclose(fd);
    
      /* Count bad pixels */
      countbadpixels(rows,cols,oldimage,coldct,hotct);
    
      /* Allocate arrays for the cold and hot pixel locations */
      coldloc=malloc(sizeof(int)*(*coldct));
      for(i=0;i<*coldct;i++)
        coldloc[i]=malloc(sizeof(int)*2);
    
      hotloc=malloc(sizeof(int)*(*hotct));
      for(i=0;i<*hotct;i++)
        hotloc[i]=malloc(sizeof(int)*2);
    
      /* Find bad pixel locations and smooth them*/
      findbadlocs(rows,cols,oldimage,coldct,hotct,coldloc,hotloc);
      newimage=smoothbadpixels(rows,cols,oldimage,coldct,hotct,coldloc,hotloc);
    
      /* Smooth the overall image */
      smoothoverall(rows,cols,newimage);
    
      /* Wrtie everything to files */
      storeformatted(rows,cols,newimage); 
      storeunformatted(rows,cols,newimage);
    
      /* Write number of each bad pixel to the screen and to file*/
      storebadpixels(coldct,hotct,coldloc,hotloc,oldimage);
      printf("%d cold pixels, %d hot pixels\n",*coldct,*hotct);
    
      return 0;
    }
    
    // FUNCTIONS  *********************************************************************************
    void getdimensions(FILE *fd, int *rows, int *cols)
    {
      int i, j;
      char buff[4];
      float **image;
       
      fread(buff,4,1,fd);
      fread(rows,4,1,fd);
      fread(cols,4,1,fd);
      fread(buff,4,1,fd);
    }
      
    
    void countbadpixels(int *rows, int *cols, float **oldimage, int *coldct, int *hotct)
    {
      int i, j;
      
      for (i=0;i<*rows;i++)
      { 
        for (j=0;j<*cols;j++)
        {
          if(oldimage[i][j]==0)
            *coldct=*coldct+1;
          if(oldimage[i][j]>=1000)
            *hotct=*hotct+1;
        }
      }
    }
    
    void findbadlocs(int *rows, int *cols, float **oldimage, int *coldct, int *hotct, int **coldloc, int **hotloc)
    {
      int i, j, k, l;
      k=0;  
      l=0;
    
      for(i=0;i<*rows;i++)
      {
        for(j=0;j<*cols;j++)
        {
          if (oldimage[i][j]==0)
          {
            coldloc[k][1]=i;
            coldloc[k][2]=j;
            k=k+1;
          }
          if (oldimage[i][j]>=1000)
          {
            hotloc[l][1]=i;
            hotloc[l][2]=j;
            l=l+1;
          }
        }
      }
    }
    
    float **smoothbadpixels(int *rows, int *cols, float **oldimage, int *coldct, int *hotct, int **coldloc, int **hotloc)
    {
      int i, j;
      float **intermed, **newimage, pixsum, p;
      pixsum = 0;
      p = 0;
    
      /* Allocate array for new image and intermediate image*/
      newimage=malloc(sizeof(float *)*(*rows+2));
      intermed=malloc(sizeof(float *)*(*rows+2));
      for(i=0;i<(*cols+2);i++)
      {
        newimage[i]=malloc(sizeof(float)*(*cols+2));
        intermed[i]=malloc(sizeof(float)*(*cols+2));
      }  
    
      /* Set arrays equal to zero */
      for(i=0;i<(*rows+2);i++)
      {
        for(j=0;j<(*cols+2);j++)
        {
          newimage[i][j]=0;
          intermed[i][j]=0;
        }
      }
    
      /* Set middle of arrays equal to the old image */
      for(i=0;i<*rows;i++)
      {
        for(j=0;j<*cols;j++)
        {
          newimage[i+1][j+1]=oldimage[i][j];
          intermed[i+1][j+1]=oldimage[i][j];
        }
      }
    
      /* Keep in mind the new image is surrounded by zeros, so old coordinates are each 1 off */
      for(i=0;i<*coldct;i++)
      {
        for(j=0;j<=2;j++)
        {
          /* Three above */
          if ((intermed[coldloc[i][1]][coldloc[i][2]+j]>0)&&(intermed[coldloc[i][1]][coldloc[i][2]+j]<1000))
            {pixsum=pixsum+intermed[coldloc[i][1]][coldloc[i][2]+j]; p=p+1;}
          if ((intermed[coldloc[i][1]+2][coldloc[i][2]+j]>0)&&(intermed[coldloc[i][1]+2][coldloc[i][2]+j]<1000))
            {pixsum=pixsum+intermed[coldloc[i][1]+2][coldloc[i][2]+j]; p=p+1;}
        }
        /* Left and right */
        if ((intermed[coldloc[i][1]+1][coldloc[i][2]]>0)&&(intermed[coldloc[i][1]+1][coldloc[i][2]]<1000))
          {pixsum=pixsum+intermed[coldloc[i][1]+1][coldloc[i][2]]; p=p+1;}
        if ((intermed[coldloc[i][1]+1][coldloc[i][2]+2]>0)&&(intermed[coldloc[i][1]+1][coldloc[i][2]+2]<1000))
          {pixsum=pixsum+intermed[coldloc[i][1]+1][coldloc[i][2]+2]; p=p+1;}
        /* Store averaged pixel in new array */
        if (p>0)
          newimage[coldloc[i][1]+1][coldloc[i][2]+1]=pixsum/p;
        /* Reinitialize values */
        pixsum=0;
        p=0;
      }
      /* Now do hot pixels */
      for(i=0;i<*hotct;i++)
      {
        for(j=0;j<=2;j++)
        {
          /* Three above and below, one column at a time */
          if ((intermed[hotloc[i][1]][hotloc[i][2]+j]>0)&&(intermed[hotloc[i][1]][hotloc[i][2]+j]<1000))
            {pixsum=pixsum+intermed[hotloc[i][1]][hotloc[i][2]+j]; p=p+1;}
          if ((intermed[hotloc[i][1]+2][hotloc[i][2]+j]>0)&&(intermed[hotloc[i][1]+2][hotloc[i][2]+j]<1000))
            {pixsum=pixsum+intermed[hotloc[i][1]+2][hotloc[i][2]+j]; p=p+1;}
        }
        /* Left and right */
        if ((intermed[hotloc[i][1]+1][hotloc[i][2]]>0)&&(intermed[hotloc[i][1]+1][hotloc[i][2]]<1000))
          {pixsum=pixsum+intermed[hotloc[i][1]+1][hotloc[i][2]]; p=p+1;}
        if ((intermed[hotloc[i][1]+1][hotloc[i][2]+2]>0)&&(intermed[hotloc[i][1]+1][hotloc[i][2]+2]<1000))
          {pixsum=pixsum+intermed[hotloc[i][1]+1][hotloc[i][2]+2]; p=p+1;}
        /* Store averaged pixel in new array */
        if (p>0)
          newimage[hotloc[i][1]+1][hotloc[i][2]+1]=pixsum/p;
        /* Reinitialize values */
        pixsum=0;
        p=0;
      }
      free(intermed);
      return newimage;
    }
    
    void smoothoverall(int *rows, int *cols, float **newimage)
    {
      int i, j, k;
      float **intermed, pixsum, p;
      pixsum = 0;
      p = 0;
      /* Allocate array for new image and intermediate image*/
      intermed=malloc(sizeof(float *)*(*rows+2));
      for(i=0;i<(*cols+2);i++)
        intermed[i]=malloc(sizeof(float)*(*cols+2));
      /* Set temp array to the new array so far */
      for(i=0;i<(*rows+2);i++)
      {
        for(j=0;j<(*cols+2);j++)
          intermed[i][j]=newimage[i][j];
      }
      /* Find averages and put them in the new array */
      for(i=1;i<=*rows;i++)
      {
        for(j=1;j<=*cols;j++)
        {
          for(k=-1;k<=1;k++)
          {
            /* Three above and below, one column at a time */
            if (intermed[i-1][j+k]>0)
              {pixsum=pixsum+intermed[i-1][j+k]; p=p+1;}
            if (intermed[i+1][j+k]>0)
              {pixsum=pixsum+intermed[i+1][j+k]; p=p+1;}
          }
          /* Left and right */
          if (intermed[i][j-1]>0)
            {pixsum=pixsum+intermed[i][j-1]; p=p+1;}
          if (intermed[i][j+1]>0)
            {pixsum=pixsum+intermed[i][j+1]; p=p+1;}
          /* Update new image */
          newimage[i][j]=pixsum/p;
          /* Reinitialize values */
          pixsum=0;
          p=0;
        }
      }
      free(intermed);
    }
    
    void storeformatted(int *rows, int *cols, float **newimage)
    {
      int i, j;
      FILE *fd;
    
      fd = fopen("formout.dat","w");
      if (fd==NULL)
      {
        printf("Error writing formatted file.");
        exit(-1);
      }
    
      /* Write Dimensions */
      fprintf(fd,"%dx%d\n",*rows,*cols);
    
      /* Wrtie array */
      for (i=1;i<=*rows;i++)
      {
        for (j=1;j<=*cols;j++)
          fprintf(fd,"\t%.3f",newimage[i][j]);
        fprintf(fd,"\n");
      }
      printf("\t\"formout.dat\" written\n");
    }
    
    /*NOTE: This unformatted file has been made to be compatible with Fortran READ/WRITE statements */
    void storeunformatted(int *rows, int *cols, float **newimage)
    {
      int i, j, arrayhdrftr, dimhdrftr;
      FILE *fd;
    
      arrayhdrftr = 4*(*rows)*(*cols);
      dimhdrftr = 8;
    
      fd = fopen("unformout.bin","wb");
      if (fd==NULL)
      {
        printf("Error writing unformatted file.\n");
        exit(-1);
      }
    
      /* Fortran header */
      fwrite(&dimhdrftr,4,1,fd);
      /* Dimensions */
      fwrite(rows,4,1,fd);
      fwrite(cols,4,1,fd);
      /* Fortran footer, then header */
      fwrite(&dimhdrftr,4,1,fd);
      fwrite(&arrayhdrftr,4,1,fd);
      /* Write matrix info, column major */
      for(j=1;j<=*cols;j++)
      {
        for(i=1;i<=*rows;i++)
        {
          fwrite(&newimage[i][j],4,1,fd);
        }
      }
      /* Write Fortran footer */
      fwrite(&arrayhdrftr,4,1,fd);
      
      printf("\t\"unformout.bin\" written\n");
    }
    
    void storebadpixels(int *coldct, int *hotct, int **coldloc, int **hotloc, float **oldimage)
    {
      int i;
      FILE *fd;
      fd = fopen("badpixels.dat","w");
      if (fd==NULL)
      {
        printf("Error writing bad pixels file.\n");
        exit(-1);
      }
    
      fprintf(fd,"%d cold, %d hot\n",*coldct,*hotct);
      fprintf(fd,"ROW\tCOL\tVALUE\n");
      for (i=0;i<*coldct;i++)
        fprintf(fd,"%d\t%d\t%.3f\n",coldloc[i][1]+1,coldloc[i][2]+1,oldimage[coldloc[i][1]][coldloc[i][2]]);
      for (i=0;i<*hotct;i++)
        fprintf(fd,"%d\t%d\t%.3f\n",hotloc[i][1]+1,hotloc[i][2]+1,oldimage[hotloc[i][1]][hotloc[i][2]]);
    
      printf("\t\"badpixels.dat\" written\n");
    }
    // ********************************************************************************************
    Here is the binary image to run (300x400 matrix):
    Binary Image

    The assignment said to store 3 files: formatted smoothed image, unformatted smoothed image, and locations and values of bad pixels.

    In my main function I get a runtime error that occurs in the "fclose(fd)" statement. The error says "*** glibc detected *** ./a.out: corrupted double-linked list: <address>..." I'm not sure what to do, any suggestions? Also, it works on my local machine, but when I ssh to the school's machine I get this error. Thanks.

    -mwhar

    P.S. The file was written with the Fortran statements:
    WRITE(7) rows, cols
    WRITE(7) matrix
    where each write statement has a 4 byte header and footer.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Code:
     if (fd==NULL)
      { printf("Error opening file.\n");
        exit(-1);}
      getdimensions(fd,rows,cols);
      
      oldimage=(float **)malloc(sizeof(float *)*(*rows));
      for(i=0;i<*cols;i++)
        oldimage[i]=(float *)malloc(sizeof(float)*(*cols));
      printf("%dx%d\n",*rows,*cols);
      fread(buff,4,1,fd);
      for(j=0;j<*cols;j++)
      { for(i=0;i<*rows;i++)
          fread(&oldimage[i][j],sizeof(float),1,fd);}
      printf("A(3,3)=%f\n",oldimage[4][4]);
      fclose(fd);
    Take a look at your malloc statements... you are relying upon the values of *rows and *cols (which really don't need to be pointers)...

    However; in get dimensions you are doing this...

    Code:
    void getdimensions(FILE *fd, int *rows, int *cols)
    {
      int i, j;
      char buff[4];
      float **image;
       
      fread(buff,4,1,fd);
      fread(rows,4,1,fd);
      fread(cols,4,1,fd);
      fread(buff,4,1,fd);
    }

    You read the values from the disk but you never assign them to *rows or *cols...
    Thus you are using these variables in an uninitialized state with malloc... and quite likely getting some significant errors in the process.

  3. #3
    Registered User
    Join Date
    Apr 2011
    Posts
    3
    I thought fread() puts the value in that location to begin with? I put in a print statement just before the malloc() statements and got the right dimensions (300 and 400), so it seems like the right values are in that location by the time malloc() needs them. Am I missing something? Thanks!

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by mwhar View Post
    I thought fread() puts the value in that location to begin with? I put in a print statement just before the malloc() statements and got the right dimensions (300 and 400), so it seems like the right values are in that location by the time malloc() needs them. Am I missing something? Thanks!
    Never mind... I misread the code... I see what you're doing now... it's a bit strange but so is C...
    Last edited by CommonTater; 04-27-2011 at 05:54 PM.

  5. #5
    Registered User
    Join Date
    Apr 2011
    Posts
    3
    I figured it out. In this segment (and many others just like it):
    Code:
    oldimage=(float **)malloc(sizeof(float *)*(*rows));
      for(i=0;i<*cols;i++)
        oldimage[i]=(float *)malloc(sizeof(float)*(*cols));
    The upper bound in the for loop is cols, not rows, as it should be. Thanks!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. double linked list
    By TNA$H in forum C Programming
    Replies: 19
    Last Post: 06-13-2008, 07:45 AM
  2. single linked list to double linked list (help)
    By Countfog in forum C Programming
    Replies: 8
    Last Post: 04-29-2008, 08:04 PM
  3. I need Help with Double linked list
    By axe in forum C Programming
    Replies: 5
    Last Post: 03-12-2006, 02:46 AM
  4. Double linked list error, help!
    By raell in forum C Programming
    Replies: 10
    Last Post: 03-07-2004, 06:28 PM
  5. Double linked list
    By Unregistered in forum C Programming
    Replies: 3
    Last Post: 11-24-2001, 08:07 PM