mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Changed the Image getexif method to return a shared Exif instance
This commit is contained in:
		
							parent
							
								
									0b405c86be
								
							
						
					
					
						commit
						f3ed44a566
					
				| 
						 | 
					@ -555,6 +555,7 @@ class Image(object):
 | 
				
			||||||
        self.category = NORMAL
 | 
					        self.category = NORMAL
 | 
				
			||||||
        self.readonly = 0
 | 
					        self.readonly = 0
 | 
				
			||||||
        self.pyaccess = None
 | 
					        self.pyaccess = None
 | 
				
			||||||
 | 
					        self._exif = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def width(self):
 | 
					    def width(self):
 | 
				
			||||||
| 
						 | 
					@ -1324,10 +1325,10 @@ class Image(object):
 | 
				
			||||||
        return self.im.getextrema()
 | 
					        return self.im.getextrema()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getexif(self):
 | 
					    def getexif(self):
 | 
				
			||||||
        exif = Exif()
 | 
					        if self._exif is None:
 | 
				
			||||||
        if "exif" in self.info:
 | 
					            self._exif = Exif()
 | 
				
			||||||
            exif.load(self.info["exif"])
 | 
					        self._exif.load(self.info.get("exif"))
 | 
				
			||||||
        return exif
 | 
					        return self._exif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getim(self):
 | 
					    def getim(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -3137,7 +3138,8 @@ class Exif(MutableMapping):
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self._data = {}
 | 
					        self._data = {}
 | 
				
			||||||
        self._ifds = {}
 | 
					        self._ifds = {}
 | 
				
			||||||
        self.info = None
 | 
					        self._info = None
 | 
				
			||||||
 | 
					        self._loaded_exif = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _fixup(self, value):
 | 
					    def _fixup(self, value):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -3173,15 +3175,24 @@ class Exif(MutableMapping):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # The EXIF record consists of a TIFF file embedded in a JPEG
 | 
					        # The EXIF record consists of a TIFF file embedded in a JPEG
 | 
				
			||||||
        # application marker (!).
 | 
					        # application marker (!).
 | 
				
			||||||
 | 
					        if data == self._loaded_exif:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self._loaded_exif = data
 | 
				
			||||||
 | 
					        self._data.clear()
 | 
				
			||||||
 | 
					        self._ifds.clear()
 | 
				
			||||||
 | 
					        self._info = None
 | 
				
			||||||
 | 
					        if not data:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.fp = io.BytesIO(data[6:])
 | 
					        self.fp = io.BytesIO(data[6:])
 | 
				
			||||||
        self.head = self.fp.read(8)
 | 
					        self.head = self.fp.read(8)
 | 
				
			||||||
        # process dictionary
 | 
					        # process dictionary
 | 
				
			||||||
        from . import TiffImagePlugin
 | 
					        from . import TiffImagePlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.info = TiffImagePlugin.ImageFileDirectory_v1(self.head)
 | 
					        self._info = TiffImagePlugin.ImageFileDirectory_v1(self.head)
 | 
				
			||||||
        self.endian = self.info._endian
 | 
					        self.endian = self._info._endian
 | 
				
			||||||
        self.fp.seek(self.info.next)
 | 
					        self.fp.seek(self._info.next)
 | 
				
			||||||
        self.info.load(self.fp)
 | 
					        self._info.load(self.fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # get EXIF extension
 | 
					        # get EXIF extension
 | 
				
			||||||
        ifd = self._get_ifd_dict(0x8769)
 | 
					        ifd = self._get_ifd_dict(0x8769)
 | 
				
			||||||
| 
						 | 
					@ -3286,29 +3297,29 @@ class Exif(MutableMapping):
 | 
				
			||||||
        return self._ifds.get(tag, {})
 | 
					        return self._ifds.get(tag, {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        if self.info is not None:
 | 
					        if self._info is not None:
 | 
				
			||||||
            # Load all keys into self._data
 | 
					            # Load all keys into self._data
 | 
				
			||||||
            for tag in self.info.keys():
 | 
					            for tag in self._info.keys():
 | 
				
			||||||
                self[tag]
 | 
					                self[tag]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return str(self._data)
 | 
					        return str(self._data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __len__(self):
 | 
					    def __len__(self):
 | 
				
			||||||
        keys = set(self._data)
 | 
					        keys = set(self._data)
 | 
				
			||||||
        if self.info is not None:
 | 
					        if self._info is not None:
 | 
				
			||||||
            keys.update(self.info)
 | 
					            keys.update(self._info)
 | 
				
			||||||
        return len(keys)
 | 
					        return len(keys)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __getitem__(self, tag):
 | 
					    def __getitem__(self, tag):
 | 
				
			||||||
        if self.info is not None and tag not in self._data and tag in self.info:
 | 
					        if self._info is not None and tag not in self._data and tag in self._info:
 | 
				
			||||||
            self._data[tag] = self._fixup(self.info[tag])
 | 
					            self._data[tag] = self._fixup(self._info[tag])
 | 
				
			||||||
            if tag == 0x8825:
 | 
					            if tag == 0x8825:
 | 
				
			||||||
                self._data[tag] = self.get_ifd(tag)
 | 
					                self._data[tag] = self.get_ifd(tag)
 | 
				
			||||||
            del self.info[tag]
 | 
					            del self._info[tag]
 | 
				
			||||||
        return self._data[tag]
 | 
					        return self._data[tag]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __contains__(self, tag):
 | 
					    def __contains__(self, tag):
 | 
				
			||||||
        return tag in self._data or (self.info is not None and tag in self.info)
 | 
					        return tag in self._data or (self._info is not None and tag in self._info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not py3:
 | 
					    if not py3:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3316,23 +3327,23 @@ class Exif(MutableMapping):
 | 
				
			||||||
            return tag in self
 | 
					            return tag in self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __setitem__(self, tag, value):
 | 
					    def __setitem__(self, tag, value):
 | 
				
			||||||
        if self.info is not None:
 | 
					        if self._info is not None:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                del self.info[tag]
 | 
					                del self._info[tag]
 | 
				
			||||||
            except KeyError:
 | 
					            except KeyError:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
        self._data[tag] = value
 | 
					        self._data[tag] = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __delitem__(self, tag):
 | 
					    def __delitem__(self, tag):
 | 
				
			||||||
        if self.info is not None:
 | 
					        if self._info is not None:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                del self.info[tag]
 | 
					                del self._info[tag]
 | 
				
			||||||
            except KeyError:
 | 
					            except KeyError:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
        del self._data[tag]
 | 
					        del self._data[tag]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __iter__(self):
 | 
					    def __iter__(self):
 | 
				
			||||||
        keys = set(self._data)
 | 
					        keys = set(self._data)
 | 
				
			||||||
        if self.info is not None:
 | 
					        if self._info is not None:
 | 
				
			||||||
            keys.update(self.info)
 | 
					            keys.update(self._info)
 | 
				
			||||||
        return iter(keys)
 | 
					        return iter(keys)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -485,19 +485,9 @@ def _fixup_dict(src_dict):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _getexif(self):
 | 
					def _getexif(self):
 | 
				
			||||||
    # Use the cached version if possible
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return self.info["parsed_exif"]
 | 
					 | 
				
			||||||
    except KeyError:
 | 
					 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if "exif" not in self.info:
 | 
					    if "exif" not in self.info:
 | 
				
			||||||
        return None
 | 
					        return None
 | 
				
			||||||
    exif = dict(self.getexif())
 | 
					    return dict(self.getexif())
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Cache the result for future use
 | 
					 | 
				
			||||||
    self.info["parsed_exif"] = exif
 | 
					 | 
				
			||||||
    return exif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _getmp(self):
 | 
					def _getmp(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,8 +86,6 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
 | 
				
			||||||
        self.offset = self.__mpoffsets[frame]
 | 
					        self.offset = self.__mpoffsets[frame]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.fp.seek(self.offset + 2)  # skip SOI marker
 | 
					        self.fp.seek(self.offset + 2)  # skip SOI marker
 | 
				
			||||||
        if "parsed_exif" in self.info:
 | 
					 | 
				
			||||||
            del self.info["parsed_exif"]
 | 
					 | 
				
			||||||
        if i16(self.fp.read(2)) == 0xFFE1:  # APP1
 | 
					        if i16(self.fp.read(2)) == 0xFFE1:  # APP1
 | 
				
			||||||
            n = i16(self.fp.read(2)) - 2
 | 
					            n = i16(self.fp.read(2)) - 2
 | 
				
			||||||
            self.info["exif"] = ImageFile._safe_read(self.fp, n)
 | 
					            self.info["exif"] = ImageFile._safe_read(self.fp, n)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user