Go - Flipping an Image Upside Down

发布时间 2023-10-10 11:32:13作者: ZhangZhihuiAAA

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 ) 
}