473,323 Members | 1,574 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,323 software developers and data experts.

File input/output

I'm writing a stagenography program to experiment with how it works.
The algorithm I'm using appears to be producing the correct
result...however I'm struggling with the file input. I never learned
file input/output very well (I self taught all the programming I
know...and my c++ book was not good) and so I'm not sure what's wrong
with this. The problem is the function void encodemsg(fstream *img,
fstream *msg, fstream *out, char key[])

on line 69 I attempt to set img->seekg(int) to the point I want to begin
the embedding at. However it constantly stays at -1 as the img->tellg()
on line 77 shows. I don't understand why since it should start at 87
since that is what I intend to have it set to on line 69. Any help
would be appreciated as well if anyone has a good c++ file operations
tutorial they know of it would be appreciated.
/* An example of stranography. This program hides another file (most likely a txt message) inside a
* 24 bit bmp image file. It changes the LSB of each byte of the image data. This alters the color
* of each pixel by a small amount that should be undetectable visually.
*/

#include <fstream>
#include <iostream>

#define BITS_CHAR (sizeof(char) * 8)
#define BMPSTART 55

using namespace std;

void encodechar(char *, char , char *);
void encodemsg(fstream *, fstream *, fstream *, char *);
void encodeint(char *, int, char*);
void decodechar(char *, char );
void decodemsg(fstream *, fstream *, char *);
int decodeint(char*);
int filesizer(fstream *);
bool fileopener(fstream *, char *, bool);
char cipher(char *, char *);
int cipherint(int , int);
bool checksize(fstream *, fstream *);

using namespace std;

bool checksize(fstream *image, fstream *message)
{
// Verifies the message is small enough to fit in the bitmap
if ((filesizer(message) * 8) (filesizer(image) - (BMPSTART + 8 * sizeof(int))))
return false;
else
return true;
}

char cipher(char message, char key)
{
// XOR crypts the message to aid in protecting the message.
// Todo: Add better encryption
return (message ^ key);

}

int cipherint(int len, int key)
{
return (len ^ key);
}

void encodemsg(fstream *img, fstream *msg, fstream *out, char key[])
{
/* Acts as a driver to hide the work that goes into encoding the message from main.
*/
/* Possibly rewrite...since we are using an image copy already we might be able to
* change the fstream out to do both input and output saving us having to pass it in
* as well as simplifying the code.
*/
int i, j, key_size, msg_size, cryptsize, msgkey;
char imgbuffer[BITS_CHAR], outbuffer[BITS_CHAR], msgbuffer, bite, msgcrypt;
char imgintbuff[BITS_CHAR * sizeof(int)], intkey[sizeof (int)];
char outintbuff[BITS_CHAR * sizeof(int)];

key_size = strlen(key);

msg_size = filesizer(msg);

img->seekg(BMPSTART + 8 * (sizeof(int))); // Leave room for an int (msgsize)
out->seekp(BMPSTART + 8 * (sizeof(int))); // So we can encode the message size
msg->seekg(0);
for (i = 0; !msg->eof(); i++) { // Read the image and message, ecrypt the message
if (i >= key_size) // then encode the message into the output image
i = 0;
cout << img->tellg() << endl; // debug info
cout << out->tellp() << endl; // debug info
img->read(imgbuffer, BITS_CHAR);
msg->read(&msgbuffer, sizeof(char));
msgcrypt = cipher(msgbuffer, key[i]);
encodechar(imgbuffer, msgcrypt, outbuffer);
out->write(outbuffer, BITS_CHAR);
}

out->seekp(BMPSTART);
img->seekg(BMPSTART);

for (i = 0; i < sizeof(int); i++) {
intkey[i] = key[i];
}

msgkey = atoi(key);

img->read(imgintbuff, (BITS_CHAR * sizeof(int)));
cryptsize = cipherint(msg_size, msgkey);
encodeint(imgintbuff, cryptsize, outintbuff);
out->write(outintbuff, (BITS_CHAR * sizeof(int)));

return;
}

