1

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 :.

Community
  • 1
  • 1
hippocampus
  • 33
  • 1
  • 2
  • 6

3 Answers3

2

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.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Doesn't this only address a shrinking operation? The upscaling would still probably require another approach. – jdi Sep 16 '12 at 16:05
  • @hippocampus it should work for any scale factor, since your loops are over the output size and not the input size. Have you tried it? – Mark Ransom Sep 16 '12 at 17:32
  • yes, it works, like this: p = img.getPixel(int(col/factor),int(row/factor)). Thank you very much :). – hippocampus Sep 16 '12 at 17:57
1

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.

Jonathan Root
  • 535
  • 2
  • 14
  • 31
Hans Then
  • 10,935
  • 3
  • 32
  • 51
  • Thank you for your answers, I know about PIL, but I need algorithm, not some module that does it for me. :) – hippocampus Sep 16 '12 at 14:29
  • In that case, you should loop through the pixels in your image and then (for shrinking) remove some pixels every once in while, or for (enlarging) 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. Is this enough info to get started? – Hans Then Sep 16 '12 at 14:40
  • Sorry, not. I know the theory, but I have no idea how to implement it. – hippocampus Sep 16 '12 at 14:43
1

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

Dave
  • 3,834
  • 2
  • 29
  • 44