2013-03-27 34 views
5

Cố gắng thực hiện Steganography cơ bản trên một hình ảnh PPM.Steganography trong C

Tôi đã hoàn thành thuật toán cơ bản. Đọc trong tệp, kiểm tra tiêu đề bắt đầu bằng P6, lấy chiều rộng và chiều cao của hình ảnh và dữ liệu pixel.

Tôi cần có tổng cộng bốn phương pháp: ReadPPM, WritePPM, WriteMsg và ReadMsg.

Tôi có phương pháp ReadImg và WriteImg, nhưng tôi bị kẹt với phương thức WriteMsg của mình. Đây là steganography cơ bản chỉ viết từng bit của chuỗi vào bit cuối cùng trong mỗi byte. 8 byte đầu tiên được giả sử để chứa kích thước của chuỗi bị ẩn, sau đó mỗi byte sau đó bắt đầu thông báo ẩn.

Ý tưởng của tôi là tạo một mảng lớn chứa mã nhị phân cho kích thước của chuỗi, sau đó mã nhị phân của chính chuỗi đó. Tôi chỉ cố gắng tìm ra cách tôi sẽ lấy mảng đó và thêm nó vào từng byte trong hình ảnh.

Bất kỳ giúp đỡ được nhiều đánh giá cao. Đây là mã hiện tại của tôi:

#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

Định dạng mã của bạn là tốt ... ngoại trừ chức năng bạn thực sự muốn trợ giúp! Hãy sửa chữa nó. Nó hoàn toàn không thể đọc được như nó được. – MatthewD

+0

Bạn cần hai chu kỳ: một bởi len và một chu kỳ khác của mỗi char, ghi dữ liệu chỉ trong chu kỳ thứ hai như @Patashu nói hoặc theo thứ tự ngược lại ('byte << i & 0x80'). Đừng cuộn biến chiều dài! –

+0

'len = sizeof (s)' sẽ trả về kích thước của một con trỏ. Nếu bạn muốn độ dài của chuỗi, sử dụng 'strlen()'. – MatthewD

Trả lời

2

Để trích xuất chỉ là một chút duy nhất từ ​​một byte, làm điều này:

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

này chuyển bit của byte sang bên phải tôi lần, và sau đó and s nó với 0000 0001 (sao cho tất cả các bit trừ các bit thấp nhất đều bằng 0 và bit thấp nhất là 0 cho 0 và 1 cho 1).

Bạn có thể làm tương tự cho 16 bit ngắn, 32 bit int, 64 bit dài ... Và thậm chí đối với các char s của một chuỗi. Bạn có thể sử dụng sizeof (char) để xem có bao nhiêu byte trong một char.

Nhưng tất nhiên bạn sẽ có nhiều hơn một char (hoặc dài hoặc int hoặc ...) để thêm bit từ. Để quyết định yếu tố để thêm một chút từ:

Nếu bạn muốn các bit thứ i và các yếu tố là x bit rộng, sau đó nhận được bit i%x từ yếu tố [i/x]

Bây giờ bạn có bit này, để đặt nó bên trong một byte (hoặc int hay char hoặc ...), làm:

steganographybyte = originalbyte & (~ 0x1) + chút

Điều này có nghĩa là, bạn lấy số ... 0000 0001, đảo ngược các bit của nó để nó ... 1111 1110, and nó với byte ban đầu để tất cả các bit của nó được bảo tồn EXCEPT thấp nhất, sau đó chỉ cần thêm bit của bạn.