pythonimagejythonimage-rotationjes

Flipping Image Python


I am trying to flip an image horizontally.

From this:

Original Pic

To This:

Flipped Pic

But I keep getting it mirrored half way.

Like This:

Result I get

I am trying to reverse the x-axis index and I don't understand why it is being divided.

def flip(picture):
    height = getHeight(picture)
    width = getWidth(picture)
    newPicture = makeEmptyPicture(width, height)
    x2 = width-1
    for x in range(0, width):
        y2 = 0
        for y in range(0, height):
            pxl = getPixel(picture, x, y)
            newPxl = getPixel(picture, x2, y2)
            color = getColor(pxl)
            setColor(newPxl, color)
            y2 = y2+1
        x2 = x2-1
    return picture

The rest of my code:

def d():    
    f = pickAFile()
    picture = makePicture(f)        
    newPicture = copy(picture)        
    writePictureTo(newPicture, r"D:\FOLDER\newPic4.jpg")
    explore(newPicture)

Solution

  • In your flip() function (like in any function), as mentioned by the other answers, you return picture which is the image passed as a parameter of the function but is defined in d()...

    It is a matter of scope of the variables, so I invite you to have a look again at the discussion we had here.

    Here, you had two choices (you made a melting between the two):

    Details about the 2d option :

    The important thing here is that the picture variable belongs to the d() function (d() is the scope of it). In the mean time the newPicture variable belongs to the flip() function (flip() is its scope). So the life time of the newPicture is flip() (i.e. it is destroyed as soon as you terminate the execution of the flip() function, while returning). And d() doesn't know anything about this newPicture, unless you return it to d().

    So, in short (assuming we are talking about the second option):

    1) Create a function that takes a picture as parameter (flip())

    2) Inside flip(), create a local variable newPicture and modify that one only, such that the original picture remains unchanged

    3) Return the newly updated newPicture to the parent scope. Here d() is calling flip(), so it is the parent scope. We have to create a 3d variable (which belongs to d() scope), to keep a hand on what was returned by flip():

    def flip(picture)
        # Create newPicture
        # Modify newPicture (using the information from the "picture" parameter)
        setColor(newPicture, ...)
        ...
        return newPicture
    
    def d():
        file = PickAFile()
        original_pic = makePicture(file) 
        finalNewPicture = flip(original_pic)     # {1}
        show(finalNewPicture)
    

    {1}: Here we assign the value returned by flip (i.e. newPicture) to the variable of higher scope finalNewPicture (handler)...

    I hope it helps you to understand the logic behind this. It is like Russian dolls: newPicture is used inside flip(), which is used inside d(), ...


    EDIT :

    I also want to give an explanation about the 1st option...

    1) Create a function that takes a picture as parameter (flip())

    2) Inside flip(), modify directly the higher scoped picture variable

    3) Do not return anything from flip()

    This would result in this :

    def flip(picture)
        # Simply modify the variable "picture", given as a parameter
        setColor(picture, ...)
        ...
        # Do not return anything
    
    def d():
        file = PickAFile()
        original_pic = makePicture(file) 
        flip(original_pic)                     # {1}
        show(original_pic)
    

    {1}: Here flip() made the changes directly on the input picture, so we can display the original modified picture directly (original_pic). No need for an intermediate handler variable.


    Code for option 1 : (as you already have it working for option 2)

    def flip(picture):
      height = getHeight(picture)
      width = getWidth(picture)
    
      x2=width-1
      for x in range(0, width/2):   # Only process the half way
        y2=0
        for y in range(0, height):
          # swap pix and pix2
          pxl = getPixel(picture, x, y)
          pxl2 = getPixel(picture, x2, y2)
          color = getColor(pxl)
          color2 = getColor(pxl2)
          setColor(pxl2, color)
          setColor(pxl, color2)
          y2=y2+1
        x2=x2-1  
    
    def d():    
      f = pickAFile()
      original_picture = makePicture(f)        
      flip2(original_picture)        
      show(original_picture)
    
    d()
    

    Note : flip could have been widely simplified as follows :

    def flip2(picture):
      height = getHeight(picture)
      width = getWidth(picture)
    
      for x in range(0, width/2):   # Only process the half way
        for y in range(0, height):
          # swap pix and pix2
          pxl = getPixel(picture, x, y)
          pxl2 = getPixel(picture, width-1-x, y)
          color = getColor(pxl)
          color2 = getColor(pxl2)
          setColor(pxl2, color)
          setColor(pxl, color2)