Welcome, guest | Sign In | My Account | Store | Cart

Create a Sierpinski carpet using MuPDF's graphics library fitz (binding PyMuPDF) at high speed.

Python, 64 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# -*- coding: utf-8 -*-
"""
@created: 2016-01-15 08:40:00

@author: Jorj X. McKie

Create Sierpinki's carpet using PyMuPDF.

Dependencies:
PyMuPDF

License:
 GNU GPL 3.x
 
On a machine with 4.0 GHz, run time should be around 0.5 sec for d = 729 (= 3**6).
For each additional power of 3, runtime grows by a factor of 8 (not 9 as you may expect), i.e. about 4 seconds for d = 3**7, etc. in our case.
"""
import fitz, time
from __future__ import print_function

def punch(pm, x00, y00, x03, y03):
    step = x03 - x00                    
    if step < 3:                       # stop recursion if square < 3 x 3 
        return
    step = step // 3
    # define short names for square corner coordinates
    x01 = x00 + step
    x02 = x01 + step
    y01 = y00 + step
    y02 = y01 + step
    # we clear the middle square and recurse for the other 8
    ir = fitz.IRect(x01, y01, x02, y02)  # rectangle of middle square
    punch(pm, x00, y00, x01, y01)      # top left
    punch(pm, x01, y00, x02, y01)      # top middle
    punch(pm, x02, y00, x03, y01)      # top right
    punch(pm, x00, y01, x01, y02)      # middle left
    pm.clearWith(0, ir)                # clear center to black
    punch(pm, x02, y01, x03, y02)      # middle right
    punch(pm, x00, y02, x01, y02)      # bottom left
    punch(pm, x01, y02, x02, y03)      # bottom middle
    punch(pm, x02, y02, x03, y03)      # bottom right
    return

#==============================================================================
# main program
#==============================================================================
d = 3**6                               # = 729, picture dimension in pixels
# create a quadratic pixmap with origin (0,0), where width = height = d should
# be a power of 3
t0 = time.clock()
cs = fitz.Colorspace(fitz.CS_RGB)
ir = fitz.IRect(0, 0, d, d)
pm = fitz.Pixmap(cs, ir)
# fill image area with "white" and then optionally tint and gamma it
pm.clearWith(255)
#pm.tintWith(10, 20, 100)            # tint it with some sort of blue
#pm.gammaWith(0.5)                   # lighten it up
# now punch holes into it, down to 1 pixel granularity
punch(pm, 0, 0, d, d)
t1 = time.clock()
pm.writePNG("sierpinski.png")
t2 = time.clock()
print("%f sec to create img" % (t1-t0))
print("%f sec to save img" % (t2-t1))