Problem: You want to flip an image upside down.
Solution: Convert an image to a grid of pixels. Swap the positions of the top and bottom pairs of pixels and move down to swap the next pair until all the pixel positions are swapped. Convert the grid of pixels back into a flipped image.
The Image implementations (for example, image.NRGBA ) have a slice of bytes that represent pixels in the image. That’s not the most intuitive way to represent a raster image. What’s more common is a grid of pixels (because a raster image is literally a grid of pixels), so that’s the first thing you want to do — convert an image.NRGBA to a grid of pixels.
In the image package , a pixel is represented by the type color.Color so you’re going to create a 2D slice of color.Color pixels. You will extend the load function from before to do this so you can return the grid:
func load(filePath string) (grid [][]color.Color) { // open the file and decode the contents into an image file, err := os.Open(filePath) if err != nil { log.Println("Cannot read file:", err) } defer file.Close() img, _, err := image.Decode(file) if err != nil { log.Println("Cannot decode file:", err) } // create and return a grid of pixels size := img.Bounds().Size() for i := 0; i < size.X; i++ { var y []color.Color for j := 0; j < size.Y; j++ { y = append(y, img.At(i, j)) } grid = append(grid, y) } return }
To convert the image into a grid, you need to find out the size of the image. Use the Size method on the Rect struct that is returned from calling the Bounds method on the image. This returns a Point , which gives you the X and Y width and length of the image. Iterate the width and length, and at each pixel position, use the At method to get the pixel color.Color . This will give you a grid of color.Color pixels.
You will also need to extend the save function to let you save the grid of pixels back into a file:
func save(filePath string, grid [][]color.Color) { // create an image and set the pixels using the grid xlen, ylen := len(grid), len(grid[0]) rect := image.Rect(0, 0, xlen, ylen) img := image.NewNRGBA(rect) for x := 0; x < xlen; x++ { for y := 0; y < ylen; y++ { img.Set(x, y, grid[x][y]) } } // create a file and encode the image into it file, err := os.Create(filePath) if err != nil { log.Println("Cannot create file:", err) } defer file.Close() png.Encode(file, img.SubImage(img.Rect)) }
First, you need to create an image. Using the width and length of the 2D slice, create a Rect to represent the size of the image. Create a new image using the image.NewNRGBA function, passing it the Rect . Then iterate through the grid and at every position, set the color.Color pixel from the grid into the new image.
Finally, take the image and encode it into a file.
Now that you can load an image file into a grid of pixels and save it back into an image file, look at the algorithm you want to use to flip the image upside down:
func flip(grid [][]color.Color) { for x := 0; x < len(grid); x++ { col := grid[x] for y := 0; y < len(col)/2; y++ { z := len(col) - y - 1 col[y], col[z] = col[z], col[y] } } }
It’s relatively simple to flip the image with a grid of pixels. You simply iterate through each column of the grid and swap the top and bottom pixels. Here’s how you can use this algorithm to flip the image:
func main() { grid := load("monalisa.png") flip(grid) save("flipped.png", grid) }