I have a file that is representing an image, here's the puddle.img file:
10 22
2222888222882222228882
2222888222882222228882
3333333333333333333333
1111111111111111111111
1111144444111111111111
1111444444411551111111
1114643434345551111111
1111333333311551111111
1111133333111111115114
1111111111111111115543

The first two numbers are the size of the image, rows and then columns. Then I have to pull in the image, and before the user sees it, it is rendered, such as a 0 = a space, 1 = -, 2 is =, 3 is a O and so forth. So they'll see this after they enter the name of the image file:

====WWW===WW======WWW=
====WW===WWWW=====WWW=
OOOOOOOOOOOOOOOOOOOOOOOO
-------------------------------------------
-----ZZZZZ------------------------------
----ZZZZZZZ--XX-----------------------
---ZBZOZOZOXXX----------------------
----OOOOOOO--XX---------------------
-----OOOOO------------------------X--Z
-------------------------------------XXZO

Basically 1-9 each mean something else when rendered before outputting to the screen.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

string filename;
int rows;
int cols;
int k = 0;
int m = 0;
string row;
const int ROW_SIZE = 40;
const int COL_SIZE = 70;
int image [ROW_SIZE][COL_SIZE];

int main()
{
  ifstream inFile;
  cout << "Enter image file name:" << endl;
  getline(cin, filename);
  inFile.open(filename.c_str());



return 0;
}

I tried messing with a getline to get the row and column number, but getline can't be used with integers, then if I use a cin I think it gets stuck on whitespace and just sits there.

Recommended Answers

All 17 Replies

> ... but getline can't be used with integers ...
it is easier to process each element in your image as a char rather than an int. eg.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cassert>
#include <iterator>
using namespace std;

struct replace_chars
{
  string operator() ( const string& str ) const
  {
    string result = str ;
    for( size_t i=0 ; i<result.size() ; ++i )
    {
      switch( result[i] )
      {
        case '0' : result[i] = ' ' ; break ;
        case '1' : result[i] = '-' ; break ;
        case '2' : result[i] = '=' ; break ;
        case '3' : result[i] = 'O' ; break ;
        // etc
      }
    }
    return result ;
 }
};

int main()
{
  string filename ;
  getline( cin, filename ) ;
  ifstream file( filename.c_str() ) ;
  size_t rows, cols ;
  file >> rows >> cols >> ws ; // skip over white spaces
  assert( rows>0 && cols>0 ) ;
  vector< string > image ;
  const string digits = "0123456789" ;
  string line ;
  while( getline( file, line ) && ( image.size() < rows ) )
  {
    assert( line.size() == cols ) ;
    assert( line.find_first_not_of(digits) == string::npos ) ;
    image.push_back( line ) ;
  }
  assert( image.size() == rows ) ;
  transform( image.begin(), image.end(),
             ostream_iterator<string>(cout,"\n"),
             replace_chars() ) ;
}

You can use >> operator to get the row/column values as ints, then read the data as individual chars

inFile >> rows >> columns;
infile.ignore( 10, '\n');  //ignores up to 10 characters, or until newline
//or
infile.ws( );  //eats up the whitespace

Then begin to read your data ( as characters, as vijayan suggests)

inFile >> image[r][c];  //inside a loop that correctly corresponds to the row and column values you read in.

Thanks for the help so far, I believe I'm now ignoring the whitespace or that first line when I'm going to try and read the image. I was told something about using nested for loops to draw in the image, you'll see it in the code I have now, I'm still messing around with it trying to get it to work. If I had used structs before or had any familiarity with them I would've gone that route, but I've never used them before. I'm trying to solve this particular problem through parallel arrays.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

string filename;
int rows;
int cols;
int k = 0;
int m = 0;
string bum;
string row;
const int ROW_SIZE = 40;
const int COL_SIZE = 70;
int image [ROW_SIZE][COL_SIZE];
int main()
{
  ifstream inFile;
  cout << "Enter image file name:" << endl;
  getline(cin, filename);
  inFile.open(filename.c_str());
  inFile >> rows >> cols;
  inFile.ignore( 10, '\n');
  inFile >> image[k][m];
  while (inFile){
  for (k =0; k < rows; k++)
      for (m =0; m < cols; m++)
  inFile >> image[k][m];
  }
  cout << image[2][3];
return 0;
}

I can tell at the moment what I have isn't doing the trick, if I try to cout just a certain piece of the image, even before converting it to whatever characters it should come out as, it always couts a 0. So what I have isn't doing the trick.

>> int image [ROW_SIZE][COL_SIZE];
OK. You want to display the image as characters ... do you need to keep it in memory? If you do you can either change the type of the image to a character array. It'll read in all the numbers as single characters. Then, once it's all read in, you can convert a '0' to a '-' or whatever, hece using the same variable.
Alternatively you could just create a second array of the same size...

It might be worth dynamically allocating enough memory for the image at runtime ... You familiar with new/delete?

I do need to keep it in memory because after I output what it looks like after being rendered, you know with the whole 0= 1=, stuff, the user can then brighten or darken the image, which will increment all the integers in the image +1 or -1 depending if they chose to brighten or darken it. I changed my array to char like you said, and now it is working, when I cout a specific cell the correct integer actually comes out. How can I get the entire image posted to the screen? More for loops?

