Skip to content

Commit 585357a

Browse files
westurnerCarreau
authored andcommitted
ENH: add webp support to IPython.display.Image and complete identification of JPEG,PNG,GIF,WEBP image types by initial bytes
1 parent e63a316 commit 585357a

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

IPython/core/display.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323

2424
__all__ = ['display_pretty', 'display_html', 'display_markdown',
25-
'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
25+
'display_svg', 'display_png', 'display_jpeg', 'display_webp',
26+
'display_latex', 'display_json',
2627
'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
2728
'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'ProgressBar', 'JSON',
2829
'GeoJSON', 'Javascript', 'Image', 'set_matplotlib_formats',
@@ -200,6 +201,23 @@ def display_jpeg(*objs, **kwargs):
200201
_display_mimetype('image/jpeg', objs, **kwargs)
201202

202203

204+
def display_webp(*objs, **kwargs):
205+
"""Display the WEBP representation of an object.
206+
207+
Parameters
208+
----------
209+
*objs : object
210+
The Python objects to display, or if raw=True raw JPEG data to
211+
display.
212+
raw : bool
213+
Are the data objects raw data or Python objects that need to be
214+
formatted before display? [default: False]
215+
metadata : dict (optional)
216+
Metadata to be associated with the specific mimetype output.
217+
"""
218+
_display_mimetype('image/webp', objs, **kwargs)
219+
220+
203221
def display_latex(*objs, **kwargs):
204222
"""Display the LaTeX representation of an object.
205223
@@ -776,9 +794,12 @@ def _repr_javascript_(self):
776794
r += _lib_t2*len(self.lib)
777795
return r
778796

779-
# constants for identifying png/jpeg data
797+
# constants for identifying png/jpeg/gif/webp data
780798
_PNG = b'\x89PNG\r\n\x1a\n'
781799
_JPEG = b'\xff\xd8'
800+
_GIF1 = b"GIF87a"
801+
_GIF2 = b"GIF89a"
802+
_WEBP = b'WEBP'
782803

783804
def _pngxy(data):
784805
"""read the (width, height) from a PNG header"""
@@ -809,18 +830,37 @@ def _gifxy(data):
809830
"""read the (width, height) from a GIF header"""
810831
return struct.unpack('<HH', data[6:10])
811832

833+
def _webpxy(data):
834+
"""read the (width, height) from a WEBP header"""
835+
if data[12:16] == b"VP8 ":
836+
width, height = struct.unpack('<HH', data[24:30])
837+
width = (width & 0x3fff)
838+
height = (height & 0x3fff)
839+
return (width, height)
840+
elif data[12:16] == b"VP8L":
841+
size_info = struct.unpack('<I', data[21:25])[0]
842+
width = 1 + ((size_info & 0x3F) << 8) | (size_info >> 24)
843+
height = 1 + ((((size_info >> 8) & 0xF) << 10) |
844+
(((size_info >> 14) & 0x3FC) << 2) |
845+
((size_info >> 22) & 0x3))
846+
return (width, height)
847+
else:
848+
raise ValueError("Not a valid WEBP header")
849+
812850

813851
class Image(DisplayObject):
814852

815853
_read_flags = 'rb'
816854
_FMT_JPEG = u'jpeg'
817855
_FMT_PNG = u'png'
818856
_FMT_GIF = u'gif'
819-
_ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF]
857+
_FMT_WEBP = u'webp'
858+
_ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG, _FMT_GIF, _FMT_WEBP]
820859
_MIMETYPES = {
821860
_FMT_PNG: 'image/png',
822861
_FMT_JPEG: 'image/jpeg',
823862
_FMT_GIF: 'image/gif',
863+
_FMT_WEBP: 'image/webp',
824864
}
825865

826866
def __init__(
@@ -858,7 +898,7 @@ def __init__(
858898
Images from a file are always embedded.
859899
860900
format : unicode
861-
The format of the image data (png/jpeg/jpg/gif). If a filename or URL is given
901+
The format of the image data (png/jpeg/jpg/gif/webp). If a filename or URL is given
862902
for format will be inferred from the filename extension.
863903
864904
embed : bool
@@ -942,13 +982,21 @@ def __init__(
942982
format = self._FMT_PNG
943983
elif ext == u'gif':
944984
format = self._FMT_GIF
985+
elif ext == u'webp':
986+
format = self._FMT_WEBP
945987
else:
946988
format = ext.lower()
947989
elif isinstance(data, bytes):
948990
# infer image type from image data header,
949991
# only if format has not been specified.
950992
if data[:2] == _JPEG:
951993
format = self._FMT_JPEG
994+
elif data[:8] == _PNG:
995+
format = self._FMT_PNG
996+
elif data[8:12] == _WEBP:
997+
format = self._FMT_WEBP
998+
elif data[:6] == self._GIF1 or data[:6] == self._GIF2:
999+
format = self._FMT_GIF
9521000

9531001
# failed to detect format, default png
9541002
if format is None:

0 commit comments

Comments
 (0)