2013-03-27 5 views
5

PPM 이미지에서 기본 스테 가노 그래피를 시도합니다.스테 가노 그라피 C

기본 알고리즘을 완료했습니다. 파일을 읽고 헤더가 P6으로 시작하는지 확인하고 이미지 너비와 높이 및 픽셀 데이터를 가져옵니다.

총 4 가지 방법 (ReadPPM, WritePPM, WriteMsg 및 ReadMsg)이 필요합니다.

필자는 ReadImg 및 WriteImg 메서드를 사용하지 않지만 내 기능이 멈추는 곳은 WriteMsg 메서드입니다. 이것은 각 바이트의 마지막 비트에 문자열의 각 비트를 쓰는 기본 스테 가노 그래피입니다. 처음 8 바이트는 숨겨진 문자열의 크기를 포함한다고 가정하고 그 이후의 각 바이트는 숨겨진 메시지를 시작합니다.

제 아이디어는 문자열의 크기와 이진 코드의 바이너리 코드를 저장하는 방대한 배열을 만드는 것이 었습니다. 나는 그 배열을 어떻게 가져 와서 이미지의 각 바이트에 추가할지 알아 내려고하고있다.

도움을 주시면 감사하겠습니다. 여기에 내 현재 코드 :

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

typedef struct { 
    unsigned char red,green,blue; 
} PPMPixel; 

typedef struct { 
    int x, y; 
    PPMPixel *data; 
} PPMImage; 

#define CREATOR "RPFELGUEIRAS" 
#define RGB_COMPONENT_COLOR 255 

static PPMImage *readPPM(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] != '6') { 
     fprintf(stderr, "Invalid image format (must be 'P6')\n"); 
     exit(1); 
    } 

    //alloc memory form image 
    img = (PPMImage *)malloc(sizeof(PPMImage)); 
    if (!img) { 
     fprintf(stderr, "Unable to allocate memory\n"); 
     exit(1); 
    } 

    //check for comments 
    c = getc(fp); 
    while (c == '#') { 
    while (getc(fp) != '\n') ; 
     c = getc(fp); 
    } 

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

    //read rgb component 
    if (fscanf(fp, "%d", &rgb_comp_color) != 1) { 
     fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename); 
     exit(1); 
    } 

    //check rgb component depth 
    if (rgb_comp_color!= RGB_COMPONENT_COLOR) { 
     fprintf(stderr, "'%s' does not have 8-bits components\n", filename); 
     exit(1); 
    } 

    while (fgetc(fp) != '\n') ; 
    //memory allocation for pixel data 
    img->data = (PPMPixel*)malloc(img->x * img->y * sizeof(PPMPixel)); 

    if (!img) { 
     fprintf(stderr, "Unable to allocate memory\n"); 
     exit(1); 
    } 

    //read pixel data from file 
    if (fread(img->data, 3 * img->x, img->y, fp) != img->y) { 
     fprintf(stderr, "Error loading image '%s'\n", filename); 
     exit(1); 
    } 

    fclose(fp); 
    return img; 
} 

void writePPM(const char *filename, PPMImage *img) 
{ 
    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, "P6\n"); 

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

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

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

    // pixel data 
    fwrite(img->data, 3 * img->x, img->y, fp); 
    fclose(fp); 
} 

void writeMsg(PPMImage *img, char *s) 
{ 

    int i; 
    int len; 
    len = sizeof(s); 

    if (img) 
    { 
     j = 0; 
     for (i=0; i < img->x * img->y; i++) 
     { 
       while(j < 8) 
       { 
        if(len & 0x80) 
        { 
         img->data[i].red= img->data[i].red | 0x01; 
        } 
        else 
        { 
         img->data[i].red= img->data[i].red & 0xFE; 
        } 

        len=len << 1; 
        j++; 

        if (len & 0x80) 
        { 
         img->data[i].green= img->data[i].green | 0x01; 
        } 
        else 
        { 
         img->data[i].green= img->data[i].green & 0xFE; 
        } 


        len = len << 1; 
        j++; 

        if (len & 0x80) 
        { 
         img->data[i].blue= img->data[i].blue | 0x01; 
        } 
        else 
        { 
         img->data[i].blue= img->data[i].blue & 0xFE; 
        } 
        j++; 
       } 
     } 
    } 
} 
+0

코드 형식이 대부분 괜찮습니다 ... 실제로 도움이 필요한 기능은 제외! 고쳐주세요. 그것은 완전히 읽을 수없는 것입니다. – MatthewD

+0

당신은 두 사이클을 필요로합니다 : 하나는 len이고 다른 하나는 모든 char의 비트들입니다. @Patashu가 말한 것과 같은 두 번째 사이클 내에서만 데이터를 쓰거나 역순으로 ('byte << i & 0x80') 쓰십시오. 길이 변수를 굴리지 마라! –

+0

'len = sizeof (s)'는 포인터의 크기를 반환합니다. 문자열의 길이를 원하면'strlen()'을 사용하십시오. – MatthewD

답변

2

가 바이트에서 단지 하나의 비트를 추출하기가 이렇게 :

bit(i) = byte >> i & 0x1

이 오른쪽으로 난 시간, 다음 and들 바이트의 비트를 이동 0000 0001 (최하위를 제외한 모든 비트는 0이되고 최하위 비트는 0의 경우 0, 1의 경우 1).

16 비트의 짧은, 32 비트의 int, 64 비트의 길이에 대해서도 비슷하게 할 수 있습니다 ... char 문자열의 경우에도 마찬가지입니다. sizeof (char)를 사용하여 char에있는 바이트 수를 확인할 수 있습니다.

물론 여분의 비트를 생성하기 위해 char (또는 long 또는 int 또는 ...)을 여러 개 가질 수 있습니다. 에서 약간의 여분에 어떤 요소를 결정하려면

당신이 i 번째 비트를 원하는 경우 및 요소가 x 비트가 넓은, 다음 지금 당신이이 비트를 가지고 요소 [i/x]

에서 i%x 비트를 얻을을 배치 할 바이트의 내부 (또는 것은 char 또는 ... 또는 INT), 수행

steganographybyte = originalbyte & (~을 0x1) + 비트 이것은 무엇을 의미

을, 당신은 수 ... 0000 0001을, 비트를 반전해서 ... 1111 1110, and 원래의 바이트와 함께 모든 비트가 보존되므로 가장 낮은 비트를 제외하고 가장 낮은 비트를 제외하고 그냥 비트를 넣으십시오.