Background
In the discussion on #75793 (comment), the question came up of whether EXIF rotation detection is best done client-side rather than relying on the server. We agreed to continue the discussion in a follow-up — this is that follow-up.
Current state
EXIF orientation is currently detected server-side and rotation is applied client-side:
- Server (PHP):
wp_read_image_metadata() reads the EXIF orientation during upload and stores it in attachment metadata. Gutenberg_REST_Attachments_Controller::prepare_item_for_response() exposes it as exif_orientation on the REST response (lib/media/class-gutenberg-rest-attachments-controller.php:262).
- Server (PHP):
wp_image_maybe_exif_rotate is filtered to __return_false during the client-side upload flow so the server does not rotate the original (lib/media/class-gutenberg-rest-attachments-controller.php:382).
- Client (JS):
generateThumbnails() reads attachment.exif_orientation from the response and dispatches a rotation operation when it isn't 1 (packages/upload-media/src/store/private-actions.ts:1096).
So today, detection lives in PHP (wp_read_image_metadata) and rotation lives in JS (vips). The orientation value round-trips through the upload response.
Three approaches
1. Server-side detection (current)
The browser uploads the original; the server reads EXIF and returns the orientation in the response; the client rotates and sideloads sub-sizes.
Pros
- Single source of truth — reuses
wp_read_image_metadata(), which all of WordPress already trusts.
- Backwards compatible with any existing PHP filters/plugins that hook into the metadata reader.
- Works for any MIME type the server can parse (HEIC, TIFF, etc.) — no need to ship a JS EXIF parser per format.
- Consistent results across browsers (no JS EXIF library quirks).
Cons
- Detection is delayed until after the original upload completes — rotation can't begin until the response arrives.
- Adds an unavoidable PHP step even when the client already has the file in memory.
- Couples the client-side processing pipeline to a server round-trip for a piece of information the client could compute locally.
2. Client-side detection
Read EXIF orientation in JS (e.g. via exifr, a small custom parser, or createImageBitmap with imageOrientation: 'from-image') before/during upload and rotate locally without waiting for the server.
Pros
- No server round-trip needed before rotation — pipeline can run end-to-end in the browser.
- Lets us rotate the original before upload, so the server stores an already-correct file (matches iOS/Android camera behavior).
- Simpler data flow — no
exif_orientation field on the REST response.
Cons
- Need to parse EXIF in JS for every supported format. HEIC/HEIF EXIF parsing in particular is non-trivial and varies by browser.
- Bypasses any PHP filter that plugins use to override orientation handling (loss of
wp_image_maybe_exif_rotate-style extensibility).
- Potential cross-browser inconsistency.
createImageBitmap({ imageOrientation: 'from-image' }) is well-supported but doesn't give us the raw orientation value, only the rotated bitmap.
- Not all browsers support client side media so the server would still be a fallback meaning we need to maintain both paths
3. Hybrid
Detect client-side when possible (fast path), fall back to server-side detection (already in the response) when the client can't read EXIF for that format. Or: detect client-side and verify server-side.
Pros
- Best of both: fast path for common cases, safety net for edge cases.
- Lets us migrate incrementally — keep the server path, add the client path opportunistically.
Cons
- Two implementations to keep in sync.
- More complex contract: when does the client trust its own reading vs. the server's? Conflict resolution rules need to be specified.
- The "best of both" can become "worst of both" if the fast path is rarely a win in practice.
Questions for the discussion
- Do we have data on how often EXIF rotation is actually needed? (i.e. is the fast path worth optimizing?)
- How important is the ability for plugins to filter orientation handling in PHP? Howe many popular plugins use filters that would be lost?
- Are there formats (HEIC, TIFF) where client-side EXIF parsing is too costly to ship? (we already do this for HEIC when the server lacks support)
- Is there a path to have the server not read EXIF at all when client-side processing is active, so we save the PHP work entirely?
Related: #75793, the broader client-side media processing initiative ([Feature] Client Side Media).
Background
In the discussion on #75793 (comment), the question came up of whether EXIF rotation detection is best done client-side rather than relying on the server. We agreed to continue the discussion in a follow-up — this is that follow-up.
Current state
EXIF orientation is currently detected server-side and rotation is applied client-side:
wp_read_image_metadata()reads the EXIF orientation during upload and stores it in attachment metadata.Gutenberg_REST_Attachments_Controller::prepare_item_for_response()exposes it asexif_orientationon the REST response (lib/media/class-gutenberg-rest-attachments-controller.php:262).wp_image_maybe_exif_rotateis filtered to__return_falseduring the client-side upload flow so the server does not rotate the original (lib/media/class-gutenberg-rest-attachments-controller.php:382).generateThumbnails()readsattachment.exif_orientationfrom the response and dispatches a rotation operation when it isn't1(packages/upload-media/src/store/private-actions.ts:1096).So today, detection lives in PHP (
wp_read_image_metadata) and rotation lives in JS (vips). The orientation value round-trips through the upload response.Three approaches
1. Server-side detection (current)
The browser uploads the original; the server reads EXIF and returns the orientation in the response; the client rotates and sideloads sub-sizes.
Pros
wp_read_image_metadata(), which all of WordPress already trusts.Cons
2. Client-side detection
Read EXIF orientation in JS (e.g. via
exifr, a small custom parser, orcreateImageBitmapwithimageOrientation: 'from-image') before/during upload and rotate locally without waiting for the server.Pros
exif_orientationfield on the REST response.Cons
wp_image_maybe_exif_rotate-style extensibility).createImageBitmap({ imageOrientation: 'from-image' })is well-supported but doesn't give us the raw orientation value, only the rotated bitmap.3. Hybrid
Detect client-side when possible (fast path), fall back to server-side detection (already in the response) when the client can't read EXIF for that format. Or: detect client-side and verify server-side.
Pros
Cons
Questions for the discussion
Related: #75793, the broader client-side media processing initiative ([Feature] Client Side Media).