From 3a7e2e259aa705e78467d08a723b8ef447d1d778 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Fri, 15 Feb 2019 22:07:11 +0100 Subject: [PATCH 1/7] split _open in two parts --- src/PIL/MpoImagePlugin.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 64c0f57a4..0a267117e 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -46,7 +46,10 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): def _open(self): self.fp.seek(0) # prep the fp in order to pass the JPEG test JpegImagePlugin.JpegImageFile._open(self) - self.mpinfo = self._getmp() + self._after_jpeg_open(self._getmp()) + + def _after_jpeg_open(self, mpheader): + self.mpinfo = mpheader self.__framecount = self.mpinfo[0xB001] self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] for mpent in self.mpinfo[0xB002]] From ac5dd15e16580b08752aaa2a816d6d550aca7940 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Fri, 15 Feb 2019 22:08:14 +0100 Subject: [PATCH 2/7] create static method to transform a Jpeg into an Mpo This is dirty "downcasting". It just works in this special case. --- src/PIL/MpoImagePlugin.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 0a267117e..216ed9fbc 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -98,6 +98,22 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): finally: self.__fp = None + @staticmethod + def adopt(jpeg_instance, mpheader=None): + ''' + Transform the instance of JpegImageFile into + instance of MpoImageFile. + After the call, the JpegImageFile is extended + to be an MpoImageFile. + + This is essentially useful when opening a JPEG + file that reveals itself as an MPO, to avoid + double call to _open. + ''' + jpeg_instance.__class__ = MpoImageFile + jpeg_instance._after_jpeg_open(mpheader) + return jpeg_instance + # --------------------------------------------------------------------- # Registry stuff From 4a87e067a20a5ada002317f9bbe1fa2023e65eb2 Mon Sep 17 00:00:00 2001 From: Adrien CLERC Date: Fri, 15 Feb 2019 22:08:31 +0100 Subject: [PATCH 3/7] convert Jpeg to Mpo instead of re-reading everything --- src/PIL/JpegImagePlugin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 2f76e9675..e0df2e544 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -786,7 +786,8 @@ def jpeg_factory(fp=None, filename=None): if mpheader[45057] > 1: # It's actually an MPO from .MpoImagePlugin import MpoImageFile - im = MpoImageFile(fp, filename) + # Don't reload everything, just convert it. + im = MpoImageFile.adopt(im, mpheader) except (TypeError, IndexError): # It is really a JPEG pass From 85cc21b5639b14a243768fd4c4d161004c04bad3 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 7 Mar 2019 13:22:14 +0100 Subject: [PATCH 4/7] Update src/PIL/MpoImagePlugin.py Co-Authored-By: Glandos --- src/PIL/MpoImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 216ed9fbc..5b606b345 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -100,7 +100,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): @staticmethod def adopt(jpeg_instance, mpheader=None): - ''' + """ Transform the instance of JpegImageFile into instance of MpoImageFile. After the call, the JpegImageFile is extended From d0172a08ddfb65860fef917a020e12069a2be653 Mon Sep 17 00:00:00 2001 From: Hugo Date: Thu, 7 Mar 2019 13:22:20 +0100 Subject: [PATCH 5/7] Update src/PIL/MpoImagePlugin.py Co-Authored-By: Glandos --- src/PIL/MpoImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 5b606b345..7ea1018bc 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -109,7 +109,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): This is essentially useful when opening a JPEG file that reveals itself as an MPO, to avoid double call to _open. - ''' + """ jpeg_instance.__class__ = MpoImageFile jpeg_instance._after_jpeg_open(mpheader) return jpeg_instance From dbf65b0890a82042389755d6aa061b79616cac0b Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Sat, 23 Mar 2019 22:11:32 +0100 Subject: [PATCH 6/7] Update src/PIL/MpoImagePlugin.py Co-Authored-By: Glandos --- src/PIL/MpoImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 7ea1018bc..a55cce2ec 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -102,7 +102,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): def adopt(jpeg_instance, mpheader=None): """ Transform the instance of JpegImageFile into - instance of MpoImageFile. + an instance of MpoImageFile. After the call, the JpegImageFile is extended to be an MpoImageFile. From b08b122c8b4f77f5b5068ba66adb6800400f1a4a Mon Sep 17 00:00:00 2001 From: Glandos Date: Sun, 24 Mar 2019 09:48:23 +0100 Subject: [PATCH 7/7] use default value if mpheader is not provided --- src/PIL/MpoImagePlugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 216ed9fbc..dcea887ad 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -46,10 +46,10 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): def _open(self): self.fp.seek(0) # prep the fp in order to pass the JPEG test JpegImagePlugin.JpegImageFile._open(self) - self._after_jpeg_open(self._getmp()) + self._after_jpeg_open() - def _after_jpeg_open(self, mpheader): - self.mpinfo = mpheader + def _after_jpeg_open(self, mpheader=None): + self.mpinfo = mpheader if mpheader is not None else self._getmp() self.__framecount = self.mpinfo[0xB001] self.__mpoffsets = [mpent['DataOffset'] + self.info['mpoffset'] for mpent in self.mpinfo[0xB002]]