Skip to content

Return the filtered wp_editor_set_quality value in the image upload response #78419

Description

@adamsilverstein

Parent Issue

Part of #74333

Context

In client-side media processing, sub-size images (and, when format conversion applies, the main image) are encoded in the browser via the @wordpress/vips worker. The encoder needs a JPEG/WebP/AVIF quality value to use.

Today the client uses a single hardcoded constant (DEFAULT_OUTPUT_QUALITY = 0.82 in packages/upload-media/src/store/private-actions.ts), optionally overridden by a generic imageQuality setting. This bypasses WordPress's wp_editor_set_quality filter entirely, so any plugin or theme that tunes encode quality on the server has no effect on client-side-processed images.

This is the same class of problem solved for the output format in #75784 / #75793 ("Move image output format filtering to upload response"), and for EXIF rotation before that: per-file image-processing decisions belong in the per-attachment upload response where the real filename, MIME type, and target dimensions are available.

Problem

  • The client-side encoder ignores wp_editor_set_quality. A site that lowers or raises quality server-side gets inconsistent results between server-processed and client-processed uploads.
  • wp_editor_set_quality is size-aware since WP 6.8 — its signature is ( int $quality, string $mime_type, array $size ) (see WP_Image_Editor::set_quality()). Plugins can return a different quality per dimension (e.g. higher quality for the full image, lower for thumbnails). The client currently applies one flat quality to every size.
  • Quality should be derived from the output MIME type (post image_editor_output_format conversion), exactly as core's set_quality() does, not the input type.

Proposed Solution

Add an image_quality field to the attachment REST response (the Gutenberg_REST_Attachments_Controller), mirroring the existing image_output_format / image_save_progressive fields:

"image_quality": {
  "default": 82,              // wp_editor_set_quality for the full-size output, 1-100
  "sizes": { "large": 90 }    // per-registered-size overrides, only where the
                              // filtered value differs from "default"
}
  • The REST callback applies wp_editor_set_quality with the resolved output MIME type and the full-image dimensions for default.
  • when generating sub sizes on the client: For each registered image sub-size, it re-applies the filter with that size's width/height and includes the result under sizes only when it differs from default (keeps the payload small).
  • packages/upload-media consumes image_quality instead of DEFAULT_OUTPUT_QUALITY: each sub-size resize/transcode uses sizes[name] ?? default (converted from 1-100 to the 0-1 scale the vips worker expects); the main-image transcode uses default. The hardcoded constant remains only as a final fallback when the field is absent (older Core).

Benefits

  • Client-side-processed images honor wp_editor_set_quality, matching server-side behavior.
  • Per-size quality tuning works on the client.
  • Keeps per-file processing logic in the upload response, consistent with image_output_format, image_save_progressive, and exif_orientation.

References

Metadata

Metadata

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions