This a C problem, here is the overview Thank you very much. Overview: This progr
ID: 3803645 • Letter: T
Question
This a C problem, here is the overview
Thank you very much.
Overview: This program embeds a text file into an image, or decrypts an image that contains text within it. For our images, we use basic black-and-white (greyscale) P2 images. We use a graphics format that uses ASCII (text) width-in-pixels files. Most graphics programs use binary files (gif, jpeg height-in-pixels etc) which promote smaller file sizes. Since this is just CS maximum-grayscale-value (always 255 for this project) 100, we'll stick with ASCII (text files, even though they pixel-1-1-intensity pixel-1-2-intensity pixel-1-3-intensity pixel-2-1-intensity pixel-2-2-intensity pixel-2-3-intensity take more space. The ASCII format we use is called pgm and is shown at the right. The first line is always P2. After pixel-N-1-intensity pixel-N-2-intensity pixel-N-3-intensity that, you have three values (width, height, grayscale levels) that can be on a single line or separate lines. Finally, you have the actual pixel values for each pixel in the image. A pixel with a value of 0 is black (absence of light and a pixel with a value of 255 is white (all light) As an example of a pgm image, consider the file shown at the left (data.pgm) P2 This image is seven columns wide and six rows high. It has 255 grayscale 7 6 255 values (all the images used in this project will have 255 possible grayscale 0 0 0 0 0 0 values). This image has a one pixel border in black (zero absence of light 0 255 255 255 255 255 0 o 255 255 255 255 255 0 and a white interior (255 all light) 0 255 255 255 255 255 0 0 255 255 255 255 255 0 This program uses, and creates pgm images. To see 0 0 0 if your program is working properly, you need to be able to view pgm images. Your system might (or might not have a viewer that supports pgm images. If not, download the free program GIMP (GNU Image Manipulation Program) at ht downloads. Using GIMP that you can actually see it, as the actual image is only six pixels high by seven pixels wide Encoding a Message into an Image Now that you understand a bit about how pgm images work, we need to understand how to embed a message into these images. We want to make the modified image (containing an embedded message) look no different than the original image so that no one will suspect it contains an embedded message. Given this, we only modify the last (or rightmost or least-significant bit of the pixels in the image. We use the last/rightmost/least-significant bit as changes to that bit do not drastically impact the color displayed by that pixel. Distinguishing between pure black (a pixel value of zero and almost pure black a pixel value of one is difficult, if not impossible, for the average person. Similarly distinguishing between pure white (255) and almost pure white 254) is equally difficult.Explanation / Answer
Given below is the code for encoding a message into a PGM image and decoding the message.
Please don't forget to rate the answer if it helped. Thank you very much.
//
// hide.c
// program to hide a message from a file into a pgm image from a file and write it to new image file
//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// a function to load a PGM image and return the data as a 2D array. Also returns the width height in address passed
unsigned char ** loadPGMImage(FILE *fp, int *width, int *height);
void writePGMImage(FILE *fp, unsigned char **data, int width, int height);
void encodeMessage(FILE *fp, unsigned char **data, int width, int height); //encode message contained in the file pointed by fp into the pixel data
void encodeChar(unsigned char ch, unsigned char **data, int width, int height, int pixRow, int pixCol);
unsigned char decodeChar(unsigned char **data, int width, int height, int pixRow, int pixCol);
void decodeMessage(unsigned char **data, int width, int height, char *msg);
int main(int argc, char *argv[])
{
int err = 1;
FILE *msgFile = NULL;
FILE *imgFile = NULL;
FILE *outFile = NULL;
int mode = 0;
unsigned char **pixels = NULL;
char message[100];
int width, height, maxval;
if(argc >= 3)
{
if(strcmp(argv[1], "encode") == 0)
{
mode = 1;
if(argc != 5)
{
printf("Incorrect number of arguments. usage: %s <msg_file> <img_file> <out_file> ", argv[0]);
return 1;
}
msgFile = fopen(argv[2], "r");
imgFile = fopen(argv[3], "r");
outFile = fopen(argv[4], "w");
if(msgFile == NULL)
printf("Could not open file %s for reading ", argv[2]);
else if(imgFile == NULL)
printf("Could not open file %s for reading ", argv[3]);
else if(outFile == NULL)
printf("Could not open file %s for writing ", argv[4]);
else
err = 0;
}
else if(strcmp(argv[1], "decode") == 0)
{
mode = 2;
imgFile = fopen(argv[2], "r");
if(imgFile == NULL)
printf("Could not open file %s for reading ", argv[2]);
else
err = 0;
}
}
else
{
printf("Incorrect number of arguments. usage: %s <msg_file> <img_file> <out_file> ", argv[0]);
return 1;
}
if(err == 1)
{
return 1;
}
if(mode == 1) //encode
{
pixels = loadPGMImage(imgFile, &width, &height);
encodeMessage(msgFile, pixels, width, height);
writePGMImage(outFile, pixels, width, height);
printf("message encoded and new image is written to file %s ", argv[4]);
}
else if(mode == 2)
{
pixels = loadPGMImage(imgFile, &width, &height);
decodeMessage(pixels, width, height, message);
printf("The decoded message is %s", message);
}
}
unsigned char ** loadPGMImage(FILE *fp, int *width, int *height)
{
char str[5];
unsigned char **data;
int i, j, maxval;
fscanf(fp, "%s", str); //read the first P2 string
fscanf(fp, "%d %d %d", width, height, &maxval); //read width and height and maxval
data = (unsigned char **) malloc(sizeof(unsigned char*) * (*height));
for(i = 0; i < *height; i++)
{
data[i] = (unsigned char *) malloc(sizeof(unsigned char) * (*width));
}
//now read all pixel data
for(i = 0; i < *height; i++)
{
for(j = 0; j < *width; j++)
fscanf(fp, "%d", &data[i][j]);
}
fclose(fp);
return data;
}
void writePGMImage(FILE *fp, unsigned char **data, int width, int height)
{
int i, j;
fprintf(fp, "P2 "); //the first P2 string
fprintf(fp, "%d %d 255 ", width, height); //read width and height and maxval
//now read all pixel data
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
fprintf(fp, "%3d ", data[i][j]);
fprintf(fp, " ");
}
fclose(fp);
}
void encodeMessage(FILE *fp, unsigned char **data, int width, int height)
{
unsigned char ch;
int pixelRow = height -1 , pixelCol = width - 1;
while((ch = fgetc(fp)) )
{
// printf(" encoding %c - ", ch);
if(feof(fp))
ch = 0;
encodeChar(ch, data, width, height, pixelRow, pixelCol);
if(feof(fp))
break;
pixelCol = pixelCol - 8;
if(pixelCol < 0)
{
pixelCol += width;
pixelRow --;
if(pixelRow < 0)
break;
}
}
}
void encodeChar(unsigned char ch, unsigned char **data, int width, int height, int pixRow, int pixCol)
{
int i ;
int bit;
for(i = 7; i >= 0 ; i--)
{
bit = (ch >> i) & 1;
//printf("%d",bit);
if(bit == 1)
data[pixRow][pixCol] |= 1; //set the last bit(rightmost)
else
data[pixRow][pixCol] &= 0xFE; //1111 1110 ,clear the last bit(rightmost)
pixCol--;
if(pixCol < 0)
{
pixCol += width;
pixRow--;
if(pixRow < 0)
break;
}
}
}
void decodeMessage(unsigned char **data, int width, int height, char *msg)
{
unsigned char ch;
int pixelRow = height -1 , pixelCol = width - 1;
int idx = 0;
ch = 0;
while(1)
{
ch = decodeChar( data, width, height, pixelRow, pixelCol);
msg[idx++] = ch;
if(ch == '')
break;
pixelCol = pixelCol - 8;
if(pixelCol < 0)
{
pixelCol += width;
pixelRow --;
if(pixelRow < 0)
break;
}
}
}
unsigned char decodeChar(unsigned char **data, int width, int height, int pixRow, int pixCol)
{
int i ;
int bit;
unsigned char ch = 0;
for(i = 7; i >= 0 ; i--)
{
bit = (data[pixRow][pixCol] & 1);
ch |= bit << i;
pixCol--;
if(pixCol < 0)
{
pixCol += width;
pixRow--;
if(pixRow < 0)
break;
}
}
return ch;
}
input file : input.pgm
P2
7 6 255
0 0 0 0 0 0 0
0 255 255 255 255 255 0
0 255 255 255 255 255 0
0 255 255 255 255 255 0
0 255 255 255 255 255 0
0 0 0 0 0 0 0
input file : msg.txt
UA
output generated file: output.pgm
P2
7 6 255
0 0 0 0 0 0 0
0 255 255 254 254 254 0
0 254 254 254 254 255 0
1 254 254 254 254 255 0
0 254 254 254 255 254 1
0 1 0 1 0 1 0
output (a warning is generated when compiled, thats ok)
$ gcc hide.c
hide.c:108:30: warning: format specifies type 'int *' but the argument has type 'unsigned char *' [-Wformat]
fscanf(fp, "%d", &data[i][j]);
~~ ^~~~~~~~~~~
%s
1 warning generated.
$ ./a.out encode msg.txt input.pgm output.pgm
message encoded and new image is written to file output.pgm
$ ./a.out decode output.pgm
The decoded message is UA