图片处理

有时我们需要反复绘制一个复杂的图形。如果每次我们都从头开始绘制,显然费时费力。更好的解决方法是先把它单独绘制到一个图片(Image)上,然后重复使用该图片进行绘制。

创建和绘制图片

使用create_image()函数来创建一个新的图片对象。

有两种方法来在图片上绘制图形:

  1. 面向对象方式:使用图片对象的成员方法。create_image()创建的是一个图片对象。我们可以直接使用它的成员方法。
img=create_image(800,600)
img.draw_circle(100,100,50)
  1. 传统方式:使用前面章节中的绘图函数,同时指明在哪个图片上绘制(缺省在绘图窗口中绘制)
img=create_image(400,300)
draw_circle(100,100,50,img)

绘图窗口和绘制目标(target)

在Easy Graphics中,绘图窗口就是一个特殊的图片。

为了减少编写程序的难度,Easy Graphics系统内部包含一个“绘制目标”属性。大多数绘图函数都有一个缺省的”image”或”dst_image”参数,如果未提供该参数,就会在系统的“绘制目标”上绘图。缺省的绘制目标就是绘图窗口。

所以,如果你没有修改过系统的“绘制目标”,在调用绘图函数时也没有指明在哪儿绘制,图形就会被绘制在绘图窗口里。

可以使用set_target()函数来改变系统的“绘图目标”,以及使用get_target()函数来获取当前的绘图目标。

下面的代码使用set_target()函数来将系统的“绘图目标设置”为一个图片, 然后在上面绘图:

注意:使用close_image()函数来关闭用完的图片。
img=create_image(400,300)
set_target(img)
draw_circle(100,100,50)

保存图片

可以使用save_image()函数来将图片保存到文件中。

下面的程序绘制一辆公共汽车,并将其保存到当前文件夹的”bus_screen.png”文件中。

注意,因为:

  1. save_image()缺省保存“绘制目标”图片;
  2. 缺省的“绘制目标”是绘图窗口。

因此我们保存到文件中的是绘图窗口中的内容。

复制图片

我们可以使用draw_image()函数来复制一个图片(或它的一部分)到另一张图片上。

在下面的例子中,我们将:

  1. 创建一个图片对象,保存到变量”img”中。
  2. 将“绘制目标”设为”img”。
  3. 在“绘制目标”(”img”图片)上画一辆公共汽车
  4. 将“绘制目标”设为绘图窗口
  5. 将”img”中的内容复制到绘图窗口的不同位置
from easygraphics import *
import draw_bus

init_graph(750,450)
img=create_image(210,130)
set_target(img) # set target to img
draw_bus.draw_bus()
set_target() # set target back to the graphics window
set_background_color("black")
for i in range(0,9):
    x = i % 3 * 250
    y = i // 3 * 150
    draw_image(x+20,y+10,img)

pause()
img.close()
close_graph()

结果:

../_images/11_copy_buses.png

图片透明和合成

put_image()从源图片复制一个矩形区域到目标图片上。如果你需要复制一个外形轮廓不是矩形的图像,可以先将其画在一个背景完全透明的图片上,然后再复制。

下面的例子中大部分代码和上一个例子相同,除了在画公共汽车之前,先把源图片的背景设成了透明。

from easygraphics import *
import draw_bus

init_graph(750,450)
img=create_image(210,130)
set_background_color(Color.TRANSPARENT,img) # set img's background to transparency
set_target(img) # set target to img
draw_bus.draw_bus()
set_target() # set target back to the graphics window
set_background_color("black")
for i in range(0,9):
    x = i % 3 * 250
    y = i // 3 * 150
    draw_image(x+20,y+10,img)

pause()
img.close()
close_graph()

结果是:

../_images/11_copy_bus_trans.png

复制图片时忽略背景

如果你不喜欢使用透明背景,那么也可以在复制时将参数”with_background”设为False,这样在复制时将不会复制背景。

在下面的例子中,我们没有使用透明背景,而是直接不复制背景。

from easygraphics import *
import draw_bus

init_graph(750,450)
img=create_image(210,130)
set_target(img) # set target to img
draw_bus.draw_bus()
set_target() # set target back to the graphics window
set_background_color("black")
for i in range(0,9):
    x = i % 3 * 250
    y = i // 3 * 150
    draw_image(x+20,y+10,img,with_background=False)

pause()
img.close()
close_graph()
../_images/11_copy_bus_trans.png

带几何变换的图片复制

如果你需要在复制图片的同时对其进行几何变换(如复制一张旋转后的图片),那你应该在复制前先在目标图片上设置变换。

下面的程序进行了旋转复制。请注意save_settings()和restore_settings()函数,它们被用来保存和恢复图片的设置(包括几何变换设置)。

注意:在变换和复制图片前先保存旧的设置,然后在复制完成后恢复原有设置是个非常好的习惯。
from easygraphics import *
import draw_bus

init_graph(750,450)
img=create_image(210,130)
set_target(img) # set target to img
draw_bus.draw_bus()
set_target() # set target back to the graphics window
set_background_color("black")
for i in range(0,9):
    x = i % 3 * 250 + 20
    y = i // 3 * 150 + 10
    save_settings()
    # transforms
    translate(x,y)
    translate(105,65)
    rotate(45)
    translate(-105,-65)

    draw_image(0,0,img,with_background=False)
    restore_settings()
pause()
img.close()
close_graph()
../_images/11_copy_bus_transform.png

入图片文件

我们可以从文件中读入图片。

注意:JPEG格式图片不支持透明。因此如果你需要保存和载入带透明背景的图片,请使用PNG格式。

下面的例子从文件中读入图片,然后显示在绘图窗口中。

from easygraphics import *
init_graph(800, 600)
img = load_image("test.png")
draw_image((get_width() - img.get_width()) // 2,
           (get_height() - img.get_height()) // 2, img)
pause()
img.close()
close_graph()

无窗口(headless)模式

有时我们只需要绘制和保存图片,并不需要在屏幕窗口上显示。为此,Easygraphics提供了无窗口(headless)模式,来完成这类工作。在该模式下,不显示绘图窗口,pause()、get_click()等为动画和交互服务的的函数也无法使用。

下面的程序展示了如何使用init_graph()函数进行无窗口模式。

from easygraphics import *
import draw_bus

init_graph(headless=True)
img=create_image(210,130)
set_target(img)
draw_bus.draw_bus()
save_image("headless_bus.png")
img.close()
close_graph()