Make WordPress Core

Opened 4 months ago

Last modified 5 weeks ago

#65297 accepted defect (bug)

HEIC/HEIF MIME Type Mapping Is Inaccurate

Reported by: modi2918 Owned by: modi2918
Priority: normal Milestone: Future Release
Component: Media Version: 6.7
Severity: normal Keywords: has-patch has-unit-tests reporter-feedback
Cc: Focuses:

Description

The MIME type map acknowledges that HEIC, HEIF, HEICS, and HEIFS files are not reliably distinguished by extension:

TODO: Needs improvement. All images with the following mime types seem to
have .heic file extension.
'heic' => 'image/heic',
'heif' => 'image/heif',
'heics' => 'image/heic-sequence',
'heifs' => 'image/heif-sequence',

Additionally, in the validation code, image/heif, image/heic-sequence, and image/heif-sequence files all get their extension normalized to .heic, which is inaccurate for sequence files and HEIF files that use different container types. This can cause upload validation failures and incorrect file extension assignment.

Attachments (3)

bug-heic-heif-analysis.md (11.2 KB ) - added by modi2918 4 months ago.
shelf-christmas-decoration.heic (1.4 MB ) - added by modi2918 3 months ago.
sample1.heif (2.4 MB ) - added by modi2918 3 months ago.

Change History (22)

This ticket was mentioned in PR #11920 on WordPress/wordpress-develop by @mohamedahamed.


4 months ago
#1

  • Keywords has-patch added

## Summary

Fixes inaccurate HEIC/HEIF MIME type mappings. Previously, all HEIF-family uploads (.heif, .heics, .heifs) were incorrectly mapped to and renamed as .heic because the $mime_to_ext array collapsed all variants into the heic extension.

Additionally, this PR fixes two related issues:

  1. .heics and .heifs were missing from the wp_ext2type() image array, causing them not to be recognized as images in the Media Library.
  2. Sub-size generation skipped non-image/heic HEIF variants because of a hardcoded mime type check.

## Changes

### src/wp-includes/functions.php

  • Updated the $mime_to_ext array in wp_check_filetype_and_ext() to map each HEIF MIME type to its proper, distinct extension:
    • image/heif → heif
    • image/heic-sequence → heics
    • image/heif-sequence → heifs
  • Added 'heic' to the $heic_images_extensions trigger array.
  • Added 'heics' and 'heifs' to the image types array in wp_get_ext_types().
  • Removed outdated comments indicating all HEIC/HEIF formats commonly use .heic.

### src/wp-admin/includes/image.php

  • Replaced the explicit 'image/heic' === $mime_type check in wp_generate_attachment_metadata() with a call to wp_is_heic_image_mime_type(). This ensures all HEIF variants (not just image/heic) correctly trigger sub-size generation.

## Testing

Test Result
Upload .heic file ✅ Remains .heic, sub-sizes generated correctly
Upload .heif file ✅ Remains .heif, sub-sizes generated correctly

Trac ticket: https://core.trac.wordpress.org/ticket/65297

## Use of AI Tools

AI assistance: No

#2 @jorbin
4 months ago

  • Component UploadMedia
  • Version6.7

wp_is_heic_image_mime_type was added in 6.7. See [59315]. Setting the component to media since #62272 used that and wp_is_heic_image_mime_type is more of a general media function than upload specific.

#3 @westonruter
3 months ago

  • Owner set to adamsilverstein
  • Status newreviewing

#4 @adamsilverstein
3 months ago

Hi @modi2918 - thanks for the ticket and bug report.

If possible can you provide:

  • A sample image of each type that you want to add support for. This would be helpful for adding tests.
  • Any details about how you created these images or where they are commonly created - eg. how would WordPress users have them and be trying to upload them?

@adamsilverstein commented on PR #11920:


3 months ago
#5

Hi @NoumaanAhamed - Thanks for the PR!

If possible can you provide:

A sample image of each type that you want to add support for. This would be helpful for adding tests.
Any details about how you created these images or where they are commonly created - eg. how would WordPress users have them and be trying to upload them?

#6 @adamsilverstein
3 months ago

  • Keywords needs-unit-tests added

@adamsilverstein commented on PR #11920:


3 months ago
#7