void decodemsg(fstream *img, fstream *msg, char key[])
{
// Acts as a driver between main and the function to decode the chars

int i, j, key_size, msg_len, msgkey;
char imgbuffer[BITS_CHAR], msgbuffer, msg_lenbuff[sizeof(int)];
char imgintbuff[BITS_CHAR * sizeof(int)], intkey[sizeof (int)];
char outintbuff[BITS_CHAR * sizeof(int)];

key_size = strlen(key);

img->seekg(BMPSTART);
msg->seekp(0);

for (i = 0; i < sizeof(int); i++) { // Decode and decrypt the message length from the image
intkey[i] = key[i];
}

msgkey = atoi(key);

img->read(imgintbuff, (BITS_CHAR * sizeof(int)));
msg_len =decodeint(imgintbuff);
msg_len = cipherint(msg_len, msgkey);

for (i = 0, j = 0; i < msg_len; i++, j++) { //Read image then send it to be decoded and deciphered
if (j >= key_size)
j = 0;
img->read(imgbuffer, BITS_CHAR);
decodechar(imgbuffer, msgbuffer);
msgbuffer = cipher(msgbuffer, key[j]);
msg->write(&msgbuffer, sizeof(char));
}
return;
}

void encodechar(char bitmap[BITS_CHAR], char message, char retbitmap[BITS_CHAR])
{
// Encdodes a char into a bitmap takes 8 bytes of the bit map.
// Todo: Make it so larger messages can be encoded at the exchange of image quality (use more bits)
int i, shift;

shift = (BITS_CHAR - 1);

for (i = 0; i < BITS_CHAR; i++, shift--) {
retbitmap[i] = (bitmap[i] & 0xFF) | ((message >shift) & 0x01);
}
return;
}

void decodechar(char bitmap[BITS_CHAR], char message)
{
// Decode chars from the bytes of image data
int i;

message = 0x00;

for (i = 0; i < BITS_CHAR; i++) {
bitmap[i] = bitmap[i] & 0x01; // Mask out all except last bit
message = message | (bitmap[i] << (BITS_CHAR - i)); //move bit to correct spot and OR it in
}
return;
}

void encodeint(char bitmap[BITS_CHAR * sizeof(int)], int len, char retbitmap[BITS_CHAR * sizeof(int)])
{
int i, shift;

shift = ((BITS_CHAR * sizeof(int)) - 1);

for (i = 0; i < (BITS_CHAR * sizeof(int)); i++, shift--) {
retbitmap[i] = (bitmap[i] & 0xFF) | ((len >shift) & 0x01);
}
return;
}

int decodeint(char bitmap[BITS_CHAR * sizeof(int)])
{
int i, len;

len = 0x00;

for (i = 0; i < (BITS_CHAR * sizeof(int)); i++) {
bitmap[i] = bitmap[i] & 0x01; // Mask out all except last bit
len = len | (bitmap[i] << ((BITS_CHAR * sizeof(int)) - i)); //move bit to spot and OR it in
}
return len;
}

void copyimage(fstream *image, fstream *output)
{
/* Duplicates the image. The encode work is all done on the copy of the image
*/
char buffer;
int i;

image->seekg(0);
image->seekp(0);

while (!image->eof()) {
image->read(&buffer, sizeof(char));
output->write(&buffer, sizeof(char));
}
return;
}

int filesizer(fstream *file)
{
// Determines the file size by seeking the end of the file
int size1 = 0, size2 = 0;

file->seekg(0, ios::end);
size1 = file->tellg();
file->seekp(0, ios::end);
size2 = file->tellp();

if (size2 size1) {
size1 = size2;
}
file->seekg(0);
file->seekp(0);
return size1;
}

bool fileopener(fstream *file, char filename[], bool mode)
{
/* Used to open a file. Tests to make sure it's open and if it's goint to be used for input
* that the file has data in it.
*/
// Todo: make it confirm overwrite of nonempty output files

int size;

if (mode == 1) {
file->open(filename, ios::in);
if (file->is_open()) {
if (filesizer(file) <= 0) {
cerr << "Input file is empty!\n";
return false;
}
else return true;
}
else {
cerr << "File " << filename << " Failed to open!\n";
return false;
}
}
if (mode == 0) {
file->open(filename, ios::out);
if (file->is_open()) {
return true;
}
else {
cerr << "File " << filename << " Failed to open!\n";
return false;
}
}
return false;
}

