1# Copyright (C) 2001-2006 Python Software Foundation 2# Author: Barry Warsaw 3# Contact: [email protected] 4 5"""Class representing image/* type MIME documents.""" 6 7__all__ = ['MIMEImage'] 8 9from email import encoders 10from email.mime.nonmultipart import MIMENonMultipart 11 12 13class MIMEImage(MIMENonMultipart): 14 """Class for generating image/* type MIME documents.""" 15 16 def __init__(self, _imagedata, _subtype=None, 17 _encoder=encoders.encode_base64, *, policy=None, **_params): 18 """Create an image/* type MIME document. 19 20 _imagedata contains the bytes for the raw image data. If the data 21 type can be detected (jpeg, png, gif, tiff, rgb, pbm, pgm, ppm, 22 rast, xbm, bmp, webp, and exr attempted), then the subtype will be 23 automatically included in the Content-Type header. Otherwise, you can 24 specify the specific image subtype via the _subtype parameter. 25 26 _encoder is a function which will perform the actual encoding for 27 transport of the image data. It takes one argument, which is this 28 Image instance. It should use get_payload() and set_payload() to 29 change the payload to the encoded form. It should also add any 30 Content-Transfer-Encoding or other headers to the message as 31 necessary. The default encoding is Base64. 32 33 Any additional keyword arguments are passed to the base class 34 constructor, which turns them into parameters on the Content-Type 35 header. 36 """ 37 _subtype = _what(_imagedata) if _subtype is None else _subtype 38 if _subtype is None: 39 raise TypeError('Could not guess image MIME subtype') 40 MIMENonMultipart.__init__(self, 'image', _subtype, policy=policy, 41 **_params) 42 self.set_payload(_imagedata) 43 _encoder(self) 44 45 46_rules = [] 47 48 49# Originally from the imghdr module. 50def _what(data): 51 for rule in _rules: 52 if res := rule(data): 53 return res 54 else: 55 return None 56 57 58def rule(rulefunc): 59 _rules.append(rulefunc) 60 return rulefunc 61 62 63@rule 64def _jpeg(h): 65 """JPEG data with JFIF or Exif markers; and raw JPEG""" 66 if h[6:10] in (b'JFIF', b'Exif'): 67 return 'jpeg' 68 elif h[:4] == b'\xff\xd8\xff\xdb': 69 return 'jpeg' 70 71 72@rule 73def _png(h): 74 if h.startswith(b'\211PNG\r\n\032\n'): 75 return 'png' 76 77 78@rule 79def _gif(h): 80 """GIF ('87 and '89 variants)""" 81 if h[:6] in (b'GIF87a', b'GIF89a'): 82 return 'gif' 83 84 85@rule 86def _tiff(h): 87 """TIFF (can be in Motorola or Intel byte order)""" 88 if h[:2] in (b'MM', b'II'): 89 return 'tiff' 90 91 92@rule 93def _rgb(h): 94 """SGI image library""" 95 if h.startswith(b'\001\332'): 96 return 'rgb' 97 98 99@rule 100def _pbm(h): 101 """PBM (portable bitmap)""" 102 if len(h) >= 3 and \ 103 h[0] == ord(b'P') and h[1] in b'14' and h[2] in b' \t\n\r': 104 return 'pbm' 105 106 107@rule 108def _pgm(h): 109 """PGM (portable graymap)""" 110 if len(h) >= 3 and \ 111 h[0] == ord(b'P') and h[1] in b'25' and h[2] in b' \t\n\r': 112 return 'pgm' 113 114 115@rule 116def _ppm(h): 117 """PPM (portable pixmap)""" 118 if len(h) >= 3 and \ 119 h[0] == ord(b'P') and h[1] in b'36' and h[2] in b' \t\n\r': 120 return 'ppm' 121 122 123@rule 124def _rast(h): 125 """Sun raster file""" 126 if h.startswith(b'\x59\xA6\x6A\x95'): 127 return 'rast' 128 129 130@rule 131def _xbm(h): 132 """X bitmap (X10 or X11)""" 133 if h.startswith(b'#define '): 134 return 'xbm' 135 136 137@rule 138def _bmp(h): 139 if h.startswith(b'BM'): 140 return 'bmp' 141 142 143@rule 144def _webp(h): 145 if h.startswith(b'RIFF') and h[8:12] == b'WEBP': 146 return 'webp' 147 148 149@rule 150def _exr(h): 151 if h.startswith(b'\x76\x2f\x31\x01'): 152 return 'exr' 153