HEIC to PNG Converter
Turn iPhone .heic photos into lossless PNG — decoded entirely in your browser, nothing uploaded. Transparency survives, rotated shots come out upright, and every output is verified before download.
Convert HEIC files to PNG
Drop one or many .heic or .heif files. Each converted PNG is re-decoded and verified before its download button appears.
The lane that loads a decoder
Every other converter on this site decodes with the browser's own codecs; HEIC is the
exception, because no browser ships a HEIC decoder. What this lane does about it is specific:
this page and HEIC to JPG load libheif — © struktur
AG and contributors, licensed LGPL-3.0, together with its libde265 HEVC decoder,
also LGPL — as a separately replaceable module, a script plus a .wasm file under
/vendor/libheif/, fetched from this site's own origin, never compiled into the
site's own JavaScript, and run in a dedicated worker. The build is decode-only, and the full
licence text ships beside the module at
/vendor/libheif/LICENSE.txt. The rest of the
attribution — the pinned upstream source compiled without modification, the size and SHA-256
pinned for every vendored file, and the reason for carrying a third-party decoder at all — is
stated once on the methodology page and set beside AVIF in the guide
below, rather than repeated here.
The module is fetched from this site, your photo is decoded inside a worker in your own tab, and from there the lane is the same as every other converter here: the decoded pixels are drawn to a canvas and written out by the browser's own PNG encoder. The engine lists HEIC among its decodable formats (PNG, JPEG, WebP, GIF, BMP, HEIC, AVIF) — asked whether HEIC is decodable, it answers yes — and on its source-only list (GIF, BMP, HEIC), the formats it reads but never writes. That second answer, yes, is why this page exists in one direction only.
Guide: HEIC and AVIF: decoding and licensing. This page shows what the HEIC to PNG lane decides for a file; the guide sets the two HEIF siblings
side by side — what the ftyp box parser reads, why the HEIC pages load a decoder
and the AVIF pages do not, why the site encodes AVIF but never HEIC, and how every vendored file
is pinned by size and SHA-256. Read it when the question is about the container rather than this
conversion.
What the detector sees in a .heic file
The first thing the tool does with a file is read its leading bytes. PNG, JPEG, WebP, GIF and
BMP announce themselves with fixed signatures; HEIC does not. It is an ISO-BMFF container, and
what sits at the front is an ftyp box: four bytes of size, the ASCII
ftyp, a four-character major brand, four bytes of minor version, then compatible
brands four characters each to the end of the box. The detector parses that structure — major
and compatible brands read from the box, bounded by the declared box size, never by
substring-searching the file. The declared size is clamped to the bytes actually present, a
box too small to hold a major brand is rejected outright, and a brand that is not printable
ASCII stops the read. A file is HEIC when the list carries one of the brands the methodology
page names — heic, heix, hevc, hevx,
mif1, msf1 — and an explicitly HEVC-coded brand wins even when an AVIF
brand sits beside it. Every verdict in the table was produced at build time on bytes constructed
from the description shown.
| Constructed input | Brands the parser read | Detected as |
|---|---|---|
| major heic; compatibles mif1, heic |
heic mif1 heic
|
HEIC |
| major mif1; compatibles mif1, heic |
mif1 mif1 heic
|
HEIC |
| major heix; compatibles mif1, heix |
heix mif1 heix
|
HEIC |
| major mif1; compatibles mif1 only |
mif1 mif1
|
HEIC |
| major mif1; compatibles heic, avif |
mif1 heic avif
|
HEIC |
| major avif; compatibles avif, mif1, miaf |
avif avif mif1 miaf
|
AVIF |
| major heic, but the box declares a size of 8 |
no ftyp box read
|
unrecognized |
| major heic, but the box declares a size of 15 |
no ftyp box read
|
unrecognized |
| major heic, and the box declares a size of 16 |
heic
|
HEIC |
| major heic, but the box declares the largest 32-bit size |
heic mif1 heic
|
HEIC |
| the first 11 bytes of the first box |
no ftyp box read
|
unrecognized |
| 12 bytes opening FF D8 FF, named .heic |
no ftyp box read
|
JPEG |
Reading the rows: the major brand need not be a codec brand. A box led by mif1 with
heic among its compatibles is HEIC, and so is the box that lists
mif1 alone, because mif1 and msf1 sit on the detector's HEIC
brand list and nothing in that box says AVIF. The mixed box listing both
heic and avif is HEIC, by precedence. The AVIF still is
AVIF — drop one here and the row refuses it as AVIF rather than
HEIC and points you to AVIF to PNG, since a page
built for one source format does not quietly accept another. The box declaring eight bytes is
unrecognized: too small to be a real ftyp box, so the parser rejects it before
reading a brand. Where that floor sits was found by asking the parser, not typed: the same box declared
at 15 bytes is unrecognized (no ftyp box read), and declared at 16 bytes it is HEIC, the parser reading heic — the major
brand alone, because the declared size ends the box before the compatibles. The box declaring the
largest possible 32-bit size is still
HEIC, because the read is clamped to the data edge rather than following the
header. The 11-byte slice is unrecognized — too short to be a box at all. And the
12 bytes that open with FF D8 FF are JPEG whatever name
they carry: JPEG's fixed signature matched first, and the box parser was never consulted.
Names are compared, not trusted. After detection the filename's extension is checked
against the verdict; the extension map reads .heic and .heif
as claims of HEIC. On an invented IMG_0427.heic wrapped around the first box, the check
reports a mismatch of no; named IMG_0427.heif, the claim is
HEIC and the mismatch is still no. The same bytes named
IMG_0427.jpg are detected as HEIC while the name claims
JPEG, mismatch yes: the row says so, the conversion runs from the
actual
HEIC content, and the download is named IMG_0427.png. Named
IMG_0427.png, the claim is PNG, the mismatch is yes, and
the download is IMG_0427-converted.png — a suffix, because IMG_0427.png would
otherwise shadow the file you dropped. The reverse case, JPEG bytes named
IMG_0427.heic, reports actual JPEG, claimed HEIC, mismatch yes; this page refuses it as JPEG and points to
JPG to PNG, because the planner is never asked to convert from a
format the page was not built for.
What the plan decides for HEIC to PNG
Before any pixel moves, a pure planning module takes the detected source and the target and returns a plan. For this pair, computed at build time by the same function the tool calls on your file:
-
Encoded as
image/png, the MIME type handed to the browser's encoder; the download carries the.pngextension. -
Flatten over a background:
no. The engine treats PNG, WebP, GIF, BMP, HEIC, AVIF as sources that may carry transparency — a
HEIF image can carry an alpha auxiliary plane — but the capability table says PNG
holds alpha, so the flag is off, no colour is asked for and none is composited. The
plan still records its default of
#ffffff, and never uses it. - Quality: none. PNG is lossless in the capability table, so the plan carries no quality and the page shows no slider.
- First frame only: no. The sources whose plans raise that caveat are WebP, GIF, AVIF; HEIC is not among them, so no first-frame note is planned for this lane. What a HEIC container can hold is several top-level images: the primary image is the one decoded, and the row reports how many others it found.
The planner refuses rather than guesses, and it validates before it decides. Asked for this
conversion with an invented quality of 0.8 on its 0–1 scale, it returns "This output format is lossless and has no quality setting.". Asked for it with the background written as white instead of a hex colour, it returns
"Enter the background as a hex color like #ffffff." — even though this plan will never composite anything, an input the
planner cannot read is an error, not a default. The contrast with the JPEG lane is two fields:
the same HEIC source planned to JPEG sets flatten to yes and carries the JPEG default
of
92 on the encoder's 0–100 scale. Those two differences
are why
HEIC to JPG asks for a background colour and a quality, and this page
asks for neither.
The encoder: the browser's own PNG writer
PNG output on this lane is written by the browser's PNG encoder through the canvas — one of
the three browser encoders the methodology page lists beside the two self-hosted ones. The
plan passes image/png and no quality parameter; there is nothing to tune and nothing
to vendor on the encoding side. The only third-party code that touches your pixels is the libheif
module, with its libde265 decoder, and it runs before the canvas: it produces the decoded image,
hands it over, and the browser does the rest.
What a lossless target means mechanically: the encoder stores the pixels exactly as the canvas holds them, alpha included, so a PNG written here can be re-saved later without adding a further generation of loss. What it cannot do is reach behind the decode. The PNG is a faithful copy of the picture as libheif decoded it, not of the scene the camera saw: whatever the HEVC coding inside the HEIC discarded, if it discarded anything, stays discarded. The conversion preserves; it does not restore.
The direction is fixed. The engine's producible formats are PNG, JPEG, WebP, AVIF; the type that names a conversion target excludes HEIC, and HEIC sits on the source-only list (GIF, BMP, HEIC). The methodology page states the reason: HEIC's HEVC codec is covered by commercial patent pools, which is why browsers do not ship HEVC encoders and why this site's libheif build is decode-only — producing HEIC files would require licensing terms that a free, in-browser tool cannot honestly satisfy. Conversions here go from HEIC, never to it.
Filenames: stem kept, extension swapped
The output name keeps your stem and swaps in the target's canonical extension,
png. Computed at build time on invented names:
IMG_0427.HEIC becomes IMG_0427.png and IMG_0427.heic
becomes IMG_0427.png, the stem's case untouched either way;
kitchen.before.heic becomes kitchen.before.png, because only the last dot
marks the extension; a file with no extension at all, scan, becomes
scan.png; and a path such as Camera Roll/IMG_0427.heic is reduced to
its final segment, IMG_0427.png. The only time a suffix appears is when the name
would not change — the misnamed IMG_0427.png above, which becomes
IMG_0427-converted.png.
What re-encoding strips
Canvas re-encoding strips all embedded metadata: EXIF (including GPS location, camera model and timestamps), colour-profile tags and text chunks. The methodology page presents this as both a feature and a caveat, because it is both — a converted photo cannot leak where it was taken, and equally, copyright fields and ICC profiles are gone, so originals should be kept. Orientation is applied during decoding, before metadata is discarded, so uprightness survives even though the orientation tag does not: the rotation a HEIC stores as a container transform is applied by the decoder as the pixels are produced, which is why a photo shot sideways comes out upright and a sideways PNG is not possible from this lane. One more thing does not cross over: the other images a container may hold are counted on the row, and the PNG carries only the primary image. The full account is in what re-encoding does to metadata.
How the output is verified
A download button on this page means the output has already been checked. The produced bytes
are sniffed with the same detector applied to inputs — this lane must yield bytes the detector
classifies as PNG, image/png behind a
.png extension — so a browser silently substituting another format
is reported as an error, never handed to you as a mislabelled file. The blob is then re-decoded
and its pixel dimensions compared with the canvas that was drawn; a disagreement is an error, not
a rounding note. Only then does the row show the verified format, the verified dimensions, and the
output's true byte count beside the input's. The input limits are the methodology page's: inputs
are limited to 50 megapixels, 100 MB per file, and 40 files or 300 MB per selection.
The percentage on a row is computed from those two measured byte counts for your file and nothing else. To show the wording without implying an expectation, here is the engine's arithmetic on invented counts: 1,800,000 bytes before and 14,400,000 after reads "700% larger — keep your original"; 2,000,000 before and 2,150,000 after reads "7.5% larger — keep your original", one decimal because the change is under ten percent; 6,400,000 before and 5,900,000 after reads "7.8% smaller"; identical counts of 3,000,000 read "same size". None of these is a measurement of any real file. The site publishes no blanket compression percentages, because no percentage is true for every image — and a lossless landing can grow, in which case the row says "larger — keep your original" in the same breath as the number.
What the tool cannot know
- Whether the HEVC coding inside your HEIC discarded detail, or how much. The PNG preserves the image as it decodes; nothing on this page measures or judges picture quality.
- Whether an alpha plane, if the file has one, covers anything. The flatten flag is no regardless, the pixels come through as decoded, and an opaque photo simply has nothing transparent to preserve.
- What the other images in a container are. They are counted, not inspected; only the primary image is decoded.
- Whether the result is right for its destination. The row reports a verified format, verified dimensions and a measured byte count; whether an editor, a form or a workflow will accept the file is not something the detector can read.
- Your intent for a file whose box says AVIF or whose bytes say JPEG. The detector reports what it reads, and the row sends the file to the lane built for it rather than decoding it here.
Common misreadings
- "Lossless means the photo is restored." Lossless describes what the encoder adds — nothing — not what the HEIC's own compression already discarded. The PNG preserves the picture as decoded.
- "The PNG will be so many times larger." The site states no percentage in advance. The row measures your file and uses the engine's wording — "700% larger — keep your original" on one invented pair, "7.8% smaller" on another — whichever the bytes dictate.
- "There is a quality setting I am missing." There is not. The planner's answer to a quality on this lane is "This output format is lossless and has no quality setting."
-
"A file named .heic is HEIC." The 12 bytes opening
FF D8 FFabove are JPEG by content, and that is what the row reports. -
"The decoder is part of the site's JavaScript." It is a separately replaceable
module under
/vendor/libheif/with its licence text beside it, fetched from this site, pinned by size and SHA-256, and never compiled into the page's own code. - "Converting to PNG keeps the photo's metadata." Canvas re-encoding strips it — EXIF including GPS, colour-profile tags, text chunks. Orientation is applied before the discard; nothing else carries over.
- "There must be a PNG to HEIC tool somewhere." HEIC is source-only (GIF, BMP, HEIC) and excluded from the target type; the producible formats are PNG, JPEG, WebP, AVIF, and the reason is licensing.
- "Only the first frame of my HEIC was converted." The first-frame flag on this plan is no; that caveat belongs to WebP, GIF, AVIF. The HEIC note on a row is about other images in the container, and it says the primary image was the one converted.
Related tools
Want a smaller, lossy photo instead of a lossless one? HEIC to JPG plans a flatten over a colour you choose and takes a quality. A PNG that came out large can be scaled down with the Image Resizer or re-encoded to a lossy format by the Image Compressor. Going from PNG onward, see PNG to JPG and PNG to WebP. The container questions — brands, decoders, licences — are in HEIC and AVIF: decoding and licensing; the other guides cover detection, the pipeline, and what re-encoding strips.
Frequently asked questions
When is PNG the right target for a HEIC — instead of JPG?
When the picture must come through exactly as it decoded, transparency included, or when it will be edited and re-saved. The engine's capability table marks PNG as lossless and says it holds alpha, so the plan for this pair sets flatten to no and quality to none; the same HEIC planned to JPEG sets flatten to yes and takes a quality. When a destination needs a smaller file and can accept a lossy re-encode, the HEIC to JPG converter is the other lane — the row on either page shows the measured byte counts.
Is the PNG conversion lossless?
The PNG encoding step is lossless: every pixel libheif produces is stored exactly, alpha channel included, because PNG is lossless in the engine's capability table. The HEIC itself was already compressed by its HEVC coding, so the PNG faithfully preserves the image as it decodes — it cannot restore detail the HEIC never kept.
Why is the PNG so much bigger than the HEIC?
A lossless landing stores every decoded pixel, so it can grow — but the site states no percentage in advance, because no percentage is true for every image. The row reports the two measured byte counts for your file and the engine's wording for their difference: on invented counts of 1,800,000 before and 14,400,000 after it reads “700% larger — keep your original”. That is arithmetic on invented numbers, not a forecast; whatever your file measures is what the row shows.
Does my photo get uploaded to a server for decoding?
No. Browsers cannot decode HEIC natively, so this page loads the libheif decoder (compiled to WebAssembly) from this site into a worker in your own tab and decodes there. The site’s security policy blocks requests to other origins — verifiable in your browser’s DevTools network panel.
What about Live Photos and bursts?
A HEIC container can hold several images. The primary image — the still your camera roll shows — is converted, and the file row tells you when additional images were detected in the container. This is a count of images, not an animation: the plan’s first-frame flag for a HEIC source is no.
Is transparency kept?
Yes. HEIC can carry an alpha channel and PNG holds alpha, so the plan for this pair sets its flatten flag to no: transparent and semi-transparent areas convert as they decoded, no background colour is asked for, and none is composited. Most camera photos are fully opaque, in which case there is simply nothing to flatten.
Why is there no quality slider on this page?
Because the planner refuses one. Asked to plan this conversion with an invented quality of 0.8 on its 0–1 scale, the engine returns “This output format is lossless and has no quality setting.” — PNG is lossless, the plan’s quality field is none, and the browser’s PNG encoder is given no parameter to tune.
My file is named .jpg but the row says it is HEIC. What happens?
The tool reads the file’s leading bytes and compares them with the name. An invented IMG_0427.jpg whose bytes open with a HEIC ftyp box is detected as HEIC while the name claims JPEG; the row states the mismatch, converts from the actual HEIC content, and names the download IMG_0427.png. The reverse — JPEG bytes named .heic — is refused here as JPEG and pointed to the JPG to PNG converter.
Local processing: your photos are decoded, converted, and verified inside your browser and never transmitted. HEIC decoding by libheif, LGPL-3.0, self-hosted and used unmodified — see the methodology page for the full attribution and how to verify the no-upload claim yourself.