for (k =0; k < rows; k++)
      for (m =0; m < cols; m++)
        cout<< image[k][m];

Hmm, the for loops to output the image to screen just throw it all out in a big mess, it loses its format of rows of 10 and columns of 22. I'll keep looking at it, here's my updated code:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

string filename;
int rows;
int cols;
int k = 0;
int m = 0;
string bum;
string row;
const int ROW_SIZE = 40;
const int COL_SIZE = 70;
char image [ROW_SIZE][COL_SIZE];
int main()
{
  ifstream inFile;
  cout << "Enter image file name:" << endl;
  getline(cin, filename);
  inFile.open(filename.c_str());
  inFile >> rows >> cols;
  inFile.ignore( 10, '\n');
  inFile >> image[k][m];
while (inFile){
  inFile >> image[k][m];
  for (k =0; k < rows; k++)
      for (m =0; m < cols; m++)
  inFile >> image[k][m];
  }
  for (k =0; k < rows; k++)
     for (m =0; m < cols; m++)
        cout<< image[k][m];
//  switch( image[k][m] )
//   {
//     case '0' : image[k][m] = ' ' ; break;
//     case '1' : image[k][m] = '-' ; break;
//     case '2' : image[k][m] = '=' ; break;
//     case '3' : image[k][m] = 'O' ; break;
//     case '4' : image[k][m] = 'Z' ; break;
//     case '5' : image[k][m] = 'X' ; break;
//     case '6' : image[k][m] = 'B' ; break;
//     case '7' : image[k][m] = '@' ; break;
//     case '8' : image[k][m] = 'W' ; break;
//     case '9' : image[k][m] = '#' ; break;
//   }

return 0;
}

I'm going to read up some more on switches, try and figure that out with what I have so far.

Sorry! My bad:

for (k =0; k < rows; k++) {
      for (m =0; m < cols; m++)
        cout<< image[k][m];
  cout<< "\n";
}

What I posted earlier just throws everything on one line but this should put a new like after every row. stupid mistake of mine. Sorry.

I read up on switches, and it says they're used for strings, not chars, so I'm going to have to do a bunch of if and else if statements then? Also this is what it's putting out for the image:

2288822288222222888222
2288822288222222888233
3333333333333333333311
1111111111111111111111
1114444411111111111111
1144444441155111111111
1464343434555111111111
1133333331155111111111
1113333311111111511411
11111111111111115543

It's almost right but there's something off about it. The first two digits are being cut off for some strange reason when it goes to output it.

>I read up on switches, and it says they're used for strings, not chars
Quite the contrary. A switch doesn't work with strings, but because char is an integral type, it works just fine as a switch case.

Figured that image output problem, I had two extra inFile >> image[k][m] that I didn't need. The image output is fixed.

Ah yes, you were right about the switch. Okay, I've got the program reading the image, using the switch to "render" the image if you will. Now if the user chooses to brighten or darken the image, can I use the code that rendered it the first time and basically make some small increment or decrement add-on to it? I'm going to mess around with that, I would think something like that could be possible. But on the other hand, if they could only brighten or darken once that sounds working, but I'm not sure if they kept hitting brighten or darken.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

string filename;
char decision;
int rows = 0;
int cols = 0;
int k = 0;
int m = 0;
string bum;
string row;
const int ROW_SIZE = 40;
const int COL_SIZE = 70;
char image [ROW_SIZE][COL_SIZE];

int main()
{
  ifstream inFile;
  cout << "Enter image file name:" << endl;
  getline(cin, filename);
  inFile.open(filename.c_str());
  inFile >> rows >> cols;
  inFile.ignore( 10, '\n');
while (inFile){
  for (k =0; k < rows; k++)
      for (m =0; m < cols; m++)
  inFile >> image[k][m];
  }
  cout <<"This is the original image"<<endl;
  for (k =0; k < rows; k++){
     for (m =0; m < cols; m++)
  switch (image[k][m])
  {
case '0' : cout <<" ";
                   break;
        case '1' : cout <<"-";
                   break;
        case '2' : cout <<"=";
                   break;
        case '3' : cout <<"O";
                   break;
        case '4' : cout <<"Z";
                   break;
        case '5' : cout <<"X";
                   break;
        case '6' : cout <<"B";
                   break;
        case '7' : cout <<"@";
                   break;
        case '8' : cout <<"W";
                   break;
        case '9' : cout <<"#";
                   break;
}
        cout<< image[k][m];
        cout<< "\n";
        }
cout <<"Choose"<<endl;
cout <<"B - Brighten the picture" << endl;
cout <<"D - Darken the picture" << endl;
cout <<"S - Quit and save the image" << endl;
cout <<"Q - Quit and don't save the image" << endl;
cin >> decision;

 return 0;
}

I'm still trying to figure it out, but it did dawn on me how to fix if the user continues brightening or darkening something, I made two ints, one brightcount, the other darkcount and set them to their respective first increment/decrement value, and then after the person has picked it I'll just do a brightcount or darkcount ++. I just need to figure out how to increment or decrement every cell in the parallel array.

