Skip to main content

heic2png

Test PyPI Python License: MIT

Turn iPhone HEIC photos into PNG (or JPEG) from the command line or from Python. heic2png converts a file and puts the result next to it, or works as a filter in a shell pipe. Transparency is kept, and nothing needs compiling: it is a small wrapper around Pillow and pillow-heif that runs anywhere Python 3.8 or newer does.

Install

pip install heic2png

Quick start

heic2png -i photo.heic                       # writes photo.png next to photo.heic
heic2png -i photo.heic -q 100 -o full.png    # keeps every color (see below)
from heic2png import HEIC2PNG

HEIC2PNG("photo.heic", quality=100).save()   # writes photo.png

About quality

The command uses quality 80 by default. For PNG output, any quality below 100 turns the picture into a palette image of at most 256 colors (quality × 2.56). That roughly halves the file size, but a photo loses color detail. Here is the same 2× crop of the sample photo in tests/, converted both ways:

Side-by-side crop: with -q 100 the ceiling lights stay yellow and the red sculpture is smooth; with the default -q 80 the lights turn grey and the red becomes grainy.

Command Output Colors Size
(the original HEIC) 2.4 MB
heic2png -i photo.heic -q 100 PNG all 155,763 12.4 MB
heic2png -i photo.heic PNG 204 6.5 MB
heic2png -i photo.heic -q 30 PNG 76 4.8 MB
heic2png -i photo.heic -f jpg JPEG all 2.1 MB
  • To keep every color, use -q 100.
  • For a small file, use -f jpg. JPEG keeps all colors and is smaller than any palette PNG for photos; for JPEG, -q is the usual JPEG quality.
  • In Python, HEIC2PNG(path) keeps every color by default; pass quality= to reduce them.

Command line

usage: heic2png [-h] [-i INPUT_PATH] [-o OUTPUT_PATH] [-q QUALITY]
                [-f {png,jpg,jpeg}] [-w] [--quiet] [-v] [--version]
Option What it does Default
-i
--input-path
Image to convert: .heic, .jpg, .jpeg or .png read stdin
-o
--output-path
Where to write the result (stdout when reading stdin) next to the input
-q
--quality
Quality from 1 to 100, see About quality 80
-f
--format
Output format: png, jpg or jpeg png
-w
--overwrite
Replace the output file if it exists off
--quiet Print errors only off
-v
--verbose
Also print the settings used off
-h
--version
Print the help or the version

-f decides the format, not the file name: write -f jpg -o photo.jpg, because -o photo.jpg alone still writes PNG data.

heic2png -i photo.heic -o out.png                   # pick the output path
heic2png -i photo.heic -f jpg                       # writes photo.jpg
for f in *.heic; do heic2png -i "$f" -q 100; done   # every .heic in the folder
heic2png -i photo.heic -w                           # photo.png exists now: -w replaces it

Progress messages and errors go to stderr. With -v you see what will happen:

$ heic2png -i photo.heic -v
Converting image...
Conversion settings:
Input: photo.heic
Output: photo.png
Quality: 80
Format: png
Overwrite: False
Successfully saved converted image to: photo.png

The command exits with 0 on success, 1 when the conversion fails (for example heic2png: error: Input file not found: photo.heic), 2 for invalid options and 130 on Ctrl+C.

Pipes: stdin and stdout

Without -i, heic2png reads the image from stdin; without -o, it then writes to stdout. In this mode it prints nothing except errors, so stdout carries only image data.

cat photo.heic | heic2png > photo.png      # pipe in, pipe out
heic2png < photo.heic > photo.png          # the same with redirects
cat photo.heic | heic2png -o copy.png      # pipe in, write a file
cat photo.heic | heic2png -f jpg -q 90 > photo.jpg

# straight from the web
curl -sL https://github.com/NatLee/heic2png/raw/main/tests/calder-flamingo.heic \
  | heic2png -q 100 > flamingo.png

Python API

from heic2png import HEIC2PNG

converter = HEIC2PNG("photo.heic", quality=100)
converter.save()                                 # photo.png next to the input
converter.save("copy.png")                       # a path of your choice
converter.save("photo.jpg", extension=".jpg")    # JPEG

HEIC2PNG(image_file_path="", quality=None, overwrite=False) opens the image.

  • image_file_path: a path (str or Path) to a .heic, .jpg, .jpeg or .png file, a binary file object such as io.BytesIO, or "" to read stdin.
  • quality: None (the default) keeps every color. 1–99 reduces PNG output to a palette of quality × 2.56 colors; 100 keeps every color. For JPEG output it is the JPEG quality (None means 95).
  • overwrite: whether save() may replace an existing file.
  • Raises FileNotFoundError for a missing file, ValueError for a bad quality or file type, and OSError if the data is not an image it can read.

save(output_image_file_path=None, extension=".png") converts and writes the image, and returns the path it wrote.

  • output_image_file_path: where to write. If left out, the result goes next to the input file with the new extension, or to stdout when the input was stdin or a file object.
  • extension: ".png", ".jpg" or ".jpeg" (the dot is optional).
  • Raises FileExistsError if the file exists and overwrite is off, ValueError for an unsupported format, and OSError if writing fails.

The opened Pillow image is available as converter.image if you need it.

Converting bytes you already have in memory, such as an upload:

import io
from pathlib import Path
from heic2png import HEIC2PNG

data = Path("photo.heic").read_bytes()
HEIC2PNG(io.BytesIO(data), quality=100).save("upload.png")

Development

git clone https://github.com/NatLee/heic2png.git
cd heic2png
pip install -e ".[test]"   # the package plus pytest
pytest tests               # the tests only write to temporary folders
tox -e py                  # what CI runs: check-manifest + the tests

CI runs the tests on Python 3.8 to 3.14.

Thanks

Built on Pillow and pillow-heif; colors are reduced with Image.quantize(). The package layout started from example_pypi_package. The sample photo in tests/ is Alexander Calder's Flamingo in Chicago.

MIT licensed.

Metadata

Release files for HEIC2PNG 1.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for HEIC2PNG 1.2.2
File Size Uploaded Provenance Actions
heic2png-1.2.2.tar.gz 17.0 kB Without provenance Details for heic2png-1.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for HEIC2PNG 1.2.2
File Interpreter ABI Platform Actions
heic2png-1.2.2-py3-none-any.whl Python 3 none any Details for heic2png-1.2.2-py3-none-any.whl

Total release size: 28.6 kB

Release files / heic2png-1.2.2.tar.gz

Download URL heic2png-1.2.2.tar.gz
Size 17.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4fe3cce4a5a3af407062f82ee19e5be15f1d242a5b2f8fc0eefefef618fd8296
BLAKE2b-256 checksum
How to use checksums
822d704a73977a0629ed816ee0042d36511636e9552ea4040defc2ff89db2292
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.1

Release files / heic2png-1.2.2-py3-none-any.whl

Download URL heic2png-1.2.2-py3-none-any.whl
Size 11.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9e7541ec0f8346850d3c9372c43364c1272d50ed53a3661deb4e6b1f10e974af
BLAKE2b-256 checksum
How to use checksums
e36bacc5b858b9da51ef0f206838cf4cf6aa8367b8400728c4264b64629fc843
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.15.1

Security for HEIC2PNG 1.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page