Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

C++ Program In this project you will use the concept Steganography to encrypt a string of text into a bitmap image file, and then decrypt

C++ Program

In this project you will use the concept Steganography to encrypt a string of text into a bitmap image file, and then decrypt the text from the encrypted image. You will present the user with a menu of encrypt and decrypt functions to run, plus the ability to exit.

Sample run of the program:

Select the run mode:

1) Encrypt

2) Decrypt

3) Exit

=>1

Begin Encrypt Image:

Enter the text to encrypt: My C++ class is the best

Enter name (with path) of image file to read: fgcu_logo.bmp

Failed to open file: fgcu_logo.bmp

Select the run mode:

1) Encrypt

2) Decrypt

3) Exit

=>1

Begin Encrypt Image:

Enter the text to encrypt: My C++ class is the best!

Enter name (with path) of image file to read: images\fgcu_logo.bmp

Enter name (with path) of image file to write: images\fgcu_logo_enc.bmp

Encrypted Image: images\fgcu_logo.bmp

Bytes Read: 172534

Pixels Encrypted: 208

Created Image: images\fgcu_logo_enc.bmp

Bytes Written: 172534

Select the run mode:

1) Encrypt

2) Decrypt

3) Exit

=>2

Begin Unencrypt Image:

Enter name (with path) of image file to read: images\fgcu_logo_enc.bmp

Dencrypted Image: images\fgcu_logo_enc.bmp

Bytes Read: 172534

Pixels Encrypted: 208

Encrypted String: My C++ class is the best!

Select the run mode:

1) Encrypt

2) Decrypt

3) Exit

=>3

Implement the following:

Define a global enumerator RUN_MODE for modes ENCYRPT=1, UNENCRYPT=2, EXIT=3.

getRunMode Displays the user menu, then inputs and returns the run mode selected. You will need to read in to an integer variable and cast the variable to a RUN_MODE to return the enumerator value.

getTextToEncrypt Prompts the user for the text to insert into the image and returns it as a string. Call readString.

getImageFileIn Prompts the user for the name (with path if required) of a bitmap file to open, then returns an input file stream and the name of the file the user enters through output parameters, and returns an integer 0 if the file-open succeeds or -1 if it fails, or -1 if it fails and displays an error message. You must add std::ios::binary as a second parameter when opening the file. Call readString.

getImageFileOut Prompts the user for the name (with path if required) of a bitmap file to create, then returns an output file stream and name of the file entered by the user through output parameters, and returns an integer 0 if the file-open succeeds, or -1 if it fails and displays an error message. You must add std::ios::binary as a second parameter when opening the file. Call readString.

encryptString Receives the string to encrypt as a parameter and the BITMAPINFO structure as an output parameter, and returns the number of pixels used to encrypt the text.

decryptString Receives the string to that will be decrypted and the BITMAPINFO structure as output parameters, and returns the number of pixels used to encrypt the text.

readString Reads in a string from the standard input stream into a string and returns the string to the caller.

Tips:

You will need to include bitmap.h and probably in your main file.

You will need to define a variable of structure BITMAP type from bitmap.h.

You will need to call the following functions defined in bitmap.h:

o int readBitmap(ifstream& ins, BITMAP& bmOut);

o int writeBitmap(ofstream& outFile, BITMAP bmOut);

You may call any of the other functions from bitmap.h for debuggins, such as:

o void printBitmapFileHeader(BITMAPFILEHEADER bfOut);

o void printBitmapInfoHeader(BITMAPINFOHEADER biPrint);

o void printPixel(RGB pixel);

Files you need:

Bitmapp.h File:

/***************************************************************************** * Description: header file for the bitmap library *****************************************************************************/ #include #include "stdafx.h" #include #include #include "bytes.h" using namespace std;

#ifndef BITMAP_H_INCLUDED #define BITMAP_H_INCLUDED

/******************************************************************** * Define packing to a single byte for bitmap structures *******************************************************************/ #pragma pack (push, 1)

/******************************************************************** * Defines for image width and height in pixels * These must be redefined in students program with actual image sizes *******************************************************************/

struct BITMAPFILEHEADER { /* bf 14 bytes*/ WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; };

struct BITMAPINFOHEADER { /* bi 40 bytes */ DWORD biSize; DWORD biWidth; DWORD biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; DWORD biXPelsPerMeter; DWORD biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; };

