php support for WEBP image metadata

Does php support webp image metadata?

Specifically, I want to be able to read and write XMP and EXIF metadata for webp images natively in php code.

I have been experimenting with the below code and it is giving me a "File not supported in" warning.

<?php

$photoSourceThumbnail = "publicAssets/images/att_galleryWebP/A0001_LSF-PHOTOS-WM-TM-WEBP/A0001-EWF-LSF-01.webp";
$photoSourceFull = "assets/images/att_galleryWebP/A0001_LSF-PHOTOS-WM-FULL-WEBP/A0001-EWF-LSF-01.webp";

echo "$photoSourceFull:<br />\n";
$exif = exif_read_data($photoSourceFull, 'IFD0');
echo $exif===false ? "No header data found.<br />\n" : "Image contains headers<br />\n";

$exif = exif_read_data($photoSourceFull, 0, true);
echo "test2.jpg:<br />\n";
foreach ($exif as $key => $section) {
    foreach ($section as $name => $val) {
        echo "$key.$name: $val<br />\n";
    }
} 

It is better to use ExifTool for this.

Install ExifTool

https://exiftool.org/

PHP example

class ExifToolException extends RuntimeException{}

function getInfo(string $file) : object 
{
    $info = shell_exec('exiftool -json ' . escapeshellarg($file) . ' 2>&1');
    if(strpos($info, 'Error:') > -1) {
        throw new ExifToolException(rtrim($info, PHP_EOL));
    }
    return json_decode($info)[0];
}

try {
    var_dump(getInfo('abc.webp')->Megapixels);
} catch(ExifToolException $e) {
    var_dump($e->getMessage());
}

Update: ExifTool does not support writing webp

Instead you can look at webpmux from Google: https://developers.google.com/speed/webp/docs/webpmux


WebP supports both Exif and XMP for years already. The format is based on RIFF and acknowledges at least the chunks EXIF, XMP and ICCP. Good software will also read an IPTC chunk.

Just because some random software does not consider carrying over metadata doesn't mean the target format doesn't support it - most software is rather sloppy than ambitious. Since the RIFFormat is rather trivial it should be easy to modify existing files to include more chunks:

  • Each chunk consists of 4 bytes identifier/FourCC (i.e. the ASCII characters EXIF), then 4 bytes of its size in little Endian, then the payload.
  • The file's first chunk is similar: it starts with the 4 bytes RIFF, then 4 bytes of its entire filesize minus 8, then 4 bytes of content identification, here WEBP (to distinguish this from other formats also using RIFF, such as WAV, AVI, Maya, AIF, MIDI...).
  • This means you append your new chunk at the end of the file and then patch bytes 5 through 8 of the file with the new filesize. Example:
$sExif= '...the binary data...';  // You read that off the other file, of course
$iLenExif= strlen( $sExif );  // Payload length in bytes
if( $iLenExif% 2== 1 ) $sExif.= "\0";  // RIFF needs 16bit alignment

$hFile= fopen( 'TARGET.WEBP', 'r+' );   // Read and write access
fseek( $hFile, 0, SEEK_END );  // Go to end of file

fwrite( $hFile, 'EXIF' );  // 4 bytes chunk ID
fwrite( $hFile, pack( 'V', $iLenExif ) );  // 4 bytes of payload length
fwrite( $hFile, $sExif );  // Actual data

$iFilesize= ftell( $hFile );  // Should be bigger
fseek( $hFile, 4, SEEK_SET );  // Go to 5th byte of file
fwrite( $hFile, pack( 'V', $iFilesize- 8 ) );  // Write 4 bytes, patching old filesize

fclose( $hFile );  // Store everything.