【发布时间】: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 字符串。我愿意就如何改进这一点提出任何建议