2013-03-27 6 views
5

PPM Görüntü üzerinde temel Steganografi yapmaya çalışıyorum.C Steranografi C

Temel algoritma tamamlandı. Dosyayı okuyun, başlığın P6 ile başladığını kontrol edin, görüntü genişliğini ve yüksekliğini ve piksel verilerini alın.

Toplam dört yönteme ihtiyacım var: ReadPPM, WritePPM, WriteMsg and ReadMsg.

ReadImg ve WriteImg yöntemleri aşağıdayım, ancak sıkıştığım yerde WriteMsg yöntemim var. Bu, her bir dizgenin her bir bitini her bayttaki son bit'e yazan temel steganografidir. İlk 8 bayt, gizlenen dizginin boyutunu, sonra da gizli iletiyi başlatan her baytın boyutunu içerecek şekilde varsayalım.

Fikrim, dizenin boyutuna ilişkin ikili kodu ve daha sonra dizenin kendisinin ikili kodunu tutan çok büyük bir dizi oluşturmaktı. Sadece bu diziyi nasıl alacağımı ve görüntüdeki her bayta nasıl eklediğimi anlamaya çalışıyorum.

Herhangi bir yardım çok takdir edilmektedir. İşte benim geçerli kod:

#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

Kodunuzun biçimlendirilmesi gerçekten çok iyi ... aslında yardım istediğiniz işlevler hariç! Lütfen düzeltin. Tamamen okunamaz durumda. – MatthewD

+0

İki döngüye ihtiyacınız vardır: Biri ve diğeri, her karakterin biti ile, veriyi yalnızca ikinci döngü içinde yazıp @Patashu gibi veya ters sırada yazınız ('bayt << i & 0x80'). Uzunluk değişkeni dönme! –

+0

'len = sizeof (s)' bir imlecin boyutunu döndürür. Dizenin uzunluğunu istiyorsanız, strlen() 'işlevini kullanın. – MatthewD

cevap

2

bir bayt sadece tek bir bit ayıklamak için, bunu:

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

Bu sağa i kez ve sonra and s byte'ın bit kaydırır 0000 0001 ile (en küçük hariç tüm bitler sıfırlanır ve en düşük bit 0 ve 1 için 1'dir).

16 bit kısa, 32 bit int, 64 bit uzunluğunda benzer ... Ve hatta bir dizenin char s için. Char cinsinden kaç bayt olduğunu görmek için sizeof (char) öğesini kullanabilirsiniz.

Ancak elbette, fazladan bitlere birden fazla char (veya uzun veya int veya ...) sahip olacaksınız. biraz ekstra hangi eleman karar vermek için:

Eğer i inci istemek biraz ve elementler x bit genişliğindedir, ardından Şimdi bu biraz var o elemanın [i/x]

den i%x biraz olsun, yerleştirmek bir byte içinde (veya kömürü veya ... veya int), yapın:

steganographybyte = originalbyte & (~ 0x1) + biraz bu demektir ne

, numarayı ... 0000 0001 almak onun bitlerini tersine çevir ... 1111 1110, and orijinal bayt ile tüm bitleri korunmuş en düşük HARİÇ, daha sonra sadece bitinizi ekleyin.