struct RGB { /* rgb 3 bytes */ BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; };

struct BITMAPINFO { /* bmi */ BITMAPINFOHEADER bmiHeader; vector bmiColors; };

struct BITMAP { /* bm */ BITMAPFILEHEADER bf; BITMAPINFO bmi; };

/******************************************************************** * Bitmap Functions Declarations *******************************************************************/

// read a bitmap int readBitmap(ifstream& ins, BITMAP& bmOut); int readBitmapFileHeader(ifstream& ins,BITMAPFILEHEADER& bfOut ); int readBitmapInfoHeader(ifstream& ins, BITMAPINFOHEADER& biOut ); int readPixels(ifstream& ins, BITMAPINFO& bmi);

// write a bitmap int writeBitmap(ofstream& outFile, BITMAP bmOut); int writeBitmapFileHeader(ofstream& outFile, BITMAPFILEHEADER bfOut); int writeBitmapInfoHeader(ofstream& outFile, BITMAPINFOHEADER biOut); int writeBitmapPadding(ofstream& outFile, int bytesOut); int writeBitmapPixels(ofstream& outFile, BITMAPINFO bmiOut);

void printBitmapFileHeader(BITMAPFILEHEADER bfOut); void printBitmapInfoHeader(BITMAPINFOHEADER biPrint); void printPixel(RGB pixel);

/******************************************************************** * undefine packing for single byte *******************************************************************/ #pragma pack (pop)

#endif // BITMAP_H_INCLUDED

Byte Header file:

/***************************************************************************** * Description: header file for BYTE handeling library *****************************************************************************/ #include #include "stdafx.h" using namespace std;

/******************************************************************** * Defines for BYTE, WORD, and DWORD data size types *******************************************************************/ #define BYTE unsigned char #define WORD unsigned short #define DWORD unsigned int #define BYTE_ARRAY unsigned char

/******************************************************************** * BYTE, WORD, and DWORD Conversion Functions *******************************************************************/ int bytesToWORD(BYTE byte1, BYTE byte2); int bytesToDWORD(BYTE byte1, BYTE byte2, BYTE byte3, BYTE byte4); void WORDtoBytes(WORD wordVal, BYTE& byte1, BYTE& byte2); void DWORDtoBytes(DWORD dwordVal, BYTE& byte1, BYTE& byte2, BYTE& byte3, BYTE& byte4);

/******************************************************************** * BYTE I/O Functions *******************************************************************/ int readBytes(ifstream& ins, unsigned char bytes[], int bytesToRead); int skipBytes(ifstream& ins, int bytesToRead); int writeBytes(ofstream& outs, unsigned char bytesOut[], int bytesToWrite);

Byte CPP file:

/***************************************************************************** * Description: Functions for BYTE handeling library *****************************************************************************/ #include "bytes.h" #include "stdafx.h"