int main(int argc, char *argv[])
{
int i;
fstream image, message, image_out;

if ((argc < 4) || (argc < 5)) {
cerr << "Usage: bmpmess <image_file<message_file[image_out] <key>\n";
return EXIT_FAILURE;
}

if (!fileopener(&image, argv[1], 1))
return EXIT_FAILURE;
if (argc == 4) {
if (!fileopener(&message, argv[2], 0))
return EXIT_FAILURE;
decodemsg(&image, &message, argv[3]);
}

if (argc == 5) {
if (!fileopener(&image_out, argv[3], 0))
return EXIT_FAILURE;
if (!fileopener(&message, argv[2], 1))
return EXIT_FAILURE;
if (!checksize(&image, &message)) {
cerr << "Image too small for message\n";
return EXIT_FAILURE;
}
copyimage(&image, &image_out);
encodemsg(&image, &message, &image_out, argv[4]);
}
return 0;
}

Mar 15 '07 #1
3 6064
"John Williams" <dr*********@gmail.comwrote in message
news:fS******************@newsfe16.phx...
: I'm writing a stagenography program to experiment with how it works.
You mean Steganography, I assume.

: The algorithm I'm using appears to be producing the correct
: result...however I'm struggling with the file input. I never learned
: file input/output very well (I self taught all the programming I
: know...and my c++ book was not good) and so I'm not sure what's wrong
: with this. The problem is the function void encodemsg(fstream *img,
: fstream *msg, fstream *out, char key[])

One key problem I saw while skimming through the code is that
you appear to be opening the files in *text* mode, instead
of binary mode. For instance:
file->open(filename, ios::in);
Because you are processing binary files (as .bmp-s are), you should
be writing:
file->open(filename, ios::in||ios::binary );
Files opened in text mode are likely to choke on the first null
byte, or cause other problems with newline character converstions.

Also, for binary i/o, you should use the streambuf instances
themselves, rather than the stream classes.

Finally you have to deal with possibly inconsistent error
reporting (exceptions vs. error flags, depending on the
configuration of a specific instance), cryptic member function
names (sbumpc, etc), and a sub-par performance on most platforms.

