Your Phone's Motion Photos Are Not Corrupt — But Most Software Thinks They Are
We shipped a bug that called intact photographs damaged. Not obscure files — the default output of Samsung Galaxy and Google Pixel cameras. This is what went wrong, and why the same mistake is easy to make in any code that checks whether an image file is complete.
What a Motion Photo actually is. When you take a photo on a recent Pixel or Galaxy, the camera saves two things inside one file: a normal JPEG, and a short MP4 video appended after it. Google documents the arrangement in its Motion Photo file format specification, which describes exactly this: a primary still image followed by secondary media in one container, with XMP metadata giving each item's length and padding — the video's position is worked out by summing those, not stored directly.
The result is a file that is a completely valid JPEG. Every decoder reads it. The photo opens everywhere. It simply has extra bytes after the picture ends.
The mistake. A JPEG ends with a two-byte End of Image marker, FF D9. The obvious way to check a file is not truncated is to look at the last two bytes and see whether they are the end marker. That check is wrong, and it is wrong in a way that passes every test you are likely to write for it.
It passes on a file you truncate yourself. It passes on a normal camera JPEG. It passes on every sample image in a test fixture directory. And then it fails on the default output of two of the largest Android camera brands, because on a Motion Photo the end marker is present — it is just not last.
PNG has the same shape of problem. A PNG ends with an IEND chunk, and plenty of real files carry bytes after it: polyglot files that are valid as two formats at once, some CMS exports, and any writer that pads with something other than zeroes. Those files are intact too.
The rule, and the two things it needs to survive contact with real files. An end marker must be present, never last. But presence alone is not enough. One of the two below was designed in from the start; the other we learned the hard way, months later:
- The marker has to be long enough to scan for. JPEG's two-byte EOI and PNG's twelve-byte IEND record are distinctive enough that finding one means something. A GIF's trailer is a single byte, which would match constantly, so scanning for it tells you nothing — that format has to be judged some other way.
- Not every end marker is the file's own. An EXIF block can embed a thumbnail JPEG, and that thumbnail has an EOI of its own. A photo cut off mid-download still shows an EOI in its tail, inside that thumbnail, and reads as complete. You have to work out where the EXIF segment ends and ignore any marker that falls inside it.
With both of those in place, a marker found outside the metadata means the image data is complete whatever follows, and a genuinely absent one means the file really was cut short — which is the only case worth reporting to the person who uploaded it.
Why this matters more than it sounds. A false "corrupt file" message is worse than a crash. A crash reads as a bug in the software. A corruption warning reads as a problem with your photo — so people go looking for a backup, or re-shoot, or conclude their phone or memory card is failing. We were telling Pixel and Galaxy owners their perfectly good pictures were damaged, using their camera's default setting.
How we found it. Not from a test. Three reviewers reading a change that had already passed 2,482 automated tests found eleven defects, and three of them were separate ways an intact file could be called truncated. The fixture set had no Motion Photo in it, so nothing in the suite could ever have caught it. A test suite only tests the files you thought to include.
If you are writing this check yourself. Search for the marker rather than comparing the tail — and search far enough back to find it. Our own search looked at the last four kilobytes, which is nothing against an appended video that runs to megabytes, so for a while we scanned correctly and still missed. Keep a real Motion Photo and a PNG with trailing data in your fixtures — not files you constructed, files a phone produced. And when you are about to tell someone their file is broken, be much more certain than you would be about any other message, because that one sends people to look for backups.
MiniPx scans for the marker wherever the marker is distinctive enough to make scanning meaningful — PNG's IEND record and JPEG's EOI — and ignores one that turns out to be inside an EXIF thumbnail. If a file really cannot be opened we say what we found instead of guessing. You can try it on the JPEG compressor, which runs entirely in your browser and never uploads anything.
Related tools
More from the blog
Compress, convert, and resize images in your browser. Nothing gets uploaded.
Open MiniPx →