繁体   English   中英

如何从 .pgm 文件中提取并显示隐藏的文本消息?

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

我试图打开并通读 P5.pgm(灰度)文件,然后从每个像素中提取最低有效位。 我试图获取每个像素的 LSB,因此图像的每个字节一个位。因此需要 8 个图像字节/像素来提取 1 个字节的隐藏文本。然后,我将能够获得隐藏文本的一个字节消息并创建角色。 (使用 ASCII 值)

我还必须显示隐藏的消息。

#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);  
     
   } 
}

到目前为止我已经知道了。 为了防止经过太多像素,它应该在从文件中读取xxx后停止。 我仍然对如何显示未覆盖的字符感到困惑。

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

我将其作为输出(对于前几次迭代,我没有包括所有这些)。

我将如何提取 LSB,对它们进行分组,然后找到隐藏的文本? 我只是坚持下一步该做什么,我会很感激任何建议。

  • 可以使用 & 1 获取 lsb
  • 主 for 循环一次应该只有 go 超过八个图像字节
  • 内容可以使用位移来累加一个字节
   // 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");

我将如何提取 LSB

使用按位 AND 运算符

Image[i] & 1

我将如何...将它们分组

使用位移位和按位或运算符的组合,例如

(LSB_a << 7) | (LSB_b << 6) | (LSB_c << 5) | ....

我怎么会...然后找到隐藏的文本?

只需将结果值打印为字符,例如使用putchar

以下是一种方法的非常简单的示例:

#include <stdio.h>
#include <assert.h>


int main(void) 
{
    unsigned char Image[] = {0x46, 0x51, 0x4a, 0x5c, 0x42, 0x10, 0xaa, 0xa1,
                             0xfe, 0x7b, 0x86, 0x18, 0x54, 0x2a, 0xa3, 0x60,
                             0x3c, 0x1d, 0x24, 0x9a, 0x06, 0x60, 0xa9, 0x75};
                             
    size_t sz = sizeof Image / sizeof Image[0];
    assert(sz % 8 == 0);
    
    for (size_t i = 0; i < sz; i += 8)
    {
        int res = (Image[i]   & 1) << 7 |
                  (Image[i+1] & 1) << 6 |
                  (Image[i+2] & 1) << 5 |
                  (Image[i+3] & 1) << 4 |
                  (Image[i+4] & 1) << 3 |
                  (Image[i+5] & 1) << 2 |
                  (Image[i+6] & 1) << 1 |
                  (Image[i+7] & 1);

        putchar(res);
    }
    
    return 0;
}

此代码中的 output 是:

ABC

在上面的示例中,结果的计算是通过显式写入所有 8 个按位运算来完成的。 这样做是为了使示例简单。 如果您喜欢更短的代码,可以像这样在循环中完成:

    int res = 0;
    for (int k=0; k<8; ++k)
    {
        res |= (Image[i+k] & 1) << (7-k);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM