C Programming You are to write programs in C, to find and hide the steganographi
ID: 3697380 • Letter: C
Question
C Programming
You are to write programs in C, to find and hide the steganographic files
Here’s how we did it. We have two files:
the mask image (left, color/grayscale)
the hidden file (any format, but I suggest using a text file)
The method for hiding data in an existing image is rather simple. A standard grayscale image is made up of a 2-dimensional array of pixels. Each pixel is just an 8-bit unsigned char (a number between 0 and 255). 8 bits is usually enough to encode most information for a grayscale image. However, while your eye can probably tell the difference between a pixel value of 5 and a pixel value of 200, you probably will not notice a small difference (say the difference between 200 and 201). We can take advantage of this to hide information that a computer can detect but a person could not.
So, if we start with an 8-bit pixel, we can throw out the least significant bit, the one that distinguishes the value of 200 from 201. The binary value of 200 is: 11100010 and 201 is: 11100011.If we just toss out whatever value is in that last bit, we can hide a single bit from the file we want to hide. (like 1 if the hidden bit should be a 1, and 0 if the hidden bit should be a 0).
More specifically, you need to:
--Write a program to hide a file inside of another image
--allocate memory for a properly-sized multi-dimensional array
--for each pixel in the hidden image, encode that information along with the mask image
--write the new image to a file
--Write a program to unmask the hidden file from an encoded image and save it as a decoded file
--for each pixel in the encoded image, pull out the least significant bit and use those bits to build bytes
--write the bytes to the decoded file
Your goal (for the encode portion): to write a program that will:
--read three command-line arguments, the first is the image we wish to hide a file in, the second is the filename of the file we wish to hide, the third is the filename that we will write the hidden image to.
--copy the original image to an array
--create new pgm file to hold changed image
--allocate memory for the new image data
--start at the mask image’s 0,0 pixel
--for each bit in the hidden file
--drop the least significant bit from the mask image current pixel value
--add a 1 to that pixel value if the corresponding hidden file bit is a 1
--add a 0 (or don’t) to that pixel value if the corresponding hidden file bit should be a 0
--move to the next pixel in the image (the next column in the image, or the next row’s 0th column if at the max column has been reached)
--write an EOF character in the next 8 image pixels
--save the array to a file using the pgm image format we’ve been using for the prior projects
Your goal (for the decode portion): to write a program that will:
--read two command-line arguments; take the first command-line argument which is the filename of an image (we will provide two pgm images to test with)
--read that image from the provided filename to an array
--open the decoded file with the second command-line argument as the filename
--for each pixel in the imageif the last bit is zero
--make the next corresponding bit in the hidden file a 0
--if the last bit is one
--make the next corresponding bit in the hidden file a 1
--write each decoded byte to the decoded file
--If you recall from before, to do this you need to:
Name your files encode.c and decode.c
*FOR EXTRA CREDIT*
Challenge 1:
--For encode.c, test the files beforehand to make sure that every bit of the code file can fit into the mask image. Save this challenge as encode_challenge.c
Challenge 2:
--Create functions:
--One that takes a filename as an argument, and reads a PGM image from a file and return a dynamically allocated 2D array that stores the image
--One that takes a filename, a dynamically allocated 2D array, and image dimensions as arguments and writes the image to a file
--Save those functions in a separate filename, image.c. Put prototypes for those functions in a header file image.h, and use those files in a revised version of your program,
encode_challenge2.c
and decode_challenge2.c
Explanation / Answer
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BUF_LEN 256
void usage(char*);
int main(int argc, char **argv) {
int c, len, msgChar, i,j;
FILE *fpIn, *fpOut;
char *p;
char line[BUF_LEN];
char buf[BUF_LEN];
if (argc != 3) {
usage(argv[0]);
printf("Must have an input file and an output file as command line arguments");
}
if ((fpIn = fopen(argv[1], "r")) == NULL) {
printf("Error opening file %s for reading. ", argv[1]);
return 1;
}
if ((fpOut = fopen(argv[2], "w")) == NULL) {
printf("Error opening file %s for writing. ", argv[2]);
return 1;
}
printf("Please enter the length of your message ");
scanf("%u",&len);
printf("Please enter the message you want to hide ");
if (fgets(buf, sizeof(buf), stdin) != NULL)
{
if ((p = strchr(buf, ' ')) != NULL)
*p = '';
}
while (!feof(fpIn))
{
if (fgets(line, BUF_LEN, fpIn) != NULL) {
fprintf(fpOut, "%s", line);
if (line[0] != 'P' && line[1] != '6'){
printf("not a properly formatted .ppm file ");
return -1;
}
else if (fgets(line, BUF_LEN, fpIn) != NULL)
{
fprintf(fpOut, "%s", line);
while (line[0] == '#' && (fgets(line, BUF_LEN, fpIn) != NULL)){
printf("reading comments ");
fprintf(fpOut, "%s", line);
}
}
}
if (fgets(line, BUF_LEN, fpIn) != NULL){
fprintf(fpOut, "%s", line);
}
if (fgets(line, BUF_LEN, fpIn) != NULL){
fprintf(fpOut, "%s", line);
}
/* at pixel data, write length of message first, then message */
msgChar = len;
for (j = 0; j < 8; j++){
c = fgetc(fpIn); /* get next char of input stream */
unsigned int temp = (msgChar >> j) & 1;
if (c & 1 && temp == 0)
{
c = c - 1;
fprintf(fpOut, "%c", c);
}
else
{
c = c | temp;
fprintf(fpOut, "%c", c);
}
}
for (i = 0; i < len; i++){
msgChar = buf[i];
for (j = 0; j < 8; j++){
c = fgetc(fpIn); /* get next char of input stream */
unsigned int temp = (msgChar >> j) & 1;
if (c & 1 && temp == 0)
{
c = c - 1;
fprintf(fpOut, "%c", c);
}
else
{
c = c | temp;
fprintf(fpOut, "%c", c);
}
}
}
}
fclose(fpIn);
fclose(fpOut);
/* test read message */
fpIn = fopen(argv[2], "r");
while (!feof(fpIn))
{
if (fgets(line, BUF_LEN, fpIn) != NULL) {
if (line[0] != 'P' && line[1] != '6'){
printf("not a properly formatted .ppm file ");
return -1;
}
else if (fgets(line, BUF_LEN, fpIn) != NULL)
{
while (line[0] == '#' && (fgets(line, BUF_LEN, fpIn) != NULL)){
printf("reading comments ");
}
}
}
if (fgets(line, BUF_LEN, fpIn) != NULL){
printf("reading width and height");
}
if (fgets(line, BUF_LEN, fpIn) != NULL){
printf("reading color value");
}
/* at pixel data, write length of message first, then message */
msgChar = 0;
for (j = 0; j < 8; j++){
c = fgetc(fpIn); /* get next char of input stream */
int temp = c & 1;
temp = temp << (7 - j);
msgChar = msgChar & temp;
}
printf("Message length is %d", msgChar);
len = msgChar;
for (i = 0; i < len; i++){
msgChar = 0;
for (j = 0; j < 8; j++){
c = fgetc(fpIn); /* get next char of input stream */
int temp = c & 1;
temp = temp << (7 - j);
msgChar = msgChar & temp;
}
printf("%c", msgChar);
}
}
return 0;
}
void usage(char * prog_name){
printf("usage: %s filename ", prog_name);
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.