Imager::File::HEIF - read and write HEIF files


  use Imager;
  # you need to explicitly load it, or supply a type => "heif" parameter
  use Imager::File::HEIF;

  my $img = Imager->new;
    or die $img->errstr;

  # type won't be necessary if the extension is heif from Imager 1.008
  $img->write(file => "foo.heif", type => "heif")
    or die $img->errstr;


Implements .heif file support for Imager.


  • Due to the limitations of heif (or possibly libheif) grayscale images are written as RGB images.

  • libx265 will reject attempts to write images smaller than 64x64 pixels. Since this may change in the future I haven't tried to prevent that in Imager itself.

  • Imager's images are always RGB or grayscale images, and libheif will re-encode the RGB data Imager provides to YCbCr for output. This inevitably loses some information, and I've seen one complaint that libheif's conversion isn't as good as it could be. Grayscale images (which are still passed through as RGB) seem to be supported with very good quality. YMMV.


The h.265 compression libheif uses is covered by patents, if you use this code for commercial purposes you may need to license those patents.


To install Imager::File::HEIF you need Imager installed and you need libheif, libde265 and libx265 and their development files.

Development of Imager::File::HEIF was done with the latest development versions of libheif and libde265 at the time ie from git, older releases might fail to build or run.


You can control compression through two tags (implicityly set on the images via write() or write_multi()):

  • heif_lossless - if this is non-zero the image is compressed in "lossless" mode. Note that in both lossy and lossless modes the image is converted from the RGB colorspace to the YCbCr colorspace, which will lose information. If non-zero the heif_quality value is ignored (and irrelevant.) Default: 0 (lossy compression is used.)

  • heif_quality - a value from 0 to 100 representing the quality of lossy compression. Default: 80.

WARNING: from my testing, using the rough measure done by Imager i_img_diff(), lossy at 80 quality turned out closer to the original image than lossless.


  • can we hack grayscale by setting the chroma bits to zero? The sample code produces a chroma bits 8 image when given a grayscale input PNG, which is why I suspect the format doesn't support gray, but they might be a deficiency in the tool. I tried just adding a Y channel for grayscale, but that simply made the encoding step crash.

    The heif_enc sample creates a YCbCr image and only adds a Y plane.

  • 10-bit/sample and 12-bit/sample images. Based on this might not be supported completely yet.

  • reading metadata (any to read?) I think pixel ratios are available. HEIF supports pixel ratios via the PixelAspectRatioBox pasp member of ItemPropertyContainerBox 'ipco' but libheif doesn't appear to support that.

  • writing metadata. We don't seem to have the animation metadata that webp does.

  • reading sub-image data? we can probably skip thumbs (or provide an option to read the thumb rather than the main image), but are there other images to read? Depth images. Low priority.

  • writing sub-image data? thumbnails and depth images. Very low priority.

  • Everything else.


Tony Cook <>


Imager, Imager::Files.