hippocampus
hippocampus

Reputation: 33

Resizing image algorithm in python

So, I'm learning my self python by this tutorial and I'm stuck with exercise number 13 which says:

Write a function to uniformly shrink or enlarge an image. Your function should take an image along with a scaling factor. To shrink the image the scale factor should be between 0 and 1 to enlarge the image the scaling factor should be greater than 1.

This is not meant as a question about PIL, but to ask which algorithm to use so I can code it myself.

I've found some similar questions like this, but I dunno how to translate this into python.

Any help would be appreciated.

I've come to this:

import image

win = image.ImageWin()
img = image.Image("cy.png")

factor = 2

W = img.getWidth()
H = img.getHeight()

newW = int(W*factor)
newH = int(H*factor)

newImage = image.EmptyImage(newW, newH)

for col in range(newW):
    for row in range(newH):
        p = img.getPixel(col,row)
        newImage.setPixel(col*factor,row*factor,p)

newImage.draw(win)

win.exitonclick()

I should do this in a function, but this doesn't matter right now. Arguments for function would be (image, factor). You can try it on OP tutorial in ActiveCode. It makes a stretched image with empty columns :.

Upvotes: 1

Views: 16243

Answers (3)

Hans Then
Hans Then

Reputation: 11322

You can do that using the Python Imaging Library.

Image.resize() should do what you want.

See http://effbot.org/imagingbook/image.htm

EDIT

Since you want to program this yourself without using a module, I have added an extra solution.

You will have to use the following algorithm.

load your image extract it's size calculate the desired size (height * factor, width * factor) create a new EmptyImage with the desired size

Using a nested loop through the pixels (row by column) in your image. Then (for shrinking) you remove some pixels every once in while, or for (enlarging) you duplicate some pixels in your image.

If you want you want to get fancy, you could smooth the added, or removed pixels, by averaging the rgb values with their neighbours.

Upvotes: 1

Mark Ransom
Mark Ransom

Reputation: 308520

Your code as shown is simple and effective for what's known as a Nearest Neighbor resize, except for one little bug:

    p = img.getPixel(col/factor,row/factor)
    newImage.setPixel(col,row,p)

Edit: since you're sending a floating point coordinate into getPixel you're not limited to Nearest Neighbor - you can implement any interpolation algorithm you want inside. The simplest thing to do is simply truncate the coordinates to int which will cause pixels to be replicated when factor is greater than 1, or skipped when factor is less than 1.

Upvotes: 2

Dave
Dave

Reputation: 3956

Mark has the correct approach. To get a smoother result, you replace:

p = img.getPixel(col/factor,row/factor)

with a function that takes floating point coordinates and returns a pixel interpolated from several neighboring points in the source image. For linear interpolation it takes the four nearest neigbors; for higher-order interpolation it takes a larger number of surrounding pixels.

For example, if col/factor = 3.75 and row/factor = 1.9, a linear interpolation would take the source pixels at (3,1), (3,2), (4,1), and (4,2) and give a result between those 4 rgb values, weighted most heavily to the pixel at (4,2).

Upvotes: 1

Related Questions