2

I need to flip a picture horizontally, without using the reverse function, I thought I had it right but the returned image is just the bottom right corner of the picture and it is not flipped.

The code I have is

def Flip(image1, image2):
    img = graphics.Image(graphics.Point(0, 0), image1)
    X = img.getWidth()
    Y = img.getHeight()
    for y in range(Y):
        for x in range(X):
            A = img.getPixel(x,y)
            r = A[0]
            g = A[1]
            b = A[2]
            color = graphics.color_rgb(r,g,b)
            img.setPixel(X-x,y,color)
    img = graphics.Image(graphics.Point(0,0), image2)
    win = graphics.GraphWin(image2, img.getWidth(), img.getHeight())
    img.draw(win)

Where did I go wrong?

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
chh
  • 167
  • 2
  • 7
  • you need to flip one picture, but your function takes two inputs ? strange ? – Stephane Rolland Apr 15 '13 at 01:13
  • the first input is the file being input and the second is the file name of the output – chh Apr 15 '13 at 01:15
  • @cah Those are confusing parameter (and local variable) names then. You're also reusing the variable `img` for two things which doesn't help. – millimoose Apr 15 '13 at 01:35
  • @cah Also it seems like you're first trying to flip `image1` in-place, except badly because you don't swap pixels thus clobbering half the data before you read it. Then you throw away the results of that, open `image2`, and draw it into itself for some reason... – millimoose Apr 15 '13 at 01:36

2 Answers2

2

Here some things that I think could be improved:

def Flip(image1, image2):
    img = graphics.Image(graphics.Point(0, 0), image1)
    X = img.getWidth()
    Y = img.getHeight()
    for y in range(Y):
        for x in range(X):
            A = img.getPixel(x,y)
            r = A[0]
            g = A[1]
            b = A[2]
            color = graphics.color_rgb(r,g,b)

This assignment could be more pythonic:

            r, g, b = img.getPixel(x,y)
            color = graphics.color_rgb(r,g,b)

            img.setPixel(X-x,y,color)

img now has the image half-flipped. This happens because you are writing the content on the same image source, losing the old content anytime until you reach the middle. (Notice that X-x will increase the image size by 1 pixel. If the image width is 100, in the first iteration X-x = 100 - 0 = 100 and because it starts from 0, the image is made wider 1 pixel.) Then, you start copying back. Also, you do not use that content because:

    img = graphics.Image(graphics.Point(0,0), image2)

Here is the problem: you just overwrote the content of img without giving it any use. Later:

    win = graphics.GraphWin(image2, img.getWidth(), img.getHeight())
    img.draw(win)

This seems unrelated with the purpose of the function (flip an image). What I would do is:

import graphics
import sys

def Flip(image_filename):
    img_src = graphics.Image(graphics.Point(0, 0), image_filename)
    img_dst = img_src.clone()
    X, Y = img_src.getWidth(), img_src.getHeight()
    for x in range(X):
        for y in range(Y):
            r, g, b = img_src.getPixel(x, y)
            color = graphics.color_rgb(r, g, b)
            img_dst.setPixel(X-x-1, y, color)

    return img_dst

if __name__ == '__main__':
    input = sys.argv[1] or 'my_image.ppm'
    output = 'mirror-%s' % input
    img = Flip (input)
    img.save(output)

Notices that the function Flip only take care of flipping the image, outside the function you can do whatever you need the image, as you can see in 'main' program.

If you want to use only one image, it is possible and more efficient. For that, you can use the same principle for swapping values between variables:

def Flip(image_filename):
    img = graphics.Image(graphics.Point(0, 0), image_filename)
    X, Y = img.getWidth(), img.getHeight()
    for x in range(X/2):
        for y in range(Y):
            r_1, g_1, b_1 = img.getPixel(x, y)
            color_1 = graphics.color_rgb(r_1, g_1, b_1)

            r_2, g_2, b_2 = img.getPixel(X-x-1, y)
            color_2 = graphics.color_rgb(r_2, g_2, b_2)

            img.setPixel(X-x-1, y, color_1)
            img.setPixel(x, y, color_2)

    return img
gpoo
  • 8,408
  • 3
  • 38
  • 53
  • I tried this and I have the image flipped now but it's still not the right size. It's my original problem where it just shows a quarter of the image but now the quarter of the image is flipped so that part is good but I don't know why it isn't the right size – chh Apr 15 '13 at 03:36
  • Ok, I see the problem. The image was being overwritten losing the information of half of the image. I added and explanation and the fix. – gpoo Apr 15 '13 at 06:18
  • I don't have sys to import, is there another way to do the clone function? or another way to write the code to fix the problem? – chh Apr 15 '13 at 15:59
  • The `import sys` part is only to make the example complete for any future reader with a similar problem, also it makes a test case simpler. You should be able to replace it by anything you need. See the another example I added. – gpoo Apr 15 '13 at 17:49
0

I know it has been a long time but you can try this!

from PIL import Image

Image.open('img.png') 

img = Image.open('img.png') 
Mirror_Image=img.transpose(Image.FLIP_LEFT_RIGHT)
Mirror_Image.save(r'imgoutput.png') 
Image.open('imgoutput.png') 
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 13 '22 at 17:19