Converting a JPEG to the new HEIF format

HEIF is a new container format developed by the MPEG group. HEIF files can contain images and image sequences (e.g: iPhone "live" photos, "burst" photos, or multi-exposure shots), and encode data using the same HEVC (High Efficiency Video Coding) standard used by H265 video.

Feb 2020 Update: There is now a free service at FreeConvert.com for converting HEIC/HEIF images to JPG! On macOS Catalina, you can also use Preview to open HEIC files from an iPhone and use File > Export... to convert them to another format.

Why use HEIF?

Why (maybe) not use HEIF?

Step by Step

Note: This tutorial assumes you have macOS, Homebrew, Git, cmake, and about 5 minutes to spare. Just want a HEIF image? Download a sample.

Step 1: Install x265

brew install x265

Step 2: Download FFMPEG and build it with the --enable-x265 extension

brew uninstall ffmpeg
brew install ffmpeg --with-x265

Step 3: Download and build the HEIF Sample Implementation

git clone https://github.com/nokiatech/heif.git
cd heif
cmake .
make install

Step 4: Use FFMPEG to convert a JPEG to a HVEC bytestream

IMPORTANT: You must use an image with even width and height values (eg: 2042 not 2041) at the moment. The reference implementation will not display images with odd sizes.

ffmpeg -i ./your-image.jpg -crf 12 -preset slower -pix_fmt yuv420p \
  -f hevc bitstream.265

ffmpeg -i ./your-image.jpg -vf scale=320:240 -crf 28 -preset slower \
  -pix_fmt yuv420p -f hevc bitstream.thumb.265

Step 5: Create a config.json file

This file is required for the reference implementation of HEIF to build a HEIF file. It's necessary because HEIF supports many types of images + thumbnail combinations, sequences, images with transforms applied, etc.

I don't know much about the available options. There is no documentation and I derived these options by reading the source code that parses the JSON.

{
	"general": {
		"output": {
			"file_path": "output.heic"
		},
		"brands": {
			"major": "mif1",
			"other": ["mif1", "heic", "hevc"]
		}
	},
	"content": [{
		"master": {
			"file_path": "./path-to/bitstream.265",
			"hdlr_type": "pict",
			"code_type": "hvc1",
			"encp_type": "meta"
		},
		"thumbs": [{
			"file_path": "./path-to/bitstream.thumb.265",
			"hdlr_type": "pict",
			"code_type": "hvc1",
			"encp_type": "meta",
			"sync_rate": 1
		}]
	}]
}

Step 6: Build your HEIF file!

./Bins/writerapp ./path/to/config.json

That's all it takes! Pretty cool huh? Except... what do you do with it now? Right now, it's only possible to view HEIF files using the JavaScript viewer built in to the reference implementation on GitHub. And it's a totally bananas 1.4MB of JavaScript compiled from C++ with Emscripten.

To make testing HEIF easier, I've adapted the reference implementation to run on file blobs. View your HEIF image below by selecting it in the file picker.

Happy hacking!

- Ben Gotow (GitHub, Twitter)