title: C: Writing structs of RGB values to file to create ppm image - premature end of file
body: <p>The program i am creating a steganography program that hides a secret message inside a .ppm image by changing random red pixel values to ascii characters.
  The program is based on code that is on stackoverflow for reading and writing ppm images (<a href="https://stackoverflow.com/questions/2693631/read-ppm-file-and-store-it-in-an-array-coded-with-c">read PPM file and store it in an array; coded with C</a>), all other code is my own work. I have completed all the necessary functions to do this such as writing,reading,encoding and decoding the files but i am struggling to grasp the fwrite function. </p>
  
  <p>Currently when the program encodes an image it takes in the .ppm converts it to its rgb values in a struct. Then it hides the secret message by editing the red values to ascii characters. The issue arises when it comes to "printing" the image to a file. When the program has completed the image produced is around 90% of what it should be printing. Example show below:
  <a href="https://i.stack.imgur.com/UCVvZ.png" rel="nofollow noreferrer">Example of the unfinished image</a></p>
  
  <p>I have checked it is storing all the values are being stored correctly by printing all the rgb values and it is. (used the showPPM method). Is there not enough memory to write the image? is the image to large for the write function? these are my guesses.</p>
  
  <p>Any information on how i should go about changing the writePPM function so that i correctly print 100% of the image to the file would be great.</p>
  
  <p>Here is the code below:</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;math.h&gt;
  #include&lt;string.h&gt;
  #include&lt;time.h&gt;
  
  typedef struct {
      unsigned char red,green,blue;
  } PPMPixel;
  
  typedef struct {
  int x, y;
  PPMPixel *data;
  } PPMImage;
  
  void writePPM(PPMImage *img);
  
  static PPMImage *getPPM(const char *filename)
  {
  
      char buff[16];
       PPMImage *img;
       FILE *fp;
       int c, rgb_comp_color;
       //open PPM file for reading
       fp = fopen(filename, "rb");
       if (!fp) {
            fprintf(stderr, "Unable to open file '%s'\n", filename);
            exit(1);
       }
  
       //read image format
       if (!fgets(buff, sizeof(buff), fp)) {
            perror(filename);
            exit(1);
       }
  
  //check the image format
  if (buff[0] != 'P' || buff[1] != '3') {
       fprintf(stderr, "Invalid image format (must be 'P3')\n");
       exit(1);
  }else{
      printf("P3\n");
  }
  
  //alloc memory form image
  img = (PPMImage *)malloc(sizeof(PPMImage));
  if (!img) {
       fprintf(stderr, "Unable to allocate memory\n");
       exit(1);
  }
  
  
     c = getc(fp);
     while (c == '#') {
     while (getc(fp) != '\n') ;
       c = getc(fp);
  
  }
  ungetc(c, fp);
  //read image size information
  if (fscanf(fp, "%d %d", &amp;img-&gt;x, &amp;img-&gt;y) != 2) {
       fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
       exit(1);
  }else{
      printf("Height: %d\n",img-&gt;x);
      printf("Width: %d\n",img-&gt;y);
  
  }
  
  //read rgb component
  if (fscanf(fp, "%d", &amp;rgb_comp_color) != 1) {
       fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
       exit(1);
  }else{
      printf("%d\n",rgb_comp_color );
  }
  
  //check rgb component depth
  if (rgb_comp_color!= 255) {
       fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
       exit(1);
  }
  
  while (fgetc(fp) != '\n') ;
  //memory allocation for pixel data
  img-&gt;data = (PPMPixel*)malloc(24*img-&gt;x * img-&gt;y * sizeof(PPMPixel));
  
  if (!img) {
       fprintf(stderr, "Unable to allocate memory\n");
       exit(1);
  }
  
  //read pixel data from file
  if (fread(img-&gt;data, 10*img-&gt;x, img-&gt;y, fp) != img-&gt;y) {
       fprintf(stderr, "Error loading image '%s'\n", filename);
       exit(1);
  }
  
  fclose(fp);
  return img;
  }
  
  
  
  struct PPMImage * encode(char * text, PPMImage * img)
  {
      //convert secret message to ascii code
  
      int i,ascii,height,width;
      int total = 0;
      int rolling = 0;
      int original = 0;
      time_t t;
      srand((unsigned) time(&amp;t));
      height=img-&gt;y;
      width=img-&gt;x;
  
      for(i = 0; text[i]; i++){
  
          ascii = text[i];
  
          //create random number between 0 and max the width
          total = total + rand() % width;
          original = total;
          //printf("Random Number: %d\n",total);
  
          if(total &gt;= width){
              rolling = rolling + 1;
              total = total - width;
          }
  
          //printf("Before R: %d \n",img-&gt;data[0].red );
          img-&gt;x=rolling;
          img-&gt;y=total;
  
          printf("X: %d ",rolling );
          printf("Y: %d ",total );
  
          //set img position
          //at position random we set the red bit equal to ascii number 
          printf("Old R:  %d ",img-&gt;data[i].red );                    
          img-&gt;data[i].red=ascii; 
          printf("New R: %d\n ",img-&gt;data[i].red );   
      }
  
      //take img then print it out
      //setting the img values again for printing
      img-&gt;x=width;
      img-&gt;y=height;
      writePPM(img);
  
  }
  
  void writePPM(PPMImage *img)
  {
  FILE *fp;
  //open file to be written
  fp = fopen("encoded.ppm", "wb");
  if (!fp) {
       fprintf(stderr, "Unable to open file \n");
       exit(1);
  }
  
  //image format
  fprintf(fp, "P3\n");
  
  //comments
  //need to store comments to be outputted
  fprintf(fp, "# Created by Sean \n");
  
  //image size
  fprintf(fp,"%d %d\n",img-&gt;x,img-&gt;y);
  
  // rgb component depth
  fprintf(fp, "%d\n",255);
  
  //write pixels currently not fully working
  fwrite(img-&gt;data, sizeof(img-&gt;data), 3*img-&gt;y*img-&gt;x, fp);
  
  //close file stream
  fclose(fp);
  }
  
  void showPPM(PPMImage *img)
  {
      int i;
      if(img){
  
      for(i=-1;i&lt;img-&gt;x*img-&gt;y;i++){
          printf("Number: %d\n",i);
          printf("R: %d ",img-&gt;data[i].red );
          printf("G: %d ",img-&gt;data[i].green );
          printf("B: %d\n ",img-&gt;data[i].blue );
  
       }
  }
  }
  
  
  char * decode(PPMImage * i1,PPMImage * i2){
  
  //compare difference in number of bits in red pixels
  //if there is a different then take the red pixel value from the encrypted image
  //then translate it from ascii to chars then print.
  printf("Decoding......\n");
  
  int i;
       for(i=-1;i&lt;i1-&gt;x*i1-&gt;y;i++){
              if(i1-&gt;data[i].red != i2-&gt;data[i].red){
                  printf("%c",i1-&gt;data[i].red );
              }
       }
  
  //to be able to test and finish this need to write code for encoding
  
  }
  
  int main(int argc, char *argv[]){
  
  //input statements
  if(argc == 3){
      PPMImage *image;
      image = getPPM(argv[2]);
      //uncomment the showPPM to display all rgb values in the encoded files
      //showPPM(image);
      if(argv[1] = "e"){
      printf("Please enter your secret message to be encoded estimated max characters: %d\n",image-&gt;y);   
  
          //need to add user input
      encode("test output!",image);
      }
  }else if(argc == 4){
      PPMImage *i1;
      PPMImage *i2;
      i1 = getPPM(argv[2]);
      i2 = getPPM(argv[3]);
  
      if(argv[1] = "d"){
          decode(i1,i2);
      }
  }else{
      printf("Wrong arguments");
  }
  }
  </code></pre>