ffmpegopenexr

ffmpeg cannot write single-channel float32 exr image?


I am trying to use ffmpeg to write an EXR image containing a single channel of float32 values. Here is the code:

def test_ffmpeg_float_gray_to_exr():
  import numpy as np
  import subprocess

  array1 = np.array([[0.1, 0.2], [0.4, 0.7]], np.float32)  # Single-channel 2x2 image.
  array1.tofile('temp1.raw')
  ffmpeg_command_write = [
      'ffmpeg', '-hide_banner',
      '-f', 'rawvideo',
      '-pix_fmt', 'grayf32le',
      '-s', '2x2',
      '-i', 'temp1.raw',
      '-pix_fmt', 'grayf32le',
      '-compression', 'zip1',  # ['none', 'rle', 'zip1', zip16']
      '-format', 'float',  # ['half', 'float']
      '-vcodec', 'exr',
      '-y', 'output.exr',
  ]
  subprocess.run(ffmpeg_command_write, check=True)

  ffmpeg_command_read = [
      'ffmpeg', '-hide_banner',
      '-i', 'output.exr',
      '-f', 'image2pipe',
      '-pix_fmt', 'grayf32le',
      '-y', 'temp2.raw',
  ]
  subprocess.run(ffmpeg_command_read, check=True)
  array2 = np.fromfile('temp2.raw', dtype=np.float32).reshape(2, 2)
  print(array2)

test_ffmpeg_float_gray_to_exr()

When writing, ffmpeg gives the message Incompatible pixel format 'grayf32le' for codec 'exr', auto-selecting format 'gbrpf32le' and then reading back the values gives incorrect results.

If I create a single-channel exr image (using OpenCV), it does read correctly using the ffmpeg_command_read command in the above code, so only the writing part is broken.

And, I am able to create 3-channel (gbrpf32le) and 4-channel (gbrapf32le) exr images using ffmpeg and variants of the above code. Just not 1-channel.

The source code https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/exrenc.c suggests that it should be possible to encode grayf32le (but I'm no expert).

Am I missing some command-line option to enable this?


Solution

  • grayf32le support in exr encode is available since v5.1