66
77__all__ = ['MIMEImage' ]
88
9- import imghdr
10-
119from email import encoders
1210from email .mime .nonmultipart import MIMENonMultipart
1311
1412
15-
13+ # Originally from the imghdr module.
14+ def _what (h ):
15+ for tf in tests :
16+ if res := tf (h ):
17+ return res
18+ else :
19+ return None
20+
21+ tests = []
22+
23+ def _test_jpeg (h ):
24+ """JPEG data with JFIF or Exif markers; and raw JPEG"""
25+ if h [6 :10 ] in (b'JFIF' , b'Exif' ):
26+ return 'jpeg'
27+ elif h [:4 ] == b'\xff \xd8 \xff \xdb ' :
28+ return 'jpeg'
29+
30+ tests .append (_test_jpeg )
31+
32+ def _test_png (h ):
33+ if h .startswith (b'\211 PNG\r \n \032 \n ' ):
34+ return 'png'
35+
36+ tests .append (_test_png )
37+
38+ def _test_gif (h ):
39+ """GIF ('87 and '89 variants)"""
40+ if h [:6 ] in (b'GIF87a' , b'GIF89a' ):
41+ return 'gif'
42+
43+ tests .append (_test_gif )
44+
45+ def _test_tiff (h ):
46+ """TIFF (can be in Motorola or Intel byte order)"""
47+ if h [:2 ] in (b'MM' , b'II' ):
48+ return 'tiff'
49+
50+ tests .append (_test_tiff )
51+
52+ def _test_rgb (h ):
53+ """SGI image library"""
54+ if h .startswith (b'\001 \332 ' ):
55+ return 'rgb'
56+
57+ tests .append (_test_rgb )
58+
59+ def _test_pbm (h ):
60+ """PBM (portable bitmap)"""
61+ if len (h ) >= 3 and \
62+ h [0 ] == ord (b'P' ) and h [1 ] in b'14' and h [2 ] in b' \t \n \r ' :
63+ return 'pbm'
64+
65+ tests .append (_test_pbm )
66+
67+ def _test_pgm (h ):
68+ """PGM (portable graymap)"""
69+ if len (h ) >= 3 and \
70+ h [0 ] == ord (b'P' ) and h [1 ] in b'25' and h [2 ] in b' \t \n \r ' :
71+ return 'pgm'
72+
73+ tests .append (_test_pgm )
74+
75+ def _test_ppm (h ):
76+ """PPM (portable pixmap)"""
77+ if len (h ) >= 3 and \
78+ h [0 ] == ord (b'P' ) and h [1 ] in b'36' and h [2 ] in b' \t \n \r ' :
79+ return 'ppm'
80+
81+ tests .append (_test_ppm )
82+
83+ def _test_rast (h ):
84+ """Sun raster file"""
85+ if h .startswith (b'\x59 \xA6 \x6A \x95 ' ):
86+ return 'rast'
87+
88+ tests .append (_test_rast )
89+
90+ def _test_xbm (h ):
91+ """X bitmap (X10 or X11)"""
92+ if h .startswith (b'#define ' ):
93+ return 'xbm'
94+
95+ tests .append (_test_xbm )
96+
97+ def _test_bmp (h ):
98+ if h .startswith (b'BM' ):
99+ return 'bmp'
100+
101+ tests .append (_test_bmp )
102+
103+ def _test_webp (h ):
104+ if h .startswith (b'RIFF' ) and h [8 :12 ] == b'WEBP' :
105+ return 'webp'
106+
107+ tests .append (_test_webp )
108+
109+ def _test_exr (h ):
110+ if h .startswith (b'\x76 \x2f \x31 \x01 ' ):
111+ return 'exr'
112+
113+ tests .append (_test_exr )
114+
115+
16116class MIMEImage (MIMENonMultipart ):
17117 """Class for generating image/* type MIME documents."""
18118
19119 def __init__ (self , _imagedata , _subtype = None ,
20120 _encoder = encoders .encode_base64 , * , policy = None , ** _params ):
21121 """Create an image/* type MIME document.
22122
23- _imagedata is a string containing the raw image data. If this data
24- can be decoded by the standard Python `imghdr' module, then the
25- subtype will be automatically included in the Content-Type header.
26- Otherwise, you can specify the specific image subtype via the _subtype
27- parameter.
123+ _imagedata is a string containing the raw image data. If the data
124+ type can be detected (jpeg, png, gif, tiff, rgb, pbm, pgm, ppm,
125+ rast, xbm, bmp, webp, and exr attempted), then the subtype will be
126+ automatically included in the Content-Type header. Otherwise, you can
127+ specify the specific image subtype via the _subtype parameter.
28128
29129 _encoder is a function which will perform the actual encoding for
30130 transport of the image data. It takes one argument, which is this
@@ -38,9 +138,8 @@ def __init__(self, _imagedata, _subtype=None,
38138 header.
39139 """
40140 if _subtype is None :
41- _subtype = imghdr .what (None , _imagedata )
42- if _subtype is None :
43- raise TypeError ('Could not guess image MIME subtype' )
141+ if (_subtype := _what (_imagedata )) is None :
142+ raise TypeError ('Could not guess image MIME subtype' )
44143 MIMENonMultipart .__init__ (self , 'image' , _subtype , policy = policy ,
45144 ** _params )
46145 self .set_payload (_imagedata )
0 commit comments