##// END OF EJS Templates
ENH: add webp support to IPython.display.Image and complete identification of JPEG,PNG,GIF,WEBP image types by initial bytes (#14526)...
M Bussonnier -
r28924:d7d58a36 merge
parent child Browse files
Show More
@@ -21,13 +21,35 from IPython.testing.skipdoctest import skip_doctest
21 from . import display_functions
21 from . import display_functions
22
22
23
23
24 __all__ = ['display_pretty', 'display_html', 'display_markdown',
24 __all__ = [
25 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
25 "display_pretty",
26 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
26 "display_html",
27 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
27 "display_markdown",
28 'GeoJSON', 'Javascript', 'Image', 'set_matplotlib_formats',
28 "display_svg",
29 'set_matplotlib_close',
29 "display_png",
30 'Video']
30 "display_jpeg",
31 "display_webp",
32 "display_latex",
33 "display_json",
34 "display_javascript",
35 "display_pdf",
36 "DisplayObject",
37 "TextDisplayObject",
38 "Pretty",
39 "HTML",
40 "Markdown",
41 "Math",
42 "Latex",
43 "SVG",
44 "ProgressBar",
45 "JSON",
46 "GeoJSON",
47 "Javascript",
48 "Image",
49 "set_matplotlib_formats",
50 "set_matplotlib_close",
51 "Video",
52 ]
31
53
32 _deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"]
54 _deprecated_names = ["display", "clear_output", "publish_display_data", "update_display", "DisplayHandle"]
33
55
@@ -200,6 +222,23 def display_jpeg(*objs, **kwargs):
200 _display_mimetype('image/jpeg', objs, **kwargs)
222 _display_mimetype('image/jpeg', objs, **kwargs)
201
223
202
224
225 def display_webp(*objs, **kwargs):
226 """Display the WEBP representation of an object.
227
228 Parameters
229 ----------
230 *objs : object
231 The Python objects to display, or if raw=True raw JPEG data to
232 display.
233 raw : bool
234 Are the data objects raw data or Python objects that need to be
235 formatted before display? [default: False]
236 metadata : dict (optional)
237 Metadata to be associated with the specific mimetype output.
238 """
239 _display_mimetype("image/webp", objs, **kwargs)
240
241
203 def display_latex(*objs, **kwargs):
242 def display_latex(*objs, **kwargs):
204 """Display the LaTeX representation of an object.
243 """Display the LaTeX representation of an object.
205
244
@@ -776,9 +815,14 class Javascript(TextDisplayObject):
776 r += _lib_t2*len(self.lib)
815 r += _lib_t2*len(self.lib)
777 return r
816 return r
778
817
779 # constants for identifying png/jpeg data
818
780 _PNG = b'\x89PNG\r\n\x1a\n'
819 # constants for identifying png/jpeg/gif/webp data
781 _JPEG = b'\xff\xd8'
820 _PNG = b"\x89PNG\r\n\x1a\n"
821 _JPEG = b"\xff\xd8"
822 _GIF1 = b"GIF87a"
823 _GIF2 = b"GIF89a"
824 _WEBP = b"WEBP"
825
782
826
783 def _pngxy(data):
827 def _pngxy(data):
784 """read the (width, height) from a PNG header"""
828 """read the (width, height) from a PNG header"""
@@ -786,6 +830,7 def _pngxy(data):
786 # next 8 bytes are width/height
830 # next 8 bytes are width/height
787 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
831 return struct.unpack('>ii', data[ihdr+4:ihdr+12])
788
832
833
789 def _jpegxy(data):
834 def _jpegxy(data):
790 """read the (width, height) from a JPEG header"""
835 """read the (width, height) from a JPEG header"""
791 # adapted from http://www.64lines.com/jpeg-width-height
836 # adapted from http://www.64lines.com/jpeg-width-height
@@ -805,22 +850,45 def _jpegxy(data):
805 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
850 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
806 return w, h
851 return w, h
807
852
853
808 def _gifxy(data):
854 def _gifxy(data):
809 """read the (width, height) from a GIF header"""
855 """read the (width, height) from a GIF header"""
810 return struct.unpack('<HH', data[6:10])
856 return struct.unpack('<HH', data[6:10])
811
857
812
858
859 def _webpxy(data):
860 """read the (width, height) from a WEBP header"""
861 if data[12:16] == b"VP8 ":
862 width, height = struct.unpack("<HH", data[24:30])
863 width = width & 0x3FFF
864 height = height & 0x3FFF
865 return (width, height)
866 elif data[12:16] == b"VP8L":
867 size_info = struct.unpack("<I", data[21:25])[0]
868 width = 1 + ((size_info & 0x3F) << 8) | (size_info >> 24)
869 height = 1 + (
870 (((size_info >> 8) & 0xF) << 10)
871 | (((size_info >> 14) & 0x3FC) << 2)
872 | ((size_info >> 22) & 0x3)
873 )
874 return (width, height)
875 else:
876 raise ValueError("Not a valid WEBP header")
877
878
813 class Image(DisplayObject):
879 class Image(DisplayObject):
814
880
815 _read_flags = 'rb'
881 _read_flags = "rb"
816 _FMT_JPEG = u'jpeg'
882 _FMT_JPEG = "jpeg"
817 _FMT_PNG = u'png'
883 _FMT_PNG = "png"
818 _FMT_GIF = u'gif'
884 _FMT_GIF = "gif"
819 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
885 _FMT_WEBP = "webp"
886 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF, _FMT_WEBP]
820 _MIMETYPES = {
887 _MIMETYPES = {
821 _FMT_PNG: 'image/png',
888 _FMT_PNG: "image/png",
822 _FMT_JPEG: 'image/jpeg',
889 _FMT_JPEG: "image/jpeg",
823 _FMT_GIF: 'image/gif',
890 _FMT_GIF: "image/gif",
891 _FMT_WEBP: "image/webp",
824 }
892 }
825
893
826 def __init__(
894 def __init__(
@@ -837,7 +905,7 class Image(DisplayObject):
837 metadata=None,
905 metadata=None,
838 alt=None,
906 alt=None,
839 ):
907 ):
840 """Create a PNG/JPEG/GIF image object given raw data.
908 """Create a PNG/JPEG/GIF/WEBP image object given raw data.
841
909
842 When this object is returned by an input cell or passed to the
910 When this object is returned by an input cell or passed to the
843 display function, it will result in the image being displayed
911 display function, it will result in the image being displayed
@@ -858,7 +926,7 class Image(DisplayObject):
858 Images from a file are always embedded.
926 Images from a file are always embedded.
859
927
860 format : unicode
928 format : unicode
861 The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
929 The format of the image data (png/jpeg/jpg/gif/webp). If a filename or URL is given
862 for format will be inferred from the filename extension.
930 for format will be inferred from the filename extension.
863
931
864 embed : bool
932 embed : bool
@@ -942,6 +1010,8 class Image(DisplayObject):
942 format = self._FMT_PNG
1010 format = self._FMT_PNG
943 elif ext == u'gif':
1011 elif ext == u'gif':
944 format = self._FMT_GIF
1012 format = self._FMT_GIF
1013 elif ext == "webp":
1014 format = self._FMT_WEBP
945 else:
1015 else:
946 format = ext.lower()
1016 format = ext.lower()
947 elif isinstance(data, bytes):
1017 elif isinstance(data, bytes):
@@ -949,6 +1019,12 class Image(DisplayObject):
949 # only if format has not been specified.
1019 # only if format has not been specified.
950 if data[:2] == _JPEG:
1020 if data[:2] == _JPEG:
951 format = self._FMT_JPEG
1021 format = self._FMT_JPEG
1022 elif data[:8] == _PNG:
1023 format = self._FMT_PNG
1024 elif data[8:12] == _WEBP:
1025 format = self._FMT_WEBP
1026 elif data[:6] == _GIF1 or data[:6] == _GIF2:
1027 format = self._FMT_GIF
952
1028
953 # failed to detect format, default png
1029 # failed to detect format, default png
954 if format is None:
1030 if format is None:
@@ -1,6 +1,15
1 ============
1 ============
2 8.x Series
2 8.x Series
3 ============
3 ============
4
5 .. _version 8.29:
6
7 IPython 8.29
8 ============
9
10
11 - Add support for WEBP to ``IPython.display.Image``. :ghpull:`14526`
12
4 .. _version 8.28:
13 .. _version 8.28:
5
14
6 IPython 8.28
15 IPython 8.28
General Comments 0
You need to be logged in to leave comments. Login now