【问题标题】:How to convert LSB extracted data to text or binary to text如何将 LSB 提取的数据转换为文本或二进制转换为文本
【发布时间】:2016-05-04 23:33:33
【问题描述】:

更新**************************** 作为参考,我包含了我为打开 PPM 图像而制作的程序 - 将消息嵌入到图像中,然后用嵌入的文本保存一个新图像。使用下面的函数,我希望额外显示该消息(隐藏在 LSB 中),然后将其转换为文本以显示它。感谢到目前为止的回复 - 我将开始对其进行测试,看看是否有任何效果。


我正在尝试编写一个函数来提取无符号字符值的 LSB - 将它们放在一起以形成提取的消息。我有我需要从文件中提取多少 LSB 的长度,但我在如何将其转换为消息时遇到了麻烦。

起初我将前 8 位提取到一个 int 数组中 - 给了我诸如 00110000 之类的东西。现在我有一个具有该值的 INT 数组,我需要将它转换为单个字符来表示字母。但是,我认为我应该将所有 LSB 放入一个 messageLength * 7 的数组中,并以某种方式将该 int 数组转换为文本。它将在转换之前给我文本的二进制表示。也许他们是一种将一长串 1 和 0 转换为文本的方法?

unsigned char * extBits(PPMImage *img, int messageLen, unsigned char * decMsg)
{
    //int count = 2;
    int embCount = 0;
    int deM = messageLen * 7;
    int count = 0;
    unsigned char byte;
//  int mask;
//  unsigned char update;
//  unsigned char flipOne = 0x01;  //0x01
//  unsigned char flipZero = 0xFE;  //0x00
    unsigned char dMsg[deM];
    int byteArray[7];
    int takeByte = 0;
    unsigned char *extMsg;
    char c;

    for(int j = 0; j < 7; j++)
    {
        if(takeByte == 8)
        {
            //first letter extracted

            takeByte = 0;               
        }
        //byte = msgOne[j];
    //  byte = img->pixel[j];
        //encMsg[j] = byte;
        byte = img->pixel[j];
        //printf("byte: %c\n", byte); 
    //  printf("byte: %x\n", byte); 
        byte &= 1;
        //printf("byte after: %x\n", byte); 
        dMsg[j] = byte; 
        byteArray[j] = byte;
        data[j] = byteArray[j];
        printf("dMsg:%x ", dMsg[j]);        
    //  printf("pixel:%c \n", img->pixel[j]);       
        embCount++; 
        takeByte++;
    }
/*  
    for(int r=0;r<7;r++)
    {
        printf("\n%d\n", byteArray[r]);
    }   
    printf("count: %d", embCount);
    printf("%s ", dMsg);
*/
    return decMsg = dMsg;
}

嵌入程序*******

//////////////////////////////////////////////////////////////
/*
    execute as ./emb -i <img2embed> -i <text file> -o <embedIMG>

*/
//////////////////////////////////////////////////////////////


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


typedef struct {
    int x, y;
    unsigned char *pixel;
} PPMImage;

#define RGB_COMPONENT_COLOR 255

static PPMImage *readPPM(const char *filename)
{
    FILE * fp;
    PPMImage *img;
        int rgb_comp_color;
    int size = 0;
    fp = fopen(filename, "a+");

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    unsigned char *buff;
    unsigned char stuff[16];
    int c;
    int x,y;
    buff = (unsigned char*) malloc(sizeof(unsigned char)*size +1);
    memset(buff, '\0', sizeof(unsigned char)*size+1);

        fgets(stuff, sizeof(stuff), fp);

    if (stuff[0] != 'P' || stuff[1] != '3') {
    fprintf(stderr, "Invalid image format (must be 'P3')\n");
    exit(1);
    }

    //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);

    if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
        fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
        exit(1);
    }

    if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
        fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
        exit(1);
    }
    if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
        fprintf(stderr, "'%s' does not have 8-bits components\n",filename);
        exit(1);
    }

    //printf("x: %d y: %d\n", img->x, img->y);

    unsigned char buffer[1024];
    memset(buffer,0,1024);  
    fgets(buffer,1024,fp);

    fread(buff, 1, size, fp);   

    img->pixel = buff;
