PyCairo 中的剪裁和屏蔽
在 PyCairo 教程的這個部分,我們將討論剪裁和屏蔽操作。
剪裁
裁剪 是將繪制限定在某一區域內。這樣做有一些效率的因素,或者為了創建有趣的效果。PyCairo 有一個 clip() 方法用于設置裁剪區域。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis program shows how to perform clipping in PyCairo.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib import cairo import math import randomclass Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()self.load_image()self.init_vars()def init_ui(self):self.darea = Gtk.DrawingArea()self.darea.connect("draw", self.on_draw)self.add(self.darea)GLib.timeout_add(100, self.on_timer)self.set_title("Clipping")self.resize(300, 200)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def load_image(self):self.image = cairo.ImageSurface.create_from_png("beckov.png")def init_vars(self):self.pos_x = 128self.pos_y = 128self.radius = 40self.delta = [3, 3]def on_timer(self):self.pos_x += self.delta[0]self.pos_y += self.delta[1]self.darea.queue_draw()return Truedef on_draw(self, wid, cr):w, h = self.get_size()if (self.pos_x < 0 + self.radius):self.delta[0] = random.randint(5, 9)elif (self.pos_x > w - self.radius):self.delta[0] = -random.randint(5, 9)if (self.pos_y < 0 + self.radius):self.delta[1] = random.randint(5, 9)elif (self.pos_y > h - self.radius):self.delta[1] = -random.randint(5, 9)cr.set_source_surface(self.image, 1, 1)cr.arc(self.pos_x, self.pos_y, self.radius, 0, 2 * math.pi)cr.clip()cr.paint()def main():app = Example()Gtk.main()if __name__ == "__main__":main()在這個例子中,我們將裁剪一幅圖片。一個圓圈在窗口區域移動,并顯示下面的圖片的一部分。這就好像我們通過一個洞看過去一樣。
def load_image(self):self.image = cairo.ImageSurface.create_from_png("beckov.png")這是下面的圖片。每一個定時器周期,我們將看到這幅圖片的一部分。
if (self.pos_x < 0 + self.radius):self.delta[0] = random.randint(5, 9)elif (self.pos_x > w - self.radius):self.delta[0] = -random.randint(5, 9)如果圓圈擊中了窗口的左邊或右邊,則圓圈移動的方向會隨機地改變。對于上邊和下邊也一樣。
cr.arc(self.pos_x, self.pos_y, self.radius, 0, 2 * math.pi)這一行給 Cairo 上下文添加一個圓形的 Path。
cr.clip()clip() 設置裁剪區域。裁剪區域是當前正在使用的 Path。當前的 path 由 arc() 方法調用創建。
cr.paint()paint() 用當前的 source 描繪當前裁剪區域內的部分。
屏蔽
在 source 被應用于 surface 之前,它首先會被過濾。mask 被用作一個過濾器。mask 決定 source 的哪個部分被應用,而哪個部分不會。mask 不透明的部分允許復制 source。透明的部分則不允許復制 source 到 surface。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis program demonstrates masking.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk import cairoclass Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()self.load_image()def init_ui(self):darea = Gtk.DrawingArea()darea.connect("draw", self.on_draw)self.add(darea)self.set_title("Masking")self.resize(310, 100)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def load_image(self):self.ims = cairo.ImageSurface.create_from_png("omen.png")def on_draw(self, wid, cr):cr.mask_surface(self.ims, 0, 0);cr.fill()def main():app = Example()Gtk.main()if __name__ == "__main__":main()在這個例子中,屏蔽決定了哪些地方需要繪制哪些地方不繪制。
cr.mask_surface(self.ims, 0, 0);cr.fill()我們使用一幅圖片作為 mask,這將會把它顯示在窗口中。
Blind down 效果
在這個代碼例子中,我們將 blind down 我們的圖片。這類似于我們使用的遮光窗簾。
#!/usr/bin/python''' ZetCode PyCairo tutorialThis program creates a blind down effect using masking operation.author: Jan Bodnar website: zetcode.com last edited: August 2012 '''import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GLib import cairo import mathclass Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()self.load_image()self.init_vars()def init_ui(self):self.darea = Gtk.DrawingArea()self.darea.connect("draw", self.on_draw)self.add(self.darea)GLib.timeout_add(35, self.on_timer)self.set_title("Blind down")self.resize(325, 250)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def load_image(self):self.image = cairo.ImageSurface.create_from_png("beckov.png")def init_vars(self):self.timer = Trueself.h = 0self.iw = self.image.get_width()self.ih = self.image.get_height()self.ims = cairo.ImageSurface(cairo.FORMAT_ARGB32,self.iw, self.ih)def on_timer(self):if (not self.timer):return Falseself.darea.queue_draw()return Truedef on_draw(self, wid, cr):ic = cairo.Context(self.ims)ic.rectangle(0, 0, self.iw, self.h)ic.fill()self.h += 1if (self.h == self.ih):self.timer = Falsecr.set_source_surface(self.image, 10, 10)cr.mask_surface(self.ims, 10, 10)def main():app = Example()Gtk.main()if __name__ == "__main__":main()blend down 效果背后的想法相當的簡單。圖像有 h 個像素高。我們繪制 0,1, 2… 個 1 像素高的行。每個周期,圖像的部分多出一像素的高度,直到整幅圖片都變得可見為止。
def load_image(self):self.image = cairo.ImageSurface.create_from_png("beckov.png")在 load_image() 方法中,我們由一幅 PNG 圖片創建一個圖片 surface。
def init_vars(self):self.timer = Trueself.h = 0self.iw = self.image.get_width()self.ih = self.image.get_height()self.ims = cairo.ImageSurface(cairo.FORMAT_ARGB32,self.iw, self.ih)在 init_vars() 方法中,我們初始化一些變量。我們初始化 self.timer 和 self.h 變量。我們獲取所加載的圖片的寬度和高度。然后我們創建一個空的圖像 surface。它將會被來自于先前我們所創建的圖像 surface 的像素行所填充。
ic = cairo.Context(self.ims)我們由空的圖像 source 創建一個 cairo 上下文。
ic.rectangle(0, 0, self.iw, self.h)ic.fill()我們向最初為空的圖像中繪制一個矩形。矩形每個周期高出 1px。用這種方式創建的圖像將在后面作為一個 mask。
self.h += 1將要顯示的圖像的高度被加了一個單元。
if (self.h == self.ih):self.timer = False當我們在 GTK 窗口中繪制了整個圖片時,我們停掉定時器方法。
cr.set_source_surface(self.image, 10, 10)cr.mask_surface(self.ims, 10, 10)城堡的圖片被設置為繪制時的 source。mask_surface() 繪制當前的 source,使用 surface 的 alpha 通道作為一個 mask。
Blind down 是一種動畫效果。
本章討論了PyCairo中的裁剪和屏蔽。
原文
Done.
總結
以上是生活随笔為你收集整理的PyCairo 中的剪裁和屏蔽的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Brotli压缩算法的Android封装
- 下一篇: PyCairo 中的透明度