|
22 | 22 | "from random import choice, randint, uniform\n", |
23 | 23 | "from math import pi\n", |
24 | 24 | "\n", |
25 | | - "from PIL import Image\n", |
| 25 | + "from PIL import Image as PILImage\n", |
26 | 26 | "\n", |
27 | 27 | "import numpy as np\n", |
28 | 28 | "\n", |
29 | | - "from ipycanvas import MultiCanvas, hold_canvas" |
| 29 | + "from ipywidgets import Image\n", |
| 30 | + "\n", |
| 31 | + "from ipycanvas import Canvas, hold_canvas" |
| 32 | + ] |
| 33 | + }, |
| 34 | + { |
| 35 | + "cell_type": "markdown", |
| 36 | + "metadata": {}, |
| 37 | + "source": [ |
| 38 | + "## Drawing a sprite from an ``Image`` widget" |
30 | 39 | ] |
31 | 40 | }, |
32 | 41 | { |
|
35 | 44 | "metadata": {}, |
36 | 45 | "outputs": [], |
37 | 46 | "source": [ |
38 | | - "def load_image(path):\n", |
39 | | - " \"\"\"Load an image into a NumPy array.\"\"\"\n", |
40 | | - " return np.array(Image.open(path))" |
| 47 | + "sprite1 = Image.from_file('sprites/smoke_texture0.png')\n", |
| 48 | + "sprite2 = Image.from_file('sprites/smoke_texture1.png')\n", |
| 49 | + "\n", |
| 50 | + "canvas1 = Canvas(size=(300, 300))\n", |
| 51 | + "canvas1.fill_style = '#a9cafc'\n", |
| 52 | + "canvas1.fill_rect(0, 0, 300, 300)\n", |
| 53 | + "canvas1.draw_image(sprite1, 50, 50)\n", |
| 54 | + "\n", |
| 55 | + "canvas1" |
41 | 56 | ] |
42 | 57 | }, |
43 | 58 | { |
|
46 | 61 | "metadata": {}, |
47 | 62 | "outputs": [], |
48 | 63 | "source": [ |
49 | | - "# Loading sprites as NumPy arrays\n", |
50 | | - "sprites_data = [load_image('sprites/smoke_texture{}.png'.format(i)) for i in range(3)]" |
| 64 | + "canvas1.draw_image(sprite2, 100, 100)" |
| 65 | + ] |
| 66 | + }, |
| 67 | + { |
| 68 | + "cell_type": "markdown", |
| 69 | + "metadata": {}, |
| 70 | + "source": [ |
| 71 | + "## Drawing from another ``Canvas``" |
51 | 72 | ] |
52 | 73 | }, |
53 | 74 | { |
|
56 | 77 | "metadata": {}, |
57 | 78 | "outputs": [], |
58 | 79 | "source": [ |
59 | | - "sprites_data[0].shape" |
| 80 | + "canvas2 = Canvas(size=(600, 300))\n", |
| 81 | + "canvas2.draw_image(canvas1, 0, 0)\n", |
| 82 | + "\n", |
| 83 | + "canvas2" |
60 | 84 | ] |
61 | 85 | }, |
62 | 86 | { |
|
65 | 89 | "metadata": {}, |
66 | 90 | "outputs": [], |
67 | 91 | "source": [ |
68 | | - "m = MultiCanvas(n_canvases=2, size=(800, 600))\n", |
69 | | - "m[0].fill_style = '#a9cafc'\n", |
70 | | - "m[0].fill_rect(0, 0, m.size[0], m.size[1])\n", |
71 | | - "\n", |
72 | | - "m" |
| 92 | + "canvas2.draw_image(canvas1, 300, 0)" |
| 93 | + ] |
| 94 | + }, |
| 95 | + { |
| 96 | + "cell_type": "markdown", |
| 97 | + "metadata": {}, |
| 98 | + "source": [ |
| 99 | + "## Drawing from a NumPy array" |
| 100 | + ] |
| 101 | + }, |
| 102 | + { |
| 103 | + "cell_type": "code", |
| 104 | + "execution_count": null, |
| 105 | + "metadata": {}, |
| 106 | + "outputs": [], |
| 107 | + "source": [ |
| 108 | + "sprite3 = np.array(PILImage.open('sprites/smoke_texture2.png'))" |
73 | 109 | ] |
74 | 110 | }, |
75 | 111 | { |
|
78 | 114 | "metadata": {}, |
79 | 115 | "outputs": [], |
80 | 116 | "source": [ |
81 | | - "with hold_canvas(m[1]):\n", |
82 | | - " for _ in range(200):\n", |
83 | | - " m[1].save()\n", |
| 117 | + "canvas2.put_image_data(sprite3, 250, 150)" |
| 118 | + ] |
| 119 | + }, |
| 120 | + { |
| 121 | + "cell_type": "markdown", |
| 122 | + "metadata": {}, |
| 123 | + "source": [ |
| 124 | + "## Drawing thousands of sprites, the more optimized solution is to first \"cache\" your images in other ``Canvas`` instances" |
| 125 | + ] |
| 126 | + }, |
| 127 | + { |
| 128 | + "cell_type": "code", |
| 129 | + "execution_count": null, |
| 130 | + "metadata": {}, |
| 131 | + "outputs": [], |
| 132 | + "source": [ |
| 133 | + "# The fastest solution is drawing from another canvas\n", |
| 134 | + "canvas_sprite1 = Canvas(size=(100, 100))\n", |
| 135 | + "canvas_sprite1.draw_image(sprite1, 0, 0)\n", |
| 136 | + "canvas_sprite1" |
| 137 | + ] |
| 138 | + }, |
| 139 | + { |
| 140 | + "cell_type": "code", |
| 141 | + "execution_count": null, |
| 142 | + "metadata": {}, |
| 143 | + "outputs": [], |
| 144 | + "source": [ |
| 145 | + "canvas_sprite2 = Canvas(size=(100, 100))\n", |
| 146 | + "canvas_sprite2.draw_image(sprite2, 0, 0)\n", |
| 147 | + "canvas_sprite2" |
| 148 | + ] |
| 149 | + }, |
| 150 | + { |
| 151 | + "cell_type": "code", |
| 152 | + "execution_count": null, |
| 153 | + "metadata": {}, |
| 154 | + "outputs": [], |
| 155 | + "source": [ |
| 156 | + "canvas_sprite3 = Canvas(size=(100, 100))\n", |
| 157 | + "canvas_sprite3.draw_image(Image.from_file('sprites/smoke_texture2.png'), 0, 0)\n", |
| 158 | + "canvas_sprite3" |
| 159 | + ] |
| 160 | + }, |
| 161 | + { |
| 162 | + "cell_type": "code", |
| 163 | + "execution_count": null, |
| 164 | + "metadata": {}, |
| 165 | + "outputs": [], |
| 166 | + "source": [ |
| 167 | + "canvas3 = Canvas(size=(800, 600))\n", |
| 168 | + "\n", |
| 169 | + "sprites = [canvas_sprite1, canvas_sprite2, canvas_sprite3]\n", |
| 170 | + "\n", |
| 171 | + "with hold_canvas(canvas3):\n", |
| 172 | + " for _ in range(2_000):\n", |
| 173 | + " canvas3.save()\n", |
84 | 174 | "\n", |
85 | 175 | " # Choose a random sprite texture\n", |
86 | | - " sprite = sprites_data[choice(range(3))]\n", |
87 | | - " \n", |
| 176 | + " sprite = sprites[choice(range(3))]\n", |
| 177 | + "\n", |
88 | 178 | " # Choose a random sprite position\n", |
89 | | - " pos_x = randint(0, m.size[0] - sprite.shape[1])\n", |
90 | | - " pos_y = randint(0, m.size[1] - sprite.shape[0])\n", |
| 179 | + " pos_x = randint(0, canvas3.size[0] - 50)\n", |
| 180 | + " pos_y = randint(0, canvas3.size[1] - 50)\n", |
91 | 181 | "\n", |
92 | 182 | " # Choose a random rotation angle (but first set the rotation center with `translate`)\n", |
93 | | - " t_x = pos_x + 0.5 * sprite.shape[1]\n", |
94 | | - " t_y = pos_y + 0.5 * sprite.shape[0]\n", |
95 | | - " m[1].translate(t_x, t_y)\n", |
96 | | - " m[1].rotate(uniform(0., pi))\n", |
| 183 | + " canvas3.translate(pos_x, pos_y)\n", |
| 184 | + " canvas3.rotate(uniform(0., pi))\n", |
97 | 185 | "\n", |
98 | 186 | " # Choose a random sprite size\n", |
99 | 187 | " scale = uniform(0.2, 1.)\n", |
100 | | - " m[1].scale(scale)\n", |
| 188 | + " canvas3.scale(scale)\n", |
101 | 189 | "\n", |
102 | 190 | " # Restore the canvas center\n", |
103 | | - " m[1].translate(- t_x, - t_y)\n", |
| 191 | + " canvas3.translate(- pos_x, - pos_y)\n", |
104 | 192 | "\n", |
105 | 193 | " # Draw the sprite\n", |
106 | | - " m[1].put_image_data(sprite, pos_x, pos_y)\n", |
| 194 | + " canvas3.draw_image(sprite, pos_x, pos_y)\n", |
| 195 | + "\n", |
| 196 | + " canvas3.restore()\n", |
107 | 197 | "\n", |
108 | | - " m[1].restore()" |
| 198 | + "canvas3" |
109 | 199 | ] |
110 | 200 | } |
111 | 201 | ], |
|
125 | 215 | "name": "python", |
126 | 216 | "nbconvert_exporter": "python", |
127 | 217 | "pygments_lexer": "ipython3", |
128 | | - "version": "3.7.3" |
| 218 | + "version": "3.7.4" |
129 | 219 | } |
130 | 220 | }, |
131 | 221 | "nbformat": 4, |
|
0 commit comments