/*  
    for(int h = 0; h < 20; h++)
    {
        printf("%c", buff2[h]);

    }


    printf("%s", buff2);
*/
    fclose(fp);

    return img;

} 

void writePPM(const char *filename, unsigned char * img, int x, int y)
{
    FILE *fp;
    //open file for output
    fp = fopen(filename, "wb");
    if (!fp) {
        fprintf(stderr, "Unable to open file '%s'\n", filename);
        exit(1);
    }

    //write the header file
    //image format
    fprintf(fp, "P3\n");

    //comments
   // fprintf(fp, "# Created by %s\n",CREATOR);

    //image size
    fprintf(fp, "%d %d\n",x,y);

    // rgb component depth
    fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);

    // pixel pixel
    fwrite(img,1, strlen(img), fp);
    fclose(fp);
}

//unsigned char * embBits(PPMImage *img, int messageLen, unsigned char*msgOne, unsigned char *encMsg)
int embBits(PPMImage *img, int messageLen, unsigned char*msgOne, int embLen)
{
    //int count = 2;
    int embCount = 0;
    int count = 0;
    unsigned char *eMsg;    
    unsigned char byte;
    int mask;
    unsigned char update;
    unsigned char flipOne = 0x01;  //0x01
    unsigned char flipZero = 0xFE;  //0x00

    for(int j = 0; j < messageLen; j++)
    {
        byte = msgOne[j];
        //encMsg[j] = byte;

        for(int k=7; 0 < k; k--)
        {
            update = byte;  

            update = update & (1<<k);
            //printf("pixel:%c\n", img->pixel[count]);      
            //printf("pixel+1:%c\n", img->pixel[count+1]);      
        //  printf("pixel+2:%c\n", img->pixel[count+2]);        
            if(update == 0)
            {
                // if i see 1   |=
                // if i see a 0 &=
                //img->pixel[count] = img->pixel[count] &= flipZero;        
                img->pixel[count+2] &= flipZero;        
            }   
            else
            {
                //flip bit
                //red
                    //check LSB and FLIP 
                //  img->pixel[count] = img->pixel[count] |= flipOne;       
                img->pixel[count+2] |= flipOne;     
            }       

            //mask--;   
            //eMsg[count] = img->pixel[count];
            //printf("count: %d\n", count);
            count = count + 3;
        }   
//      eMsg[j] = byte; 
    }

    //return encMsg = eMsg;
    //unsigned char *yes = "sucess";
    /*
    for(int a = 0; a < messageLen; a++)
    {
        printf("pixel: %c", img->pixel[a]);     
        printf("msg: %c\n", eMsg[a]);       
    //  eMsg[a] = img->pixel[a];
    }
*/

    embCount = count;   
    return embLen = embCount;
}

int main(int argc, char **argv){

    int messageLen;
    int i = 0; 
    PPMImage *img;
    int size = 0;
    FILE * fp;
    int testSize;
    fp = fopen(argv[4], "a+");

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    unsigned char *buff;
    buff = (unsigned char*) malloc(sizeof(unsigned char)*size +1);
    memset(buff, '\0', sizeof(unsigned char)*size+1);
    fread(buff, 1, size, fp);

    fclose(fp);
//  printf("text encryption: %s\n", buff);
    testSize = strlen(buff);    
//  printf("Size of text %d\n", testSize);

    messageLen = strlen(buff); 

    img = readPPM(argv[2]);
/*
    int testing = strlen(img->pixel);
    for (int f=0;f<6;f++)
    {   
        //f2 = 1
        //f3 = 6
        printf("%c", img->pixel[f]);            
    }       
*/

//  printf("%c \n", img->pixel[2]);
//  printf("%c \n", img->pixel[5]);
    printf("\n");
//  unsigned char * encMsg;

    int encMsg = 0;         
    encMsg = embBits(img, messageLen, buff, encMsg);

//  printf("cipher msg:%s\n", img->pixel);
    printf("message length: %d\n", messageLen);
//  printf("cipher msg length: %d\n", encMsg);


    writePPM(argv[6], img->pixel, img->x, img->y);

    printf("Please press enter to complete\n");
    getchar();
}