Okay, I've got bright working, and if that's working then dark should work, but somehow my input loop is goofed. No matter what letter is typed, it brightens the image and nothing else.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

string filename;
string decision;
int brightcount = -1;
int darkcount = 1;
int rows = 0;
int cols = 0;
int k = 0;
int m = 0;
string bum;
string row;
const int ROW_SIZE = 40;
const int COL_SIZE = 70;
char image [ROW_SIZE][COL_SIZE];

int main()
{
  ifstream inFile;
  cout << "Enter image file name:" << endl;
  getline(cin, filename);
  inFile.open(filename.c_str());
inFile >> rows >> cols;
  inFile.ignore( 10, '\n');
  while (inFile){
  for (k =0; k < rows; k++)
      for (m =0; m < cols; m++)
  inFile >> image[k][m];
  }
  cout <<"This is the original image"<<endl;
  for (k =0; k < rows; k++){
     for (m =0; m < cols; m++)
switch (image[k][m])
  {
        case '0' : cout <<" ";
                   break;
        case '1' : cout <<"-";
                   break;
        case '2' : cout <<"=";
                   break;
        case '3' : cout <<"O";
                   break;
        case '4' : cout <<"Z";
                   break;
        case '5' : cout <<"X";
                   break;
        case '6' : cout <<"B";
                   break;
        case '7' : cout <<"@";
                   break;
        case '8' : cout <<"W";
                   break;
        case '9' : cout <<"#";
                   break;
     }
        cout<< image[k][m];
        cout<< "\n";
        }
cout <<"Choose"<<endl;
cout <<"B - Brighten the picture" << endl;
cout <<"D - Darken the picture" << endl;
cout <<"S - Quit and save the image" << endl;
cout <<"Q - Quit and don't save the image" << endl;
cin >> decision;
while (decision != "Q" || "q"){
if (decision == "B" || "b"){
        for (k =0; k < rows; k++){
        for (m =0; m < cols; m++)
        switch (image[k][m] = image[k][m] + brightcount)
        {
        case '0' : cout <<" ";
                   break;
        case '1' : cout <<"-";
                   break;
        case '2' : cout <<"=";
                   break;
        case '3' : cout <<"O";
                   break;
        case '4' : cout <<"Z";
                   break;
        case '5' : cout <<"X";
                   break;
        case '6' : cout <<"B";
                   break;
        case '7' : cout <<"@";
                   break;
        case '8' : cout <<"W";
                   break;
        case '9' : cout <<"#";
                   break;
        }
        cout<< (image[k][m]);
        cout<< "\n";
        }
}

else if (decision == "D" || "d"){
        for (k =0; k < rows; k++){
        for (m =0; m < cols; m++)
        switch (image[k][m] = image[k][m] + darkcount)
        {
        case '0' : cout <<" ";
          break;
        case '1' : cout <<"-";
                   break;
        case '2' : cout <<"=";
                   break;
        case '3' : cout <<"O";
                   break;
        case '4' : cout <<"Z";
                   break;
        case '5' : cout <<"X";
                   break;
        case '6' : cout <<"B";
                   break;
        case '7' : cout <<"@";
                   break;
        case '8' : cout <<"W";
                   break;
        case '9' : cout <<"#";
                   break;
        }
        cout<< (image[k][m]);
        cout<< "\n";
        }
}


cout <<"Choose"<<endl;
cout <<"B - Brighten the picture" << endl;
cout <<"D - Darken the picture" << endl;
cout <<"S - Quit and save the image" << endl;
cout <<"Q - Quit and don't save the image" << endl;
cin >> decision;
}

 return 0;
}

I need a pair of eagle eyes on this one, there must be some little snag that's only thinking it should brighten all the time and nothing else.

>> decision == "B" || "b"
That isn't what you think... what you want is:

decision == "b" || decision == "B" or you could do some kind of toupper() usage. That applies to all the comparisons too.

I'm almost to the point of having this solved, this is my first time working with outputting data to a file, so I've got some rough code that I need some pointers on.

else if (decision == "S" || decision == "s"){
        cout << "File name? " <<"("<<filename<<")"<< endl;
        cin >> newfile;
        if (newfile == '/0'){
        outdata.open("filename");
        for (k =0; k < rows; k++){
           for (m =0; m < cols; m++)
           outdata<< (image[k][m]);
           outdata<< "\n";
           outdata.close();
           }
}
        return 0;
//      else {
//      outdata.open("newfile");
//      for (k =0; k < rows; k++){
//         for (m =0; m < cols; m++)
//         outdata<< (image[k][m]);
//         outdata<< "\n";
//         outdata.close();
//         }
//     }
//      return 0;
}

If the person doesn't enter anything then it overwrites the file that was opened, and if the user enters something then it just pours the image into that filename. I'm not sure how to use null string, and also the outdata.open requires quotation marks around whatever is inside the parenthesis so I can't use the two strings filename and newfile. And I turned my else statement into a comment at the moment because the compiler doesn't like it so I'm trying to figure out what's wrong with that now.

I'm going to mark this as solved and start a new question thread.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.