Hi @NoumaanAhamed[[Image(chrome-extension://hgomfjikakokcbkjlfgodhklifiplmpg/images/wp-logo.png)]] - Thanks for the PR!

If possible can you provide:

A sample image of each type that you want to add support for. This would be helpful for adding tests. Any details about how you created these images or where they are commonly created - eg. how would WordPress users have them and be trying to upload them?

The doc block the PR removes even mentions this - is it not accurate?

https://github.com/user-attachments/assets/3d55c957-ee3e-4cce-8560-2de3035f7df1

@modi2918
3 months ago

#8 @modi2918
3 months ago

### Where These File Types Come From in Everyday Use

test-heic.heic — Photos from iPhones

This is by far the most common HEIC file users upload. Apple introduced HEIC as the default photo format with iOS 11, and every iPhone since the iPhone 7 captures photos in this format unless the user changes the camera settings. A typical scenario is someone taking a photo on their iPhone, transferring it to a Mac, and then uploading it to a website or WordPress. These files usually use the heic major brand.

test-heif.heif — Photos from Android Devices

Many Android phones, including Samsung Galaxy and Google Pixel devices, support the HEIF format. Unlike Apple, Android devices generally use the mif1 major brand, which follows the MPEG HEIF specification. Files exported through Samsung Gallery, Google Photos, or other HEIF-compatible applications commonly use this format. This distinction is important because a file may have a .heif extension while still using the mif1 brand rather than heif, causing some file detection methods to miss it and rely on fallback detection mechanisms.

test-heics.heics — Apple Live Photos

Apple Live Photos combine a still image with a short motion clip. When exported, they can be stored as HEVC image sequences using the hevc major brand and typically carry the .heics extension. While less common than standard HEIC photos, users who back up or export their iPhone photo libraries may encounter these files.

test-heifs.heifs — Burst Photos and Image Sequences

Some Android devices and image-processing tools generate HEIF image sequences rather than single images. For example, burst-mode photos may be packaged using the msf1 major brand and saved with a .heifs extension. These files can also be produced by professional imaging software and tools that support the HEIF format, such as applications built on libheif.

@mohamedahamed commented on PR #11920:


3 months ago
#9

Good catch, I've reverted those specific changes. @adamsilverstein

Attached sample files for testing. ( They all should resolve to .heic when uploaded )

heic-files.zip

#10 @adamsilverstein
3 months ago

Thanks for adding the test image and an explanation of image sources. I’ll take a look!

This ticket was mentioned in PR #12352 on WordPress/wordpress-develop by @adamsilverstein.


2 months ago
#11

  • Keywords has-unit-tests added; needs-unit-tests removed

## Summary

Fixes the inaccurate HEIC/HEIF MIME type mapping described in Trac #65297. Previously wp_check_filetype_and_ext() re-validated .heif, .heics, and .heifs uploads and normalized all of them to the .heic extension, so a genuine HEIF still image was silently renamed to .heic.

## Why the obvious fix is wrong

The intuitive fix is to remap image/heif => 'heif' in the $mime_to_ext array. That regresses the most common case. PHP's exif_imagetype() returns IMAGETYPE_HEIF for *both* .heic and .heif files, and image_type_to_mime_type() maps that to image/heif. Because wp_get_image_mime() calls exif_imagetype() first, $real_mime is image/heif for an ordinary iPhone .heic too. Remapping image/heif => heif would therefore rename every .heic upload to .heif. This is exactly why the original code deliberately collapsed everything to .heic.

## The fix

  • src/wp-includes/functions.php — Remove 'heif' from the $heic_images_extensions re-validation list in wp_check_filetype_and_ext(). A genuine .heif then has $real_mime === $type and is never force-rewritten, so it keeps its extension. The image/heif => 'heic' mapping is intentionally kept: it is what keeps an ordinary .heic upload named .heic (where $real_mime !== $type). The sequence types remain collapsed to .heic because GD and Imagick decode only a single frame and cannot process sequences.
  • src/wp-admin/includes/image.php — Use wp_is_heic_image_mime_type() in wp_generate_attachment_metadata() so image/heif attachments still trigger sub-size generation now that they are stored with their own MIME type.
  • Tests — Add unit tests asserting .heic keeps .heic (regression guard) and .heif keeps .heif, guarded to skip on builds without HEIC/HEIF detection.

Sequence support (.heics/.heifs, e.g. Live Photos / burst) is intentionally out of scope here since the server image libraries cannot process multi-frame images; it is being explored separately on the client-side processing path.

## Relationship to #11920

Supersedes #11920, which took the image/heif => heif approach (regressing .heic) and shipped without tests. Props @NoumaanAhamed for the original patch and @modi2918 for the detailed report and sample files.

## Testing

  • phpunit --filter 'check_filetype_and_ext|getimagesize_heic' — 35 tests pass.
  • New .heic/.heif tests pass (not skipped) on a build with HEIC/HEIF detection.
  • wpGenerateAttachmentMetadata tests pass.
  • PHPCS clean on changed files.

Props NoumaanAhamed, modi2918.
Fixes #65297.

## Use of AI Tools

AI assistance: Yes

#12 @adamsilverstein
2 months ago

  • Keywords reporter-feedback added

@modi2918 I posted a potential fix in https://github.com/WordPress/wordpress-develop/pull/12352 - can you see if this resolves your issue?

Also, if you can test the upload in Chrome with Gutenberg enabled, I'm curious if the issue is fixed there (where we have a new media handling pipeline active that is coming to WordPress 7.1).

#13 @modi2918
8 weeks ago

  • Owner changed from adamsilverstein to modi2918
  • Status reviewingaccepted

@adamsilverstein Thanks for the fix — the code logic looks solid to me (keeps .heic uploads as .heic via the existing image/heif → heic mapping, while genuine .heif files now pass through untouched since $real_mime matches $type). I'll run it through the Playground instance and test in Chrome with Gutenberg enabled, and report back with results.

#14 @modi2918
8 weeks ago

  • Milestone Awaiting Review7.1

#15 @modi2918
6 weeks ago

  • Owner changed from modi2918 to adamsilverstein
  • Status acceptedassigned

@wildworks commented on PR #11920:


5 weeks ago
#16

Closing this in favor of #12352

#17 @modi2918
5 weeks ago

  • Owner changed from adamsilverstein to modi2918
  • Status assignedaccepted

This ticket was mentioned in Slack in #core by adrianduffell. View the logs.


5 weeks ago

#19 @adrianduffell
5 weeks ago

  • Milestone 7.1Future Release

This was discussed in today's bug scrub. With 7.1 RC 1 due in the coming hours, let's punt this to a future release to give it more time to work through.

Note: See TracTickets for help on using tickets.