Let me reframe how you index into your image, and this whole problem will go away.
You define the image as:
vector<double> data = {1,2,3,4,5,6};
int width = 2;
int height = 3;
I suggest you also need the strides, how to increase or decrease the index into data to go to the next pixel along each dimension:
int h_step = 1;
int v_step = width;
And also an origin, the index of the pixel at (0,0):
int origin = 0;
Your loop over the pixels now is:
for (int i = 0; i < height; ++i) {
int index = origin + i * v_step;
for (int j = 0; j < width; ++j, index += h_step) {
std::cout << data[index] << ' ';
index += h_step;
}
std::cout << '\n';
}
std::cout << '\n';
[Note that I'd prefer to use std::size_t and/or std::ptrdiff_t over int, but I left the int in to keep changes from your code minimal.]
The double loop above prints the pixel values in address order, starting with the first one, which is considered to be at the bottom left of the image (we print downwards, so it shows upside-down here, ignore that):
1 2
3 4
5 6
You now want to flip the image, so that the pixel at index (0,0) is the top-left pixel. This requires updating the origin to point to the top-left pixel, and the v_step to move downwards:
origin = (height - 1) * v_step
v_step = -v_step;
The exact same double-loop above now outputs the data in the new order:
5 6
3 4
1 2
You didn't need to copy any data over, you didn't need to reorder or reorganize your pixels, all you needed to do was to specify a new origin and strides. This trick allows you to rotate the image over multiples of 90 degrees, mirror and flip the image as you please.
[Imaging libraries usually have origin be a pointer rather than an index, which avoids one addition per pixel accessed, but this is a minor difference, as memory access generally takes more time than an addition.]
That said, I highly recommend that you use an existing image processing library to do all this stuff, so you don't need to reinvent the wheel.