【问题讨论】:

  • 如果您已正确完成提取,那么您已经在数组中拥有消息字符。尝试在printf 中使用%c 而不是%x 将数据显示为字符。
  • 非静态局部变量的返回地址似乎不太好,因为该变量会在从函数返回时消失,并且在调用者中取消引用地址将调用未定义的行为
  • @kaylum dMsg[j] 在此程序中将是 0 或 1,而简单地将 %x 更改为 %c 不会给出应有的结果。
  • @MikeCAT 我没有详细查看代码,因为它确实不清楚它在做什么。 OP 写了“给我一些诸如 00110000 之类的东西”,所以我以此为目的,因此在我的评论前加上“如果你正确地完成了提取......”。只是试图将 OP 指向正确的方向,要点是如果提取正确,提取的数据应该已经是有效字符。
  • 嵌入程序制作的图像看起来不错。它改变了我想要的值,我只是遇到了从中提取数据的问题。我的提取器应该能够从图像本身中提取消息。现在我正在弹出 LSB 并形成一个长的 INT 字符串。我愿意就如何改进这一点提出任何建议

标签: c text binary char


【解决方案1】:

我不知道您具体对文件做了什么并将每个位分配给数组中的一个位置,但您可以打印存储在unsigned int 中的二进制序列。尝试使用类似的东西...

#include <stdio.h>

int main() {
    unsigned int arr[] = {00110110, 00111100, 10111011};
    int i = sizeof(arr)/sizeof(arr[0]);
    while(i-->0) {
        printf("%c, ", arr[i]);
    }
    printf("\n");
}

【讨论】:

    【解决方案2】:

    您可以使用位操作将这些位收集到一个字节中。

    #include <stdio.h>
    
    #define BYTE_LENGTH 8
    
    #if 1
    /* MSB is in data[0], LSB is in data[BYTE_LENGTH - 1] */
    int arrayToChar(const int data[]) {
        int c = 0;
        int i;
        for (i = 0; i < BYTE_LENGTH; i++) {
            if (data[i]) c |= (1 << (BYTE_LENGTH - 1 - i));
        }
        return c;
    }
    #else
    /* LSB is in data[0], MSB is in data[BYTE_LENGTH - 1] */
    int arrayToChar(const int data[]) {
        int c = 0;
        int i;
        for (i = 0; i < BYTE_LENGTH; i++) {
            if (data[i]) c |= (1 << i);
        }
        return c;
    }
    #endif
    
    int main(void) {
        int data[8] = {0, 0, 1, 1, 0, 0, 0, 0};
        int c = arrayToChar(data);
        printf("%d %c\n", c, c);
        return 0;
    }
    

    如果您想从 7 位产生一个字节,请将 BYTE_LENGTH 更改为 7。

    如果您想处理长序列,请重复应用arrayToChar,同时更改要传递的第一个元素(地址)。

    【讨论】:

    • 我有一个巨大的字符串,它是一个无符号字符 *。我正在尝试访问某些值并将值的 LSB 存储到某些东西中。一旦我有 8 LSB,这应该形成一封信。这个想法是将该字符串转换为它所代表的无符号字符。但是,每当我尝试将 unsigned char 分配给我的 unsigned char * 字符串中的任何值时,它都会返回空白。我可以为它分配一个 INT,但不能分配一个字符
    • 基本上是读取 PPM p3 图像-它的值例如 16 37 29 17 等。我将所有这些存储为无符号字符 *。然后,我将诸如 37 之类的值翻转为 36 - 创建输出 16 36 29 17。通过这样做,我将一条消息存储在第二个原因 37 的 LSB 中,使其变为 36。我的嵌入似乎有效- 但是当我从 LSB 中提取这些值时,我遇到了无法将这些值存储为除 INT 之外的任何值的问题。如果我从函数中返回,我将失去作用域。
    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多