ComfyUI icon indicating copy to clipboard operation
ComfyUI copied to clipboard

HDR Images Error: Image file is truncated

Open ckao10301 opened this issue 1 year ago • 5 comments

Error message below when doing image to image:

Reproduce:

  1. Use attached image in "Load Image" node. Sample workflow attached. IMG_0666

  2. Run

  3. Error shows

Error occurred when executing LoadImage:

image file is truncated (0 bytes not processed)

File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\ComfyUI\execution.py", line 155, in recursive_execute output_data, output_ui = get_output_data(obj, input_data_all) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\ComfyUI\execution.py", line 85, in get_output_data return_values = map_node_over_list(obj, input_data_all, obj.FUNCTION, allow_interrupt=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\ComfyUI\execution.py", line 78, in map_node_over_list results.append(getattr(obj, func)(**slice_dict(input_data_all, i))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\ComfyUI\nodes.py", line 1473, in load_image i = ImageOps.exif_transpose(i) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\python_embeded\Lib\site-packages\PIL\ImageOps.py", line 602, in exif_transpose transposed_image = image.transpose(method) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\python_embeded\Lib\site-packages\PIL\Image.py", line 2810, in transpose self.load() File "C:\Users\ckao1\OneDrive\Desktop\stable swarm\StableSwarmUI\dlbackend\comfy\python_embeded\Lib\site-packages\PIL\ImageFile.py", line 266, in load raise OSError(msg) sdxlimage2imageworkflow.json

ckao10301 avatar Jan 31 '24 06:01 ckao10301

I got a similar issue today and although I do not have a direct solution but here is what I found in the hope it could help.

Short answer: Open your file with an image manipulation tool (gimp for example) and export it, you should be able to use it now.

Long answer:

The problem lies in this code from LoadImage in node.py in the code:

        for i in ImageSequence.Iterator(img):
            i = ImageOps.exif_transpose(i)
            if i.mode == 'I':
                i = i.point(lambda i: i * (1 / 255))

When an HDR image is saved, the jpg file contains on top of the photo a gain map smaller than the image itself. You can check if this exists using tools for examining exif data on your image. For my example image with exiftool exiftool test.jpg will show this:

MPF Version                     : 0100
Number Of Images                : 2
MP Image Flags                  : (none)
MP Image Format                 : JPEG
MP Image Type                   : Undefined
MP Image Length                 : 98010
MP Image Start                  : 2862294
Dependent Image 1 Entry Number  : 0
Dependent Image 2 Entry Number  : 0
Image Width                     : 3072
Image Height                    : 4080
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Hdr Plus Makernote              : (Binary data 68736 bytes, use -b option to extract)

Back to our problematic code snippet, the ImageSequence.Iterator will try to give you two images since two are contained in the file without properly handling the size difference between the two images (the gain map is smaller than the original image). There is an option for Pillow to ignore truncated files, which makes you able to visualize this gain map with the following code snippet:

from PIL import ImageFile, Image, ImageSequence
ImageFile.LOAD_TRUNCATED_IMAGES = True

image = Image.open("test.jpg")
print(f"{image.format = }")
idx = 0
for i in ImageSequence.Iterator(image):
    print(f"{i.size = }\n{i.mode = }\n")
    try:
        i.save(f"{idx}.jpg")
        idx += 1
    except: 
        pass

You can note in the output here that the format is indeed MPO instead of jpg as the extension suggests, and here is the result:

image

Now this might allow you to either prevent this kind of file to be loaded by detecting and fixing it through code (in a custom node or preprocessing) but I am not certain how to graciously handle this in comfyui itself.

thjan avatar Feb 21 '24 22:02 thjan

@thjan thanks for the great write up. I hope that comfy can provide an update to handle HDR images, but for now I will do a manual conversion before.

ckao10301 avatar Mar 04 '24 21:03 ckao10301

Great explanation @thjan, I am also running into this issue on https://github.com/fofr/cog-face-to-many.

fofr avatar Mar 07 '24 13:03 fofr

The reason is that the pic size is so big exceeding the PIL limination. You can trigger the same error using the following code:

from PIL import Image, ImageOps, ImageSequence

img = Image.open(image_path)
for i in ImageSequence.Iterator(img):
    ImageOps.exif_transpose(i)

How to address it? The simple way is reducing the pic size. https://github.com/fofr/cog-face-to-many/issues/1

time-river avatar Mar 21 '24 02:03 time-river

@time-river if you mean file size (MB), I don't see that as the cause. This file is 3MB, and I don't have problems with other images up to 20 MB. I think conversion is the best answer for now

ckao10301 avatar Apr 08 '24 07:04 ckao10301