/******************************************************************** * BYTE, WORD, and DWORD Conversion Functions *******************************************************************/ /** * Convert two bytes to a WORD value. * * @param byte1 - the low BYTE * @param byte2 - the high BYTE * @return int - the WORD value of the two bytes */ int bytesToWORD(BYTE byte1, BYTE byte2) { // call the bytesToDWORD passing in the low and high bytes of // the low WORD return bytesToDWORD(byte1, byte2, 0, 0); }

/** * Convert four bytes to a DWORD value. * * @param byte1 - the low BYTE of the low WORD * @param byte2 - the high BYTE of the low WORD * @param byte3 - the low BYTE of the high WORD * @param byte4 - the high BYTE of the high WORD * @return int - the DWORD value of the four bytes */ int bytesToDWORD(BYTE byte1, BYTE byte2, BYTE byte3, BYTE byte4) { // left shift each byte by 8 to align it with its position // in the full DWORD value // (i.e. multiply each value by 2^8 * position) return (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1; }

/** * Convert a WORD value to an array of bytes. * * @param wordVal - WORD size value * @param byte1 - the low BYTE of the low WORD * @param byte2 - the high BYTE of the low WORD * @return char[] - array of bytes */ void WORDtoBytes(WORD wordVal, BYTE& byte1, BYTE& byte2) { BYTE byte3, byte4; // call the DWORD to bytes function passing // the word value passed in return DWORDtoBytes((unsigned int)wordVal, byte1, byte2, byte3, byte4); }

/** * Convert a DWORD value to an array of bytes. * * @param dwordVal - DWORD size value * @param byte1 - the low BYTE of the low WORD * @param byte2 - the high BYTE of the low WORD * @param byte3 - the low BYTE of the high WORD * @param byte4 - the high BYTE of the high WORD * @return char[] - array of bytes */ void DWORDtoBytes(DWORD dwordVal, BYTE& byte1, BYTE& byte2, BYTE& byte3, BYTE& byte4) { // get low byte of low word byte1 = (char)(dwordVal & 0X000FF);

// get high byte of low word byte2 = (char)((dwordVal >> 8) & 0X00FF);

// get low byte of high word byte3 = (char)((dwordVal >> 16) & 0X00FF);

// get high byte of high word byte4 = (char)((dwordVal >> 24) & 0X00FF); }

/******************************************************************** * BYTE I/O Functions *******************************************************************/ /** * Attempts to read n-bytes from the input stream and returns * the number of bytes successfully read. * * @param ins - the input stream to read from * @param bytes - the array of bytes to fill * @param bytesToRead - the number of bytes to read * @return int - the number of bytes read */ int readBytes(ifstream& ins, unsigned char bytes[], int bytesToRead) { int bytesRead = 0;

char next = ' '; while (!ins.fail() && bytesRead < bytesToRead) { // get the next character from the stream ins.get(next); if (!ins.fail()) { bytes[bytesRead] = (unsigned char)next; bytesRead++; } } return bytesRead; }

/** * Move the read pointer forward without storing bytes read. * * @param ins - the input stream to read from * @param bytesToSkip - the number of bytes to strip off the input stream * @return int - the number of bytes read */ int skipBytes(ifstream& ins, int bytesToSkip) { int bytesRead = 0; unsigned char temp[1]; // temp char array // just call readBytes to read one char // with a temp array for each byte to skip for (int i = 0; i < bytesToSkip; i++) { bytesRead += readBytes(ins, temp, 1); } return bytesRead; }

/** * Attempts to wite n-bytes to the output stream and returns * the number of bytes successfully written. * * @param outs - the output stream to write to * @param bytesOut - the array of bytes to write * @param bytesToWrite - the number of bytes to write from the array * @return int - the number of bytes written */ int writeBytes(ofstream& outs, unsigned char bytesOut[], int bytesToWrite) { int bytesWritten = 0;

while (!outs.fail() && bytesWritten < bytesToWrite) { outs.put(bytesOut[bytesWritten]); if (!outs.fail()) { bytesWritten++; } } return bytesWritten; }

BITMAP CPP file:

/**************************************************************************** * Purpose: bitmap image library ****************************************************************************/ #include "bitmap.h" #include #include "stdafx.h" /******************************************************************** * Bitmap Functions *******************************************************************/

/******************************************************************** * Read a bitmap structure from file *******************************************************************/

/** * Reads a bitmap file into a BITMAP structure that contains the * various bitmap header structures and the pixel array. * * @param ins - reference to an ifstream object * @param bfOut - output parameter of the BITMAP structure to fill * @return int - the number of bytes read */ int readBitmap(ifstream& ins, BITMAP& bmOut){ int bytesRead = 0; // read the File Header bytesRead = readBitmapFileHeader(ins, bmOut.bf); if(bytesRead == sizeof(BITMAPFILEHEADER)) { // read the Info Header bytesRead += readBitmapInfoHeader(ins, bmOut.bmi.bmiHeader); if (bytesRead == sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)){

// skip any color tables or other padding between the Info Header // and the pixel array if (bmOut.bf.bfOffBits > sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)) { bytesRead += skipBytes(ins, bmOut.bf.bfOffBits - (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))); }

// resize the pixel array bmOut.bmi.bmiColors.reserve(bmOut.bmi.bmiHeader.biWidth * bmOut.bmi.bmiHeader.biHeight);

// fill the pixel array bytesRead += readPixels(ins, bmOut.bmi); } }

return bytesRead; }

/** * Reads the File Header from a bitmap file and fills a BITMAPFILEHEADER * structure passed in. The function returns the number of bytes read * to fill the structure, which should be of sizeof(BITMAPFILEHEADER). * * @param ins - reference to an ifstream object * @param bfOut - output parameter of the BITMAPFILEHEADER structure to fill * @return int - the number of bytes read */ int readBitmapFileHeader(ifstream& ins, BITMAPFILEHEADER& bfOut ) { // read in the number of bytes of the bitmap file header (14 bytes) // all at once, and overwrite the whole structure, thus filling // each area of the structure with the correct values ins.read((char*)&bfOut, sizeof(BITMAPFILEHEADER)); return (int)ins.gcount(); }

/** * Reads the Info Header from a bitmap file and fills a BITMAPINFOHEADER * structure passed in. The function returns the number of bytes read * to fill the structure, which should be of sizeof(BITMAPINFOHEADER). * * @param ins - reference to an ifstream object * @param biOut - output parameter of the BITMAPINFOHEADER structure to fill * @return int - the number of bytes read */ int readBitmapInfoHeader(ifstream& ins, BITMAPINFOHEADER& biOut ) { // read in the number of bytes of the bitmap info header (40 bytes) // all at once, and overwrite the whole structure, thus filling // each area of the structure with the correct values ins.read((char*)&biOut, sizeof(BITMAPINFOHEADER)); return (int)ins.gcount(); }

/** * Read all pixels into the pixel array passed in. * * @param ins - reference to an ifstream object * @param pixelArray - pixel array to fill * @return int - the number of bytes read */ int readPixels(ifstream& ins, BITMAPINFO& bmi){ int bytesRead = 0;

// calcluate how many bytes make up each row int pixelPerRow = (int)floor(bmi.bmiHeader.biWidth * sizeof(RGB)); // calcuate the amount of padding to add at the end of each row int rowPadding = (int)floor(bmi.bmiHeader.biSizeImage / bmi.bmiHeader.biHeight) - pixelPerRow;

// temp byte array BYTE tmp[sizeof(RGB)] = { 0 }; // for each row in the bitmap for (unsigned int rows = 0; rows < bmi.bmiHeader.biHeight; rows++) { // for each pixel in the row for (unsigned int cols = 0; cols < bmi.bmiHeader.biWidth; cols++) { // read the next pixel into the temp array bytesRead += readBytes(ins, tmp, sizeof(RGB)); // now put the pixel bytes into an RGB structure RGB nextPixel = { tmp[0], tmp[1], tmp[2] }; // add the RGB structure to the pixel array bmi.bmiColors.push_back(nextPixel); } // add padding to the end of each row bytesRead += readBytes(ins, tmp, rowPadding); } return bytesRead; }

/******************************************************************** * Write a bitmap structure to file *******************************************************************/

/** * Write a bitmap to an external file. * * @param outFile - reference to an ofstream object * @param bmOut - BITMAP structure to write * @return int - the number of bytes written */ int writeBitmap(ofstream& outFile, BITMAP bmOut) { int bytesWritten = 0;

bytesWritten += writeBitmapFileHeader(outFile, bmOut.bf); bytesWritten += writeBitmapInfoHeader(outFile, bmOut.bmi.bmiHeader); int padding = bmOut.bf.bfOffBits - sizeof(BITMAPFILEHEADER) - bmOut.bmi.bmiHeader.biSize; bytesWritten += writeBitmapPadding(outFile, padding); bytesWritten += writeBitmapPixels(outFile, bmOut.bmi); return bytesWritten; }

/** * Write the bitmap file header to file * * @param outFile - reference to an ofstream object * @param bfOut - bitmap file header structure to write * @return int - the number of bytes written */ int writeBitmapFileHeader(ofstream& outFile, BITMAPFILEHEADER bfOut) { // write the whole bitmap file header structure as // a stream of bytes for the number of bytes in the structure outFile.write((char*)&bfOut, sizeof(BITMAPFILEHEADER)); return sizeof(BITMAPFILEHEADER); }

/** * Write the bitmap info header to file * * @param outFile - reference to an ofstream object * @param biOut - bitmap info header structure to write * @return int - the number of bytes written */ int writeBitmapInfoHeader(ofstream& outFile, BITMAPINFOHEADER biOut) { // write the whole bitmap info header structure as // a stream of bytes for the number of bytes in the structure outFile.write((char*)&biOut, sizeof(BITMAPINFOHEADER)); return sizeof(BITMAPINFOHEADER); }

/** * Write padding to bitmap file * * @param outFile - reference to an ofstream object * @param bytesOut - number of padding bytes to write * @return int - the number of bytes written */ int writeBitmapPadding(ofstream& outFile, int bytesOut) { int bytesWritten = 0; // write one padding byte at a time for (int i=0; i< bytesOut; i++){ BYTE padding[1] = {0}; // temp padding array bytesWritten += writeBytes(outFile, padding, 1); }

return bytesWritten; }

/** * Write pixels to bitmap file * * @param outFile - reference to an ofstream object * @param bmiOut - bitmap info header structure with pixel array * @return int - the number of bytes written */ int writeBitmapPixels(ofstream& outFile, BITMAPINFO bmiOut) { int bytesWritten = 0;

// calcluate how many bytes make up each row int pixelPerRow = (int)floor(bmiOut.bmiHeader.biWidth * sizeof(RGB)); // calcuate the amount of padding to add at the end of each row int rowPadding = (int)floor(bmiOut.bmiHeader.biSizeImage / bmiOut.bmiHeader.biHeight) - pixelPerRow; // padding array char *pad = new char[rowPadding](); // defalut array of row padding size to all zeros

int pixel = 0; // for each row in the bitmap for (unsigned int rows = 0; rows < bmiOut.bmiHeader.biHeight; rows++) { // for each pixel in the row for (unsigned int cols = 0; cols < bmiOut.bmiHeader.biWidth; cols++) { // get the next pixel into a byte array BYTE bytes[sizeof(RGB)] = { bmiOut.bmiColors[pixel].rgbBlue, bmiOut.bmiColors[pixel].rgbGreen, bmiOut.bmiColors[pixel].rgbRed }; // write the byte array out bytesWritten += writeBytes(outFile, bytes, sizeof(RGB)); pixel++; } // write row padding after each row outFile.write(pad, rowPadding); bytesWritten += rowPadding; }

return bytesWritten; }

/******************************************************************** * Print a bitmap structure *******************************************************************/

/** * Prints a BITMAPFILEHEADER structure to stdout. * * @param bfPrint - BITMAPFILEHEADER to print */ void printBitmapFileHeader(BITMAPFILEHEADER bfPrint){ cout << "BITMAPFILEHEADER" << endl; cout << '\t' << "bfType: " << (char)(bfPrint.bfType & 0X00FF) << (char)(bfPrint.bfType >> 8) << endl; cout << '\t' << "bfSize: " << bfPrint.bfSize << endl; cout << '\t' << "bfReserved1: " << bfPrint.bfReserved1 << endl; cout << '\t' << "bfReserved2: " << bfPrint.bfReserved2 << endl; cout << '\t' << "bfOffBits: " << bfPrint.bfOffBits << endl; }

/** * Prints a BITMAPINFOHEADER structure to stdout. * * @param biPrint - BITMAPINFOHEADER to print */ void printBitmapInfoHeader(BITMAPINFOHEADER biPrint){ cout << "BITMAPINFOHEADER" << endl; cout << '\t' << "biSize:" << biPrint.biSize << endl; cout << '\t' << "biWidth:" << biPrint.biWidth << endl; cout << '\t' << "biHeight:" << biPrint.biHeight << endl; cout << '\t' << "biPlanes:" << biPrint.biPlanes << endl; cout << '\t' << "biBitCount:" << biPrint.biBitCount << endl; cout << '\t' << "biCompression:" << biPrint.biCompression << endl; cout << '\t' << "biSizeImage:" << biPrint.biSizeImage << endl; cout << '\t' << "biXPelsPerMeter:" << biPrint.biXPelsPerMeter << endl; cout << '\t' << "biYPelsPerMeter:" << biPrint.biYPelsPerMeter << endl; cout << '\t' << "biClrUsed:" << biPrint.biClrUsed << endl; cout << '\t' << "biClrImportant:" << biPrint.biClrImportant << endl; }

/** * Print a single RGB pixel. * (most bitmaps are going to be too large to print all of the pixels * to the console, but this function can be called in a loop for each pixel * you want printed out) * * @param pixel - the RGB pixel to print */ void printPixel(RGB pixel){ cout << "rgb(" << (unsigned int)pixel.rgbRed << ", " << (unsigned int)pixel.rgbGreen << ", " << (unsigned int)pixel.rgbBlue << ")"; }

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Samsung Galaxy S23 Ultra Comprehensive User Manual

Authors: Leo Scott

1st Edition

B0BVPBJK5Q, 979-8377286455

More Books

Students also viewed these Databases questions