mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 10:16:17 +03:00
Allow get_child_images to access JPEG thumbnails
This commit is contained in:
parent
8ada23ed04
commit
c2a42655e1
BIN
Tests/images/flower_thumbnail.png
Normal file
BIN
Tests/images/flower_thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
|
@ -415,6 +415,13 @@ class TestFileJpeg:
|
||||||
info = im._getexif()
|
info = im._getexif()
|
||||||
assert info[305] == "Adobe Photoshop CS Macintosh"
|
assert info[305] == "Adobe Photoshop CS Macintosh"
|
||||||
|
|
||||||
|
def test_get_child_images(self):
|
||||||
|
with Image.open("Tests/images/flower.jpg") as im:
|
||||||
|
ims = im.get_child_images()
|
||||||
|
|
||||||
|
assert len(ims) == 1
|
||||||
|
assert_image_equal_tofile(ims[0], "Tests/images/flower_thumbnail.png")
|
||||||
|
|
||||||
def test_mp(self):
|
def test_mp(self):
|
||||||
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
|
with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
|
||||||
assert im._getmp() is None
|
assert im._getmp() is None
|
||||||
|
|
|
@ -1454,6 +1454,49 @@ class Image:
|
||||||
self._exif._loaded = False
|
self._exif._loaded = False
|
||||||
self.getexif()
|
self.getexif()
|
||||||
|
|
||||||
|
def get_child_images(self):
|
||||||
|
child_images = []
|
||||||
|
exif = self.getexif()
|
||||||
|
ifds = []
|
||||||
|
if ExifTags.Base.SubIFDs in exif:
|
||||||
|
subifd_offsets = exif[ExifTags.Base.SubIFDs]
|
||||||
|
if subifd_offsets:
|
||||||
|
if not isinstance(subifd_offsets, tuple):
|
||||||
|
subifd_offsets = (subifd_offsets,)
|
||||||
|
for subifd_offset in subifd_offsets:
|
||||||
|
ifds.append((exif._get_ifd_dict(subifd_offset), subifd_offset))
|
||||||
|
ifd1 = exif.get_ifd(ExifTags.IFD.IFD1)
|
||||||
|
if ifd1 and ifd1.get(513):
|
||||||
|
ifds.append((ifd1, exif._info.next))
|
||||||
|
|
||||||
|
offset = None
|
||||||
|
for ifd, ifd_offset in ifds:
|
||||||
|
current_offset = self.fp.tell()
|
||||||
|
if offset is None:
|
||||||
|
offset = current_offset
|
||||||
|
|
||||||
|
fp = self.fp
|
||||||
|
thumbnailOffset = ifd.get(513)
|
||||||
|
if thumbnailOffset is not None:
|
||||||
|
try:
|
||||||
|
thumbnailOffset += self._exif_offset
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
self.fp.seek(thumbnailOffset)
|
||||||
|
data = self.fp.read(ifd.get(514))
|
||||||
|
fp = io.BytesIO(data)
|
||||||
|
|
||||||
|
with open(fp) as im:
|
||||||
|
if thumbnailOffset is None:
|
||||||
|
im._frame_pos = [ifd_offset]
|
||||||
|
im._seek(0)
|
||||||
|
im.load()
|
||||||
|
child_images.append(im)
|
||||||
|
|
||||||
|
if offset is not None:
|
||||||
|
self.fp.seek(offset)
|
||||||
|
return child_images
|
||||||
|
|
||||||
def getim(self):
|
def getim(self):
|
||||||
"""
|
"""
|
||||||
Returns a capsule that points to the internal image memory.
|
Returns a capsule that points to the internal image memory.
|
||||||
|
|
|
@ -89,6 +89,7 @@ def APP(self, marker):
|
||||||
if "exif" not in self.info:
|
if "exif" not in self.info:
|
||||||
# extract EXIF information (incomplete)
|
# extract EXIF information (incomplete)
|
||||||
self.info["exif"] = s # FIXME: value will change
|
self.info["exif"] = s # FIXME: value will change
|
||||||
|
self._exif_offset = self.fp.tell() - n + 6
|
||||||
elif marker == 0xFFE2 and s[:5] == b"FPXR\0":
|
elif marker == 0xFFE2 and s[:5] == b"FPXR\0":
|
||||||
# extract FlashPix information (incomplete)
|
# extract FlashPix information (incomplete)
|
||||||
self.info["flashpix"] = s # FIXME: value will change
|
self.info["flashpix"] = s # FIXME: value will change
|
||||||
|
|
|
@ -1153,39 +1153,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
"""Return the current frame number"""
|
"""Return the current frame number"""
|
||||||
return self.__frame
|
return self.__frame
|
||||||
|
|
||||||
def get_child_images(self):
|
|
||||||
if SUBIFD not in self.tag_v2:
|
|
||||||
return []
|
|
||||||
child_images = []
|
|
||||||
exif = self.getexif()
|
|
||||||
offset = None
|
|
||||||
for im_offset in self.tag_v2[SUBIFD]:
|
|
||||||
# reset buffered io handle in case fp
|
|
||||||
# was passed to libtiff, invalidating the buffer
|
|
||||||
current_offset = self._fp.tell()
|
|
||||||
if offset is None:
|
|
||||||
offset = current_offset
|
|
||||||
|
|
||||||
fp = self._fp
|
|
||||||
ifd = exif._get_ifd_dict(im_offset)
|
|
||||||
jpegInterchangeFormat = ifd.get(513)
|
|
||||||
if jpegInterchangeFormat is not None:
|
|
||||||
fp.seek(jpegInterchangeFormat)
|
|
||||||
jpeg_data = fp.read(ifd.get(514))
|
|
||||||
|
|
||||||
fp = io.BytesIO(jpeg_data)
|
|
||||||
|
|
||||||
with Image.open(fp) as im:
|
|
||||||
if jpegInterchangeFormat is None:
|
|
||||||
im._frame_pos = [im_offset]
|
|
||||||
im._seek(0)
|
|
||||||
im.load()
|
|
||||||
child_images.append(im)
|
|
||||||
|
|
||||||
if offset is not None:
|
|
||||||
self._fp.seek(offset)
|
|
||||||
return child_images
|
|
||||||
|
|
||||||
def getxmp(self):
|
def getxmp(self):
|
||||||
"""
|
"""
|
||||||
Returns a dictionary containing the XMP tags.
|
Returns a dictionary containing the XMP tags.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user