: on line 69 I attempt to set img->seekg(int) to the point I want
: to begin the embedding at. However it constantly stays at -1 as
: the img->tellg() on line 77 shows.
: I don't understand why since it should start at 87
: since that is what I intend to have it set to on line 69. Any help
: would be appreciated as well if anyone has a good c++ file operations
: tutorial they know of it would be appreciated.
Sorry, no specific suggestions come to mind beyond what a trivial
google or yahoo search will bring up. (e.g.
http://www.digilife.be/quickreferenc...%20Library.pdf)

Truth is, I am among the (many) C++ programmers who find
that the standard C++ file I/O is ill-suited for binary I/O.
It is usually easier and more efficient to use the C (fopen etc)
file i/o interface, with thin wrapper implementing RAII.
[ I tend to use platform-specific io tools, which take advantage
of memory-mapping, when available, for better performance ]

But I hope that the rest of my advice will help,
Ivan

--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <http://www.brainbench.com

Mar 15 '07 #2
John Williams wrote:
I'm writing a stagenography program to experiment with how it works. The
algorithm I'm using appears to be producing the correct result...however
I'm struggling with the file input. I never learned file input/output
very well (I self taught all the programming I know...and my c++ book
was not good) and so I'm not sure what's wrong with this. The problem
is the function void encodemsg(fstream *img, fstream *msg, fstream *out,
char key[])

on line 69 I attempt to set img->seekg(int) to the point I want to begin
the embedding at. However it constantly stays at -1 as the img->tellg()
on line 77 shows. I don't understand why since it should start at 87
since that is what I intend to have it set to on line 69. Any help
would be appreciated as well if anyone has a good c++ file operations
tutorial they know of it would be appreciated.

First off, PLEASE MARK the lines you are referring to. Nobody here wants
to count the lines in your program.

Your program has a number of robustness issues and downright logic
problems. Your first misconception is how eof() works. eof()
returns true only after a read operation as returned error. You
fail to check for this.

Your fileopener should open the streams in binary mode.

The fact that tell is returning -1 is a sign that your stream is
probably in an error state. You never seem to EVER check
for errors in your program. I haven't looked at it, but I
suspect your filesizer hit the EOF and never bothered to clear
it. Try calling clear to reset the error flags.

Mar 15 '07 #3
On Mar 15, 9:00 am, "Ivan Vecerina"
<_INVALID_use_webfo...@ivan.vecerina.comwrote:
"John Williams" <druidjai...@gmail.comwrote in message

One key problem I saw while skimming through the code is that
you appear to be opening the files in *text* mode, instead
of binary mode. For instance:
file->open(filename, ios::in);
Because you are processing binary files (as .bmp-s are), you should
be writing:
file->open(filename, ios::in||ios::binary );
Of course you meant:

file->open(filename, ios::in | ios::binary ); // logical or

This is probably the big problem.
Files opened in text mode are likely to choke on the first null
byte, or cause other problems with newline character converstions.

Also, for binary i/o, you should use the streambuf instances
themselves, rather than the stream classes.
It's fine to use fstream's read and write member functions, but you
may want to look into Ivan's suggestions if you run into performance
issues.

Beyond Ivan's advice, I'd suggest you start using references rather
than pointers for your function parameters because they're less typing
and less error prone. Also, get rid of the magic numbers for file mode
(substitute your own enum, or just use ios::in and ios::out), or
better yet, prefer ifstream and ofstream to fstream when you don't
need both reading and writing for a file. And don't use
fstream::eof(). Prefer something like:

while( my_stream )
{
// Do reading/writing with my_stream
}

See http://www.parashift.com/c++-faq-lit....html#faq-15.5

Cheers! --M

Mar 15 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: suresh | last post by:
Hello All, Iam writing a wsdl file using the Servicedescription class.The document I get is a well formed xml document.But some how when I try to add this wsdl file as a webrefernce to another...
1
by: moonriver | last post by:
In a xml file, can we make reference to another xml file so that all contents of the latter xml file will be included into the first xml file? Had better give me an example for details.
0
by: Lokkju | last post by:
I am pretty much lost here - I am trying to create a managed c++ wrapper for this dll, so that I can use it from c#/vb.net, however, it does not conform to any standard style of coding I have seen....
4
by: pank7 | last post by:
hi everyone, I have a program here to test the file IO(actually output) with buffer turned on and off. What I want to see is that there will be obvious differece in time. Here I have an input...
6
by: neo | last post by:
Hello everyone, I want to write a function that takes a simple text file as input and outputs a file such that the last line in the input file becomes the first line in the output file and the...
1
by: Osoccer | last post by:
...to a different folder and in the relocated file concatenates all of the lines in one long string with a space between each line element. Here is a fuller statement of the problem: I need a...
24
by: allpervasive | last post by:
hi all, this is reddy, a beginner to c lang,,here i have some problems in reading and modifying the contents of a file,, hope you can help to solve this problem. Here i attach the file to be...
0
by: jebbyleezer | last post by:
Hello, I have source code that builds correctly, however, after the program terminates the output file produced is empty. Here is my source code: import java.io.*; import java.util.Scanner;...
0
by: Craftkiller | last post by:
=========Program compiles on both windows and linux=========== Greetings, I am currently working on an encrpytion program that will take a file and a password string and flip the bits based on the...
4
by: rsaharia | last post by:
Hello All, I need help with this particular .pl file I picked up from http://www.veritools-usa.com/xnf2vhdl.htm What it's supposed to do is really convert an xnf file to a vhdl file. I need it for...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.