Horizontally flipping an array?

5.4k views Asked by At

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

5

There are 5 answers

1
Peter On BEST ANSWER

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;
0
Galik On

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);
}
0
stupidstudent On

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.

3
Steven Hansen On

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++)
0
Juan Leni On

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