0

I am trying to take a pgm file [just a matrix of pixels, set rows and set columns] into an array, flip it horizontally, and output it again. This is how I'm reading it in:

bool PgmPicture::readPgmFile(string inputFile)
{
    stringstream ss;
    string line = "";
    int magicNumber;
    ifstream pgmIn;
    pgmIn.open(inputFile.c_str());
if (pgmIn.fail()) { //makes sure that itemList opened okay.
    perror(inputFile.c_str());
    return false;
}
    getline(pgmIn,line);
    pgmIn >> numRows >> numCols >> magicNumber;
    for(int row = 0; row < numRows ; row++) {
    for (int col = 0; col < numCols  ; col++) {
        pgmIn >> picture[row][col]; //this array only contains pixel values, no headers or flags.
    }
}
return true;
}  

So basically, the picture's 2nd line contains 2 values: row and column. For instance, 300 and 500 means the picture is of 300 rows and 500 columns. As you can see, the function above is reading that line into numRows and numCols.

In a later function, I am trying to horizontally flip the picture by swapping pairs of pixels (e.g. the very far right one with the first one, the very far right one minus one with the very first one + 1, etc to the middle.)

Here's my function:

void PgmPicture::hflip(){
int tmp;
for(int row = 0; row < numRows  ; row++) {
    for (int col = 0; col < numCols  ; col++) {
            tmp = picture[row][col];
            picture[row][col] = picture[numRows - 1 - row][col];
            picture[numRows -1  - row][col] = tmp;
    }
  }
}

What is wrong with this here? It's just outputting the exact same picture as the original. It should be going row by row and switching each element as I described. Can you guys maybe take a look at this with fresh eyes? I've been tracing this for a while and I can't figure it out.

EDIT: I changed the code to this:

int tmp;
for(int row = 0; row < numRows  ; row++) {
    for (int col = 0; col < numCols/2 ; col++) {
            tmp = picture[row][col];
            picture[row][col] = picture[row][numCols - 1 - col];
            picture[row][numCols - 1 - col] = tmp;
    }
}

and I'm just getting a garbled mess. Here's the original: http://i493.photobucket.com/albums/rr294/Jamlegend/mammoth_zps31b72d88.png and here's the after pic: http://i493.photobucket.com/albums/rr294/Jamlegend/after_zpsdf1a8b40.png

amantonas
  • 39
  • 2
  • 6
  • 2
    1- You're not showing any output code. 2- You say flipping horizontally, but your swap is over the `row` index, which means flipping vertically. – Peter Nov 19 '14 at 20:57
  • what is the declaration of `picture` and how do you write it out again? – PeterT Nov 19 '14 at 21:10
  • picture is a `short` array, 1024x1024 – amantonas Nov 19 '14 at 21:12
  • PGM files can be a `short` array - or they can be a `byte` array. You might try this again with an 8-bit array instead. – Steven Hansen Nov 19 '14 at 21:16
  • @StevenHansen depends, some variations contain a "max-value" that can exceed 255 and when that happens, the size grows to 2 bytes per pixel. As described here: http://netpbm.sourceforge.net/doc/pgm.html – PeterT Nov 19 '14 at 21:19

5 Answers5

0

From thís line of Code:

        tmp = picture[row][col];
        picture[row][col] = picture[numRows - 1 - row][col];
        picture[numRows -1  - row][col] = tmp;

I would say: you are swapping the top pixel with the bottom pixel, top-1 with bottom-1 and so on. You said you want to swap the left with the right pixel. Your line should look like this:

        tmp = picture[row][col];
        picture[row][col] = picture[row][numCols - 1 - col];
        picture[row][numCols - 1 - col] = tmp;

Try this, it could fix your problem. Maybe you didn't see it because your image have the same top and bottom? It is most time a good idea to include an image (result and input) when have image processing code.

stupidstudent
  • 678
  • 4
  • 13
0

This:

picture[row][col] = picture[numRows - 1 - row][col];
picture[numRows -1  - row][col] = tmp;

Should be this:

picture[row][col] = picture[row][numCols - 1 - col];
picture[row][numCols - 1 - col] = tmp;

AND you will need to loop through half your columns, or else you will switch everything back again.

for (int col = 0; col < numCols / 2; col++)
Steven Hansen
  • 3,189
  • 2
  • 16
  • 12
  • Ok, I made an edit to my first post. The new output is just a big garble! I can't think of any reason why this should be off like this besides maybe the numrows and numcols are wrong, but I printed them out right before the processing and they're correct. – amantonas Nov 19 '14 at 21:10
  • Maybe your PGM file contains BYTE values, and maybe it contains SHORT values. Did you check for and accommodate both types? – Steven Hansen Nov 19 '14 at 21:19
  • the pgm file is just a space delimited list of pixel values between 0 and 255. The reading in is working just fine, I also have a simple "make negative function that subtracts each value from 255, making a negative version of the picture. This works just fine. – amantonas Nov 19 '14 at 21:30
0

You need to iterate only through half of the array. Otherwise you are swapping elements twice!

Juan Leni
  • 6,982
  • 5
  • 55
  • 87
0

I would probably do something like this:

#include <algorithm>

void hflip()
{
    for(int row = 0; row < numRows; ++row)
        std::reverse(picture[row], picture[row] + numCols);
}
Galik
  • 47,303
  • 4
  • 80
  • 117
0

That "garble" looks like an image drawn with the wrong x size. It appears that you've swapped numRows and numCols. The PGM format defines the size as WIDTH first, then HEIGHT. You're expressing WIDTH as columns of your picture.

The reason the negative works is that you write the pixels back out in the same order, so it doesn't matter. Anything where you actually care about pixel location will be wrong.

Do this instead:

pgmIn >> numCols >> numRows >> magicNumber;
Peter
  • 14,559
  • 35
  • 55
  • You're the man. This has had me so frustrated. Thanks so much! It's funny, I had that right in the function where I write the file back out, I just wasn't thinking. I appreciate the help! – amantonas Nov 20 '14 at 14:37