Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

# -*- encoding: utf-8 -*- 

""" 

Sage Wrapper for Bitmap Images 

 

Some computations in Sage return bitmap images, for example matrices 

can be turned into bitmaps directly. Note that this is different from 

all plotting functionality, the latter can equally produce vector 

graphics. This module is about bitmaps only, and a shallow wrapper 

around ``PIL.Image``. The only difference is that :class:`Image` 

is displayed as graphics by the Sage if the UI can. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('RGB', (256, 256), 'white') 

sage: pixels = img.pixels() 

sage: for x in range(img.width()): 

....: for y in range(img.height()): 

....: pixels[x, y] = (x, y, 100) 

sage: img 

256x256px 24-bit RGB image 

sage: type(img) 

<class 'sage.repl.image.Image'> 

""" 

 

#***************************************************************************** 

# Copyright (C) 2015 Volker Braun <vbraun.name@gmail.com> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# as published by the Free Software Foundation; either version 2 of 

# the License, or (at your option) any later version. 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

 

 

import PIL.Image 

from sage.structure.sage_object import SageObject 

 

 

class Image(SageObject): 

 

def __init__(self, mode, size, color='white'): 

""" 

Creates a new image with the given mode and size. 

 

INPUT: 

 

- ``mode`` -- string. The mode to use for the new image. Valid 

options are: 

 

* ``'1'`` (1-bit pixels, black and white, stored with 

one pixel per byte) 

 

* ``'L'`` (8-bit pixels, black and white) 

 

* ``'P'`` (8-bit pixels, mapped to any other mode using 

a color palette) 

 

* ``'RGB'`` (3x8-bit pixels, true color) 

 

* ``'RGBA'`` (4x8-bit pixels, true color with 

transparency mask) 

 

* ``'CMYK'`` (4x8-bit pixels, color separation) 

 

* ``'YCbCr'`` (3x8-bit pixels, color video format) 

 

* ``'LAB'`` (3x8-bit pixels, the L*a*b color space) 

 

* ``'HSV'`` (3x8-bit pixels, Hue, Saturation, Value 

color space) 

 

* ``'I'`` (32-bit signed integer pixels) 

 

* ``'F'`` (32-bit floating point pixels) 

 

- ``size`` -- 2-tuple, containing (width, height) in pixels. 

 

- ``color`` -- string or tuple of numeric. What colour to use 

for the image. Default is black. If given, this should be a 

a tuple with one value per band. When creating RGB images, 

you can also use colour strings as supported by the 

ImageColor module. If the colour is None, the image is not 

initialised. 

 

OUTPUT: 

 

A new :class:`Image` object. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: Image('P', (16, 16), (13,)) 

16x16px 8-bit Color image 

""" 

self._pil = PIL.Image.new(mode, size, color) 

 

@property 

def pil(self): 

""" 

Access the wrapped PIL(low) Image 

 

OUTPUT: 

 

The underlying ``PIL.Image.Image object``. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('RGB', (16, 16), 'white') 

sage: img.pil 

<PIL.Image.Image image mode=RGB size=16x16 at 0x...> 

""" 

return self._pil 

 

def pixels(self): 

""" 

Return the pixel map 

 

OUTPUT: 

 

The PIL PixelAccess object that allows you to get/set the 

pixel data. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('RGB', (16, 16), 'white') 

sage: img.pixels() 

<PixelAccess object at 0x...> 

""" 

return self._pil.load() 

 

def _repr_(self): 

""" 

Return string representation. 

 

OUTPUT: 

 

String. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: Image('RGB', (16, 16), 'white') # indirect doctest 

16x16px 24-bit RGB image 

""" 

modestr = { 

'1': '{0}x{1}px BW image', 

'L': '{0}x{1}px 8-bit BW image', 

'P': '{0}x{1}px 8-bit Color image', 

'RGB': '{0}x{1}px 24-bit RGB image', 

'RGBA': '{0}x{1}px 32-bit RGBA image', 

'CMYK': '{0}x{1}px 24-bit CMYK image', 

'YCbCr': '{0}x{1}px 24-bit YCbCr mage', 

'LAB': '{0}x{1}px 24-bit LAB image', 

'HSV': '{0}x{1}px 24-bit HSV image', 

'I': '{0}x{1}px 32-bit signed integer image', 

'F': '{0}x{1}px 32-bit float image', 

} 

try: 

mode = modestr[self.pil.mode] 

except AttributeError: 

mode = 'Unknown mode' 

width, height = self.pil.size 

return mode.format(width, height) 

 

def mode(self): 

""" 

Return the color mode 

 

OUTPUT: 

 

String. As given when constructing the image. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('YCbCr', (16, 16), 'white') 

sage: img.mode() 

'YCbCr' 

""" 

return self.pil.mode 

 

def width(self): 

""" 

Return the horizontal dimension in pixels 

 

OUTPUT: 

 

Integer. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('1', (12, 34), 'white') 

sage: img.width() 

12 

sage: img.height() 

34 

""" 

return self.pil.size[0] 

 

def height(self): 

""" 

Return the vertical dimension in pixels 

 

OUTPUT: 

 

Integer. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('1', (12, 34), 'white') 

sage: img.width() 

12 

sage: img.height() 

34 

""" 

return self.pil.size[1] 

 

def save(self, filename): 

r""" 

Save the bitmap image 

 

INPUT: 

 

- ``filename`` -- string. The filename to save as. The given 

extension automatically determines the image file type. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('P', (12, 34), (13,)) 

sage: filename = tmp_filename(ext='.png') 

sage: img.save(filename) 

sage: open(filename).read().startswith('\x89PNG') 

True 

""" 

self.pil.save(filename) 

 

def show(self): 

r""" 

Show this image immediately. 

 

This method attempts to display the graphics immediately, 

without waiting for the currently running code (if any) to 

return to the command line. Be careful, calling it from within 

a loop will potentially launch a large number of external 

viewer programs. 

 

OUTPUT: 

 

This method does not return anything. Use :meth:`save` if you 

want to save the figure as an image. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('1', (12, 34), 'white') 

sage: img.show() 

""" 

from sage.repl.rich_output import get_display_manager 

dm = get_display_manager() 

dm.display_immediately(self) 

 

def _rich_repr_(self, display_manager, **kwds): 

""" 

Rich Output Magic Method 

 

See :mod:`sage.repl.rich_output` for details. 

 

EXAMPLES:: 

 

sage: from sage.repl.image import Image 

sage: img = Image('1', (16, 16), 'white') 

sage: from sage.repl.rich_output import get_display_manager 

sage: dm = get_display_manager() 

sage: img._rich_repr_(dm) 

OutputImagePng container 

 

sage: img = Image('F', (16, 16), 'white') # not supported in PNG 

sage: img._rich_repr_(dm) 

OutputImageGif container 

""" 

if display_manager.preferences.graphics == 'disable': 

return 

types = display_manager.types 

preferred = ( 

('PNG', types.OutputImagePng), 

('JPEG', types.OutputImageJpg), 

('GIF', types.OutputImageGif), 

) 

from six import StringIO 

from sage.repl.rich_output.buffer import OutputBuffer 

for format, output_container in preferred: 

if output_container in display_manager.supported_output(): 

stream = StringIO() 

try: 

self.pil.save(stream, format=format) 

except IOError: 

# not all formats support all modes, e.g. no alpha support in gif 

continue 

buf = OutputBuffer(stream.getvalue()) 

return output_container(buf)