##// END OF EJS Templates
implement GIF support without registering a new formatter...
Min RK -
Show More
@@ -23,7 +23,7 b' from IPython.utils.py3compat import cast_unicode'
23 23 from IPython.testing.skipdoctest import skip_doctest
24 24
25 25 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
26 'display_svg', 'display_png', 'display_jpeg', 'display_gif', 'display_latex', 'display_json',
26 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
27 27 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
28 28 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'GeoJSON', 'Javascript',
29 29 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
@@ -86,18 +86,7 b' def publish_display_data(data, metadata=None, source=None, *, transient=None, **'
86 86 See the ``display_data`` message in the messaging documentation for
87 87 more details about this message type.
88 88
89 The following MIME types are currently implemented:
90
91 * text/plain
92 * text/html
93 * text/markdown
94 * text/latex
95 * application/json
96 * application/javascript
97 * image/png
98 * image/jpeg
99 * image/gif
100 * image/svg+xml
89 Keys of data and metadata can be any mime-type.
101 90
102 91 Parameters
103 92 ----------
@@ -257,11 +246,11 b' def display(*objs, include=None, exclude=None, metadata=None, transient=None, di'
257 246 - `_repr_json_`: return a JSONable dict
258 247 - `_repr_jpeg_`: return raw JPEG data
259 248 - `_repr_png_`: return raw PNG data
260 - `_repr_gif_`: return raw GIF data
261 249 - `_repr_svg_`: return raw SVG data as a string
262 250 - `_repr_latex_`: return LaTeX commands in a string surrounded by "$".
263 251 - `_repr_mimebundle_`: return a full mimebundle containing the mapping
264 from all mimetypes to data
252 from all mimetypes to data.
253 Use this for any mime-type not listed above.
265 254
266 255 When you are directly writing your own classes, you can adapt them for
267 256 display in IPython by following the above approach. But in practice, you
@@ -496,22 +485,6 b' def display_jpeg(*objs, **kwargs):'
496 485 Metadata to be associated with the specific mimetype output.
497 486 """
498 487 _display_mimetype('image/jpeg', objs, **kwargs)
499
500 def display_gif(*objs, **kwargs):
501 """Display the GIF representation of an object.
502
503 Parameters
504 ----------
505 objs : tuple of objects
506 The Python objects to display, or if raw=True raw gif data to
507 display.
508 raw : bool
509 Are the data objects raw data or Python objects that need to be
510 formatted before display? [default: False]
511 metadata : dict (optional)
512 Metadata to be associated with the specific mimetype output.
513 """
514 _display_mimetype('image/gif', objs, **kwargs)
515 488
516 489
517 490 def display_latex(*objs, **kwargs):
@@ -984,11 +957,12 b' def _jpegxy(data):'
984 957 idx += 2
985 958
986 959 return struct.unpack('>HH', data[iSOF+5:iSOF+9])
987
960
988 961 def _gifxy(data):
989 962 """read the (width, height) from a GIF header"""
990 963 return struct.unpack('<HH', data[6:10])
991 964
965
992 966 class Image(DisplayObject):
993 967
994 968 _read_flags = 'rb'
@@ -996,6 +970,11 b' class Image(DisplayObject):'
996 970 _FMT_PNG = u'png'
997 971 _FMT_GIF = u'gif'
998 972 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
973 _MIMETYPES = {
974 _FMT_PNG: 'image/png',
975 _FMT_JPEG: 'image/jpeg',
976 _FMT_GIF: 'image/gif',
977 }
999 978
1000 979 def __init__(self, data=None, url=None, filename=None, format=None,
1001 980 embed=None, width=None, height=None, retina=False,
@@ -1097,12 +1076,15 b' class Image(DisplayObject):'
1097 1076 if format.lower() == 'jpg':
1098 1077 # jpg->jpeg
1099 1078 format = self._FMT_JPEG
1100
1079
1101 1080 self.format = format.lower()
1102 1081 self.embed = embed if embed is not None else (url is None)
1103 1082
1104 1083 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
1105 1084 raise ValueError("Cannot embed the '%s' image format" % (self.format))
1085 if self.embed:
1086 self._mimetype = self._MIMETYPES.get(self.format)
1087
1106 1088 self.width = width
1107 1089 self.height = height
1108 1090 self.retina = retina
@@ -1119,6 +1101,7 b' class Image(DisplayObject):'
1119 1101 if retina:
1120 1102 self._retina_shape()
1121 1103
1104
1122 1105 def _retina_shape(self):
1123 1106 """load pixel-doubled width and height from image data"""
1124 1107 if not self.embed:
@@ -1158,7 +1141,21 b' class Image(DisplayObject):'
1158 1141 klass=klass,
1159 1142 )
1160 1143
1161 def _data_and_metadata(self):
1144 def _repr_mimebundle_(self, include=None, exclude=None):
1145 """Return the image as a mimebundle
1146
1147 Any new mimetype support should be implemented here.
1148 """
1149 if self.embed:
1150 mimetype = self._mimetype
1151 data, metadata = self._data_and_metadata(always_both=True)
1152 if metadata:
1153 metadata = {mimetype: metadata}
1154 return {mimetype: data}, metadata
1155 else:
1156 return {'text/html': self._repr_html_()}
1157
1158 def _data_and_metadata(self, always_both=False):
1162 1159 """shortcut for returning metadata with shape information, if defined"""
1163 1160 md = {}
1164 1161 if self.metadata:
@@ -1169,7 +1166,7 b' class Image(DisplayObject):'
1169 1166 md['height'] = self.height
1170 1167 if self.unconfined:
1171 1168 md['unconfined'] = self.unconfined
1172 if md:
1169 if md or always_both:
1173 1170 return self.data, md
1174 1171 else:
1175 1172 return self.data
@@ -1179,16 +1176,13 b' class Image(DisplayObject):'
1179 1176 return self._data_and_metadata()
1180 1177
1181 1178 def _repr_jpeg_(self):
1182 if self.embed and (self.format == self._FMT_JPEG or self.format == u'jpg'):
1183 return self._data_and_metadata()
1184
1185 def _repr_gif_(self):
1186 if self.embed and self.format == self._FMT_GIF:
1179 if self.embed and self.format == self._FMT_JPEG:
1187 1180 return self._data_and_metadata()
1188 1181
1189 1182 def _find_ext(self, s):
1190 1183 return s.split('.')[-1].lower()
1191 1184
1185
1192 1186 class Video(DisplayObject):
1193 1187
1194 1188 def __init__(self, data=None, url=None, filename=None, embed=False, mimetype=None):
@@ -1287,15 +1281,6 b' class Video(DisplayObject):'
1287 1281 # TODO
1288 1282 pass
1289 1283
1290 def _repr_png_(self):
1291 # TODO
1292 pass
1293 def _repr_jpeg_(self):
1294 # TODO
1295 pass
1296 def _repr_gif_(self):
1297 # TODO
1298 pass
1299 1284
1300 1285 def clear_output(wait=False):
1301 1286 """Clear the output of the current cell receiving output.
@@ -74,7 +74,6 b' class DisplayFormatter(Configurable):'
74 74 MarkdownFormatter,
75 75 SVGFormatter,
76 76 PNGFormatter,
77 GIFFormatter,
78 77 PDFFormatter,
79 78 JPEGFormatter,
80 79 LatexFormatter,
@@ -780,24 +779,6 b' class JPEGFormatter(BaseFormatter):'
780 779 _return_type = (bytes, str)
781 780
782 781
783 class GIFFormatter(BaseFormatter):
784 """A PNG formatter.
785
786 To define the callables that compute the GIF representation of your
787 objects, define a :meth:`_repr_gif_` method or use the :meth:`for_type`
788 or :meth:`for_type_by_name` methods to register functions that handle
789 this.
790
791 The return value of this formatter should be raw GIF data, *not*
792 base64 encoded.
793 """
794 format_type = Unicode('image/gif')
795
796 print_method = ObjectName('_repr_gif_')
797
798 _return_type = (bytes, str)
799
800
801 782 class LatexFormatter(BaseFormatter):
802 783 """A LaTeX formatter.
803 784
@@ -977,10 +958,7 b' class MimeBundleFormatter(BaseFormatter):'
977 958 method = get_real_method(obj, self.print_method)
978 959
979 960 if method is not None:
980 d = {}
981 d['include'] = include
982 d['exclude'] = exclude
983 return method(**d)
961 return method(include=include, exclude=exclude)
984 962 return None
985 963 else:
986 964 return None
@@ -992,7 +970,6 b' FormatterABC.register(HTMLFormatter)'
992 970 FormatterABC.register(MarkdownFormatter)
993 971 FormatterABC.register(SVGFormatter)
994 972 FormatterABC.register(PNGFormatter)
995 FormatterABC.register(GIFFormatter)
996 973 FormatterABC.register(PDFFormatter)
997 974 FormatterABC.register(JPEGFormatter)
998 975 FormatterABC.register(LatexFormatter)
@@ -1007,19 +984,6 b' def format_display_data(obj, include=None, exclude=None):'
1007 984
1008 985 By default all format types will be computed.
1009 986
1010 The following MIME types are currently implemented:
1011
1012 * text/plain
1013 * text/html
1014 * text/markdown
1015 * text/latex
1016 * application/json
1017 * application/javascript
1018 * application/pdf
1019 * image/png
1020 * image/jpeg
1021 * image/svg+xml
1022
1023 987 Parameters
1024 988 ----------
1025 989 obj : object
@@ -32,6 +32,15 b' def test_image_size():'
32 32 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
33 33
34 34
35 def test_image_mimes():
36 fmt = get_ipython().display_formatter.format
37 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
38 mime = display.Image._MIMETYPES[format]
39 img = display.Image(b'garbage', format=format)
40 data, metadata = fmt(img)
41 nt.assert_equal(sorted(data), sorted([mime, 'text/plain']))
42
43
35 44 def test_geojson():
36 45
37 46 gj = display.GeoJSON(data={
@@ -361,3 +370,4 b' def test_display_handle():'
361 370 },
362 371 'update': True,
363 372 })
373
@@ -30,7 +30,10 b' class RichOutput(object):'
30 30 return data, self.metadata[mime]
31 31 else:
32 32 return data
33
33
34 def _repr_mimebundle_(self, include=None, exclude=None):
35 return self.data, self.metadata
36
34 37 def _repr_html_(self):
35 38 return self._repr_mime_("text/html")
36 39
@@ -48,9 +51,6 b' class RichOutput(object):'
48 51
49 52 def _repr_jpeg_(self):
50 53 return self._repr_mime_("image/jpeg")
51
52 def _repr_gif_(self):
53 return self._repr_mime_("image/gif")
54 54
55 55 def _repr_svg_(self):
56 56 return self._repr_mime_("image/svg+xml")
General Comments 0
You need to be logged in to leave comments. Login now