AcademySoftwareFoundation / openexr

The OpenEXR project provides the specification and reference implementation of the EXR file format, the professional-grade image storage format of the motion picture industry.
http://www.openexr.com/
BSD 3-Clause "New" or "Revised" License
1.62k stars 608 forks source link

OpenEXR.OutputFile Fails to Write to BytesIO Buffer #1758

Open shiukaheng opened 3 months ago

shiukaheng commented 3 months ago

Description:

I encountered an issue when trying to use OpenEXR.OutputFile to write to a BytesIO buffer. The operation fails with the following error: OSError: Cannot open image file "". file write failed. It appears that OpenEXR.OutputFile does not handle in-memory buffers as expected.

Steps to Reproduce:

  1. Install OpenEXR and dependencies.
  2. Run the following Python code:

    from io import BytesIO
    import OpenEXR
    import Imath
    import numpy as np
    
    def encode_exr(image: np.array) -> bytes:
        width, height, _ = image.shape
        header = OpenEXR.Header(width, height)
        header['channels'] = {
            'R': Imath.Channel(Imath.PixelType(Imath.PixelType.FLOAT)),
            'G': Imath.Channel(Imath.PixelType(Imath.PixelType.FLOAT)),
            'B': Imath.Channel(Imath.PixelType(Imath.PixelType.FLOAT))
        }
        header['compression'] = Imath.Compression(Imath.Compression.DWAA_COMPRESSION)
    
        data_r = image[:, :, 0].tobytes()
        data_g = image[:, :, 1].tobytes()
        data_b = image[:, :, 2].tobytes()
    
        buffer = BytesIO()
        exr = OpenEXR.OutputFile(buffer, header)
        exr.writePixels({'R': data_r, 'G': data_g, 'B': data_b})
        exr.close()
    
        return buffer.getvalue()
    
    if __name__ == '__main__':
        random_image = np.random.rand(720, 1280, 3).astype(np.float32)
        exr_bytes = encode_exr(random_image)
  3. Which gives the following error
    Traceback (most recent call last):
      File "script.py", line 30, in <module>
        exr_bytes = encode_exr(random_image)
                    ^^^^^^^^^^^^^^^^^^^^^^^^
      File "script.py", line 22, in encode_exr
        exr = OpenEXR.OutputFile(buffer, header)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    OSError: Cannot open image file "". file write failed

Expected Behavior:

OpenEXR.OutputFile should support writing to a BytesIO buffer without raising an error.

I am not very C++ savvy but it seems that the C++ implementation and the python wrapper would handle a byte stream for image writing? Especially when reading from a byte stream is supported.

Appreciate any help. Thanks!

Environment:

cary-ilm commented 3 months ago

You're right, the current python bindings only support file I/O, even though the underlying library supports streams.

I'm in the process of entirely rewriting the bindings (#1756), I can add support for byte streams.