使用Python3.2重新缩放图像

时间:2013-10-02 20:32:34

标签: python image-processing python-3.x image-resizing

我正在处理一个从命令行获取图像名称的python代码,并将其打印在一个窗口中,重新调整为用户的喜好,即输入 python3.2 resize.py image.gif 2 3 将采用image.gif并将宽度加倍并将高度加倍。我已经编写了四倍图像代码:

import sys
from cImage import *

def main():
    oldImage = FileImage(sys.argv[1])
    width = oldImage.getWidth()
    height = oldImage.getHeight()
    myWin = ImageWin("Old Image", width, height)
    myNewWin = ImageWin("Quadrupled Image", width*4, height*4)
    newImage = EmptyImage(width*4, height*4)

    for r in range(width):
        for c in range(height):
            pixel = oldImage.getPixel(r, c)
            newImage.setPixel(4*r, 4*c, pixel)
            newImage.setPixel(4*r, 4*c+1, pixel)
            newImage.setPixel(4*r, 4*c+2, pixel)
            newImage.setPixel(4*r, 4*c+3, pixel)
            newImage.setPixel(4*r+1, 4*c, pixel)
            newImage.setPixel(4*r+1, 4*c+1, pixel)
            newImage.setPixel(4*r+1, 4*c+2, pixel)
            newImage.setPixel(4*r+1, 4*c+3, pixel)
            newImage.setPixel(4*r+2, 4*c, pixel)
            newImage.setPixel(4*r+2, 4*c+1, pixel)
            newImage.setPixel(4*r+2, 4*c+2, pixel)
            newImage.setPixel(4*r+2, 4*c+3, pixel)
            newImage.setPixel(4*r+3, 4*c, pixel)
            newImage.setPixel(4*r+3, 4*c+1, pixel)
            newImage.setPixel(4*r+3, 4*c+2, pixel)
            newImage.setPixel(4*r+3, 4*c+3, pixel)
    oldImage.draw(myWin)
    newImage.draw(myNewWin)
    myWin.exitOnClick()
    myNewWin.exitOnClick()

main()

但我无法弄清楚如何编辑我的代码,以便根据要求进行扩展。我觉得我应该能够实现for循环,但是我很难让事情发挥作用。

任何帮助将不胜感激! 编辑:

我正在使用以下修改后的代码:

from cImage import *
import sys

def main():
    oldImage = FileImage(sys.argv[1])
    oldWidth = oldImage.getWidth()
    oldHeight = oldImage.getHeight()

    widthScalar = int(sys.argv[2])
    heightScalar = int(sys.argv[3])

    newWidth = oldWidth * widthScalar
    newHeight = oldHeight * heightScalar

    myWin = ImageWin("Old Image", oldWidth, oldHeight)
    myNewWin = ImageWin("Scaled Image", newWidth, newHeight)
    newImage = EmptyImage(newWidth, newHeight)

    for r in range(oldHeight*heightScalar):
        for c in range(oldWidth*widthScalar):
            pixel = oldImage.getPixel(r // heightScalar, c // widthScalar)
            newImage.setPixel(r, c, pixel)

    oldImage.draw(myWin)
    newImage.draw(myNewWin)
    myWin.exitOnClick()
    myNewWin.exitOnClick()

main()

我也尝试过使用更复杂的方法:

for r in range(oldHeight):
        for c in range(oldWidth):
            pixel = oldImage.getPixel(r,c)
            for i in range(heightScalar):
                for j in range(widthScalar):
                    myNewImage.setPixel((heightScalar*r)+i, (widthScalar*c)+j, pixel)

我已经使用相同的标量(即3 x 3)对其进行了测试,并且它与正方形图像一起正常工作,但是当我尝试更改其中一个时,我收到错误:

  

ValueError:像素索引超出范围。

当我尝试使用非方形图像时,我得到了我的坐标超出范围的错误。

我有点不知所措......感谢你们所有的帮助! ---------------------------------------------- 我已经离开并测试了我的 quadruple.py resize.py ,并且使用了正方形图像,但是当我放入一个无方形图像时,我得到以下内容:

  

pixel = oldImage.getPixel(r,c)

     

文件" /Users/jakebenedict/CPS/Lab6/cImage.py",第313行,getTkPixel

     

p = [int(j)for j in self.im.get(x,y).split()]

     

文件" /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/ init .py",第3260行,in get

     

返回self.tk.call(self.name,' get',x,y)

     

_tkinter.TclError:pyimage1 get:坐标超出范围

不确定为什么说......

2 个答案:

答案 0 :(得分:0)

  

我觉得我应该能够实现for循环

你走在正确的轨道上。但要这样做,你实际上需要两个 for循环,嵌套。*

for yoffset in range(yscale):
    for xoffset in range(xscale):
        newImage.setPixel(yscale*r + yoffset, xscale*c + xoffset, pixel)

为什么?

嗯,首先,对于每一行,你有4行代码,如下所示:

newImage.setPixel(4*r, 4*c, pixel)
newImage.setPixel(4*r, 4*c+1, pixel)
newImage.setPixel(4*r, 4*c+2, pixel)
newImage.setPixel(4*r, 4*c+3, pixel)

因此,要将其抽象为循环,您希望4*c+n成为n从0到3的循环,如下所示:

for n in range(4):
    newImage.setPixel(4*r, 4*c+n, pixel)

现在,您可以将4替换为xscale,然后就完成了。现在只需对行重复相同的技巧(并给n一个更好的名称,这样你就可以保持行和列的偏移直接)并且你有上面的代码。


但是,如果你改变你的算法,可能有一种更简单的方法来看待它。而不是迭代原始像素,并找出每个像素映射到的16个新像素,为什么不迭代新像素,并找出每个像素(非唯一)映射到的1个旧像素?

for r in range(height*yscale):
    for c in range(width*xscale):
        pixel = oldImage.getPixel(r // yscale, c // xscale)
        newImage.setPixel(r, c, pixel)

除了更简单之外,这还有另一个好处:您可以允许用户指定浮点数值,并且循环不会发生任何变化。


*你不真的需要两个循环;你总是可以在笛卡尔积上写一个循环,比如for (yoffset, xoffset) in itertools.product(range(yscale), range(xscale)):。但这真的只是以更复杂的方式说同样的事情。肯定有product有用的情况,但这不是其中之一。

答案 1 :(得分:0)

我已经弄清楚了。这是rc的问题。 r必须在oldWidth范围内,且c必须在oldHeight范围内:

from cImage import *
import sys

def main():
    oldImage = FileImage(sys.argv[1])
    oldWidth = oldImage.getWidth()
    oldHeight = oldImage.getHeight()

    widthScalar = int(sys.argv[2])
    heightScalar = int(sys.argv[3])

    newWidth = oldWidth * widthScalar
    newHeight = oldHeight * heightScalar

    myWin = ImageWin("Old Image", oldWidth, oldHeight)
    myNewWin = ImageWin("Scaled Image", newWidth, newHeight)
    newImage = EmptyImage(newWidth, newHeight)

    for r in range(oldWidth):
        for c in range(oldHeight):
            pixel = oldImage.getPixel(r, c)
            for i in range (widthScalar):
                for j in range(heightScalar):
                    newImage.setPixel((widthScalar*r)+i, (heightScalar*c)+j, pixel)

    oldImage.draw(myWin)
    newImage.draw(myNewWin)
    myWin.exitOnClick()
    myNewWin.exitOnClick()

main()