csteganographypgm

How could a hidden text message be extracted and displayed from a .pgm file?


I was trying to open and read through a P5 .pgm (grayscale) file, then extract the least-significant-bit from each pixel. I tried to get the LSB of every pixel, so one bit bit per byte of the image.So it would take 8 image bytes/pixels to extract 1 byte of hidden text.Then, I would be able to get one byte of the hidden message and create a character. (using the ASCII values)

I also have to display the hidden message.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>


//Clear PGM (XV) comments.
void pgmCommentClear(FILE *disk){
unsigned char  ch;
   fread(&ch, 1, 1, disk);
   if (ch != '#') {
      fseek(disk, -1, SEEK_CUR);
      return;
   }
   do {
      while (ch != '\n') fread(&ch, 1, 1, disk);
   } while (ch == '#');
   pgmCommentClear(disk);
}



//Read PGM formatted image (1D array). 
unsigned char *PGM_FILE_READ_1D(char *FileName, int *Width, int *Height, int *color) { 
int   pmax;
char  ch;
char  type[3];
unsigned char *Image;
FILE *disk;
   if ((disk = fopen(FileName, "rb")) == NULL) {
      return NULL;
   }
   fscanf(disk, "%s", type);
   if (!strcmp(type, "P6")) *color = 1;
                       else *color = 0;
   fread(&ch, 1, 1, disk); 
   pgmCommentClear(disk);
   fscanf(disk, "%d", Width);
   fscanf(disk, "%d", Height);
   fscanf(disk, "%d", &pmax);
   fread(&ch, 1, 1, disk);
   if (*color == 1) {
      Image = (unsigned char *)calloc(*Height * *Width * 3, sizeof(unsigned char));
      fread(Image, 1, (*Height * *Width * 3), disk);
   } else {
      Image = (unsigned char *)calloc(*Height * *Width, sizeof(unsigned char));
      fread(Image, 1, (*Height * *Width), disk);
  }
   fclose(disk);
   return Image;
}


//function to convert binary to decimal
int BinaryToDec(int array[]) {
  int decimal=0;
  int m=1;
  for(int i=7; i>=0; i--){
    decimal+= array[i]*m;
    m *= 2;
  }
  if(array[0] == 1) decimal *= -1;
  printf("decimal: %d\n", decimal);
  return decimal;
}

void DecToBinary(int dec){
    int binary[8];
    for(int i=0; i<=8; i++){
        if(dec & (1 << i)) binary[i] = 1;
            else binary[i] = 0;
    }
    printf("binaryform:");
    for(int i=7; i>=0; i--){
        printf("%d", binary[i]);
    }
    printf("\n");
}




int main(void){
   char *fileName = "hw10.pgm";
  
   int Width, Height, color;

   unsigned char *Image;
   Image = PGM_FILE_READ_1D(fileName, &Width, &Height, &color);     

   //int size = Width*Height;
   int size = 50;
   
   int array[8];
  
   int xCount =0;
   
   for(int i=0; i<size; i++){
      int mask=1;
      for(int k=0; k<8; k++){
         array[k] = Image[i]&mask;
         mask<<1;
      }
      
      printf("Image: %d\n", Image[i]);
      DecToBinary(Image[i]); 
      BinaryToDec(array);  
     
   } 
}

I have got this so far. To prevent going through too many pixels, it should stop after reading xxx from the file. I am still confused about how to display the uncovered characters.

Image: 214
binaryform:11010110
decimal: 0
Image: 213
binaryform:11010101
decimal: -255
Image: 208
binaryform:11010000
decimal: 0
Image: 214
binaryform:11010110
decimal: 0
Image: 215

I have this as output(for the first few iterations,I didn't include all of them).

How would I extract the LSBs, group them and then find the hidden text? I am just stuck on what to do next and would appreciate any suggestions.


Solution

  •    // We will have (at most) size/8 bytes in the final text
       for(int i=0; i<size/8; i++){
          // Process eight image bits in a row
          int accum = 0;
          for(int k=0; k<8; k++){
             // Shift the current contents (multiply by 2)
             // and add in the new bit. This will reconstruct
             // a byte
             accum = (accum << 1) + (Image[i*8+k] & 1);
          }
          // the resulting byte is the next character of your hidden
          // text
          printf("%c", accum);
       } 
       printf("\n");