Added generic wrapper function node_helpers.pillow to fix PIL issues #4472 and #2445 (#3422)

* Update node_helpers.py to use generic pillow wrapper to resolve multiple meta-data related issues.

replaced open_image function with a generic pillow function that takes Pil functions as a dependency injection and applies the ImageFile.LOAD_TRUNCATED_IMAGES try except fix to them. 

This provides an extensible function to handle related errors that can wrap offending functions when discovered without the need to repeat code.

* Update a few Pil functions to use node_helpers.pillow wrapper

Update a Pil function calls in a few locations to use the generic node_helpers.pillow wrapper that takes the function as a dependency injection and uses the try except method with ImageFIle.LOAD_TRUNCATED_IMAGES solution

* Corrected comment in issue #s fixed.

* Update node_helpers.py to remove import of Image from PIL

import of Image is no longer required as functions are Injected
This commit is contained in:
shawnington 2024-05-09 02:38:00 -07:00 committed by GitHub
parent 93e876a3be
commit 0fecfd2b1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 20 deletions

View File

@ -1,4 +1,4 @@
from PIL import Image, ImageFile, UnidentifiedImageError from PIL import ImageFile, UnidentifiedImageError
def conditioning_set_values(conditioning, values={}): def conditioning_set_values(conditioning, values={}):
c = [] c = []
@ -10,16 +10,15 @@ def conditioning_set_values(conditioning, values={}):
return c return c
def open_image(path): def pillow(fn, arg):
prev_value = None prev_value = None
try: try:
img = Image.open(path) x = fn(arg)
except (UnidentifiedImageError, ValueError): #PIL issues #4472 and #2445 except (OSError, UnidentifiedImageError, ValueError): #PIL issues #4472 and #2445, also fixes ComfyUI issue #3416
prev_value = ImageFile.LOAD_TRUNCATED_IMAGES prev_value = ImageFile.LOAD_TRUNCATED_IMAGES
ImageFile.LOAD_TRUNCATED_IMAGES = True ImageFile.LOAD_TRUNCATED_IMAGES = True
img = Image.open(path) x = fn(arg)
finally: finally:
if prev_value is not None: if prev_value is not None:
ImageFile.LOAD_TRUNCATED_IMAGES = prev_value ImageFile.LOAD_TRUNCATED_IMAGES = prev_value
return img return x

View File

@ -1457,21 +1457,12 @@ class LoadImage:
def load_image(self, image): def load_image(self, image):
image_path = folder_paths.get_annotated_filepath(image) image_path = folder_paths.get_annotated_filepath(image)
img = node_helpers.open_image(image_path) img = node_helpers.pillow(Image.open, image_path)
output_images = [] output_images = []
output_masks = [] output_masks = []
for i in ImageSequence.Iterator(img): for i in ImageSequence.Iterator(img):
prev_value = None i = node_helpers.pillow(ImageOps.exif_transpose, i)
try:
i = ImageOps.exif_transpose(i)
except OSError:
prev_value = ImageFile.LOAD_TRUNCATED_IMAGES
ImageFile.LOAD_TRUNCATED_IMAGES = True
i = ImageOps.exif_transpose(i)
finally:
if prev_value is not None:
ImageFile.LOAD_TRUNCATED_IMAGES = prev_value
if i.mode == 'I': if i.mode == 'I':
i = i.point(lambda i: i * (1 / 255)) i = i.point(lambda i: i * (1 / 255))
@ -1527,8 +1518,8 @@ class LoadImageMask:
FUNCTION = "load_image" FUNCTION = "load_image"
def load_image(self, image, channel): def load_image(self, image, channel):
image_path = folder_paths.get_annotated_filepath(image) image_path = folder_paths.get_annotated_filepath(image)
i = Image.open(image_path) i = node_helpers.pillow(Image.open, image_path)
i = ImageOps.exif_transpose(i) i = node_helpers.pillow(ImageOps.exif_transpose, i)
if i.getbands() != ("R", "G", "B", "A"): if i.getbands() != ("R", "G", "B", "A"):
if i.mode == 'I': if i.mode == 'I':
i = i.point(lambda i: i * (1 / 255)) i = i.point(lambda i: i * (1 / 255))