Skip to content

Media: Add UltraHDR (ISO 21496-1) gain map support#74873

Open
adamsilverstein wants to merge 34 commits into
trunkfrom
open-ultrahdr-package
Open

Media: Add UltraHDR (ISO 21496-1) gain map support#74873
adamsilverstein wants to merge 34 commits into
trunkfrom
open-ultrahdr-package

Conversation

@adamsilverstein
Copy link
Copy Markdown
Member

@adamsilverstein adamsilverstein commented Jan 22, 2026

Summary

  • Adds UltraHDR/gain map detection and resize support to the media upload workflow
  • Uploads original UltraHDR JPEGs unmodified (already backwards-compatible with SDR displays)
  • Sub-sized images preserve the ISO 21496-1 gain map so every size retains HDR capability
  • All UltraHDR processing flows through the existing @wordpress/vips worker — no extra WASM module is bundled

Closes #74874

Similar to adamsilverstein/client-side-media-experiments#15

Approach

UltraHDR support comes from wasm-vips (libvips compiled to WebAssembly), which gained native UltraHDR (uhdrload / uhdrsave) in 0.0.17. This was unblocked by google/libultrahdr#386, which dual-licensed libultrahdr under Apache-2.0 OR MIT and made it compatible with WordPress's GPLv2-or-later codebase.

@wordpress/vips is bumped to wasm-vips@^0.0.17 and gains:

  • a getUltraHdrInfo(buffer) helper that probes a JPEG for an embedded gain map and reports HDR headroom
  • an isUltraHdr flag on resizeImage that routes through uhdrloadBuffer + uhdrsaveBuffer so the gain map is downsized in lockstep with the base image and re-embedded on save

@wordpress/upload-media uses these helpers in its existing DetectUltraHdr operation and tags sub-size resizes with isUltraHdr so the resize step transparently preserves the gain map. Thanks to @kleisauke for landing native UltraHDR support in wasm-vips.

Removed

  • The standalone open-ultrahdr and open-ultrahdr-wasm dependencies are no longer needed.
  • The EncodeUltraHdr queue operation type is gone — there's no separate re-encode step; resize handles it inline.
  • The OffscreenCanvas-based ISO 21496-1 gain map reconstruction (encodeUltraHdrItem) is removed.

Follow-up

wasm-vips@0.0.18 will land a docs-only update to THIRD-PARTY-NOTICES.md to make the dual-licensing explicit. We can bump to ^0.0.18 when it's published.

Test plan

  • Upload an UltraHDR JPEG image to the media library
  • Verify the upload completes successfully and the original is uploaded unmodified
  • Verify sub-sized images also retain the HDR gain map (preserved through resize)
  • Verify the uploaded image displays correctly on non-HDR displays (SDR fallback)
  • Upload a regular JPEG and verify it still works normally

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 22, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @kleisauke, @gregbenz.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: kleisauke, gregbenz.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@adamsilverstein adamsilverstein added [Type] Enhancement A suggestion for improvement. [Feature] Client Side Media Media processing in the browser with WASM labels Jan 22, 2026
@github-project-automation github-project-automation Bot moved this to 🔎 Needs Review in WordPress 7.0 Editor Tasks Jan 22, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 22, 2026

Flaky tests detected in b608550.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/26533550660
📝 Reported issues:

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 22, 2026

Size Change: +228 kB (+2.78%)

Total Size: 8.41 MB

📦 View Changed
Filename Size Change
build/modules/vips/worker.min.js 4.79 MB +228 kB (+4.99%) 🔍
build/scripts/upload-media/index.min.js 11.7 kB +207 B (+1.8%)
ℹ️ View Unchanged
Filename Size
build/modules/a11y/index.min.js 355 B
build/modules/abilities/index.min.js 42.3 kB
build/modules/block-editor/utils/fit-text-frontend.min.js 617 B
build/modules/block-library/accordion/view.min.js 595 B
build/modules/block-library/file/view.min.js 346 B
build/modules/block-library/form/view.min.js 528 B
build/modules/block-library/image/view.min.js 2.64 kB
build/modules/block-library/navigation/view.min.js 1.14 kB
build/modules/block-library/playlist/view.min.js 10.9 kB
build/modules/block-library/query/view.min.js 518 B
build/modules/block-library/search/view.min.js 498 B
build/modules/block-library/tabs/view.min.js 946 B
build/modules/boot/index.min.js 19.6 kB
build/modules/connectors/index.min.js 2.05 kB
build/modules/content-types/index.min.js 156 kB
build/modules/core-abilities/index.min.js 926 B
build/modules/edit-site-init/index.min.js 1.4 kB
build/modules/interactivity-router/full-page.min.js 451 B
build/modules/interactivity-router/index.min.js 11.6 kB
build/modules/interactivity/index.min.js 15.3 kB
build/modules/latex-to-mathml/index.min.js 56.5 kB
build/modules/latex-to-mathml/loader.min.js 131 B
build/modules/lazy-editor/index.min.js 14.2 kB
build/modules/route/index.min.js 25.2 kB
build/modules/vips/loader.min.js 127 B
build/modules/workflow/index.min.js 19.9 kB
build/scripts/a11y/index.min.js 1.1 kB
build/scripts/annotations/index.min.js 2.53 kB
build/scripts/api-fetch/index.min.js 3.34 kB
build/scripts/autop/index.min.js 2.21 kB
build/scripts/base-styles/index.min.js 146 B
build/scripts/blob/index.min.js 665 B
build/scripts/block-directory/index.min.js 43 kB
build/scripts/block-editor/index.min.js 379 kB
build/scripts/block-library/index.min.js 323 kB
build/scripts/block-serialization-default-parser/index.min.js 1.2 kB
build/scripts/block-serialization-spec-parser/index.min.js 3.12 kB
build/scripts/blocks/index.min.js 57 kB
build/scripts/commands/index.min.js 21 kB
build/scripts/components/index.min.js 263 kB
build/scripts/compose/index.min.js 11.7 kB
build/scripts/core-commands/index.min.js 4.37 kB
build/scripts/core-data/index.min.js 31.4 kB
build/scripts/customize-widgets/index.min.js 14.6 kB
build/scripts/data-controls/index.min.js 832 B
build/scripts/data/index.min.js 9.74 kB
build/scripts/date/index.min.js 23.7 kB
build/scripts/deprecated/index.min.js 784 B
build/scripts/dom-ready/index.min.js 502 B
build/scripts/dom/index.min.js 5.04 kB
build/scripts/edit-post/index.min.js 52 kB
build/scripts/edit-site/index.min.js 295 kB
build/scripts/edit-widgets/index.min.js 22.2 kB
build/scripts/editor/index.min.js 462 kB
build/scripts/element/index.min.js 5.63 kB
build/scripts/escape-html/index.min.js 622 B
build/scripts/format-library/index.min.js 13.1 kB
build/scripts/hooks/index.min.js 1.86 kB
build/scripts/html-entities/index.min.js 529 B
build/scripts/i18n/index.min.js 2.5 kB
build/scripts/is-shallow-equal/index.min.js 607 B
build/scripts/keyboard-shortcuts/index.min.js 1.65 kB
build/scripts/keycodes/index.min.js 1.6 kB
build/scripts/list-reusable-blocks/index.min.js 2.53 kB
build/scripts/media-utils/index.min.js 112 kB
build/scripts/notices/index.min.js 1.72 kB
build/scripts/nux/index.min.js 1.92 kB
build/scripts/patterns/index.min.js 8 kB
build/scripts/plugins/index.min.js 2.18 kB
build/scripts/preferences-persistence/index.min.js 2.19 kB
build/scripts/preferences/index.min.js 3.33 kB
build/scripts/primitives/index.min.js 1.05 kB
build/scripts/priority-queue/index.min.js 1.65 kB
build/scripts/private-apis/index.min.js 1.15 kB
build/scripts/react-i18n/index.min.js 868 B
build/scripts/redux-routine/index.min.js 3.4 kB
build/scripts/reusable-blocks/index.min.js 3.14 kB
build/scripts/rich-text/index.min.js 14.1 kB
build/scripts/router/index.min.js 5.99 kB
build/scripts/server-side-render/index.min.js 1.94 kB
build/scripts/shortcode/index.min.js 1.62 kB
build/scripts/style-engine/index.min.js 2.45 kB
build/scripts/sync/index.min.js 39.6 kB
build/scripts/theme/index.min.js 22 kB
build/scripts/token-list/index.min.js 767 B
build/scripts/undo-manager/index.min.js 954 B
build/scripts/url/index.min.js 4.02 kB
build/scripts/vendors/react-dom.min.js 57.7 kB
build/scripts/vendors/react-jsx-runtime.min.js 513 B
build/scripts/vendors/react.min.js 3.1 kB
build/scripts/viewport/index.min.js 1.25 kB
build/scripts/warning/index.min.js 482 B
build/scripts/widgets/index.min.js 7.84 kB
build/scripts/wordcount/index.min.js 1.07 kB
build/styles/base-styles/admin-schemes-rtl.css 1.71 kB
build/styles/base-styles/admin-schemes-rtl.min.css 775 B
build/styles/base-styles/admin-schemes.css 1.71 kB
build/styles/base-styles/admin-schemes.min.css 775 B
build/styles/block-directory/style-rtl.css 1.97 kB
build/styles/block-directory/style-rtl.min.css 1.06 kB
build/styles/block-directory/style.css 1.98 kB
build/styles/block-directory/style.min.css 1.06 kB
build/styles/block-editor/content-rtl.css 5.51 kB
build/styles/block-editor/content-rtl.min.css 4.08 kB
build/styles/block-editor/content.css 5.52 kB
build/styles/block-editor/content.min.css 4.07 kB
build/styles/block-editor/default-editor-styles-rtl.css 697 B
build/styles/block-editor/default-editor-styles-rtl.min.css 224 B
build/styles/block-editor/default-editor-styles.css 697 B
build/styles/block-editor/default-editor-styles.min.css 224 B
build/styles/block-editor/style-rtl.css 18.7 kB
build/styles/block-editor/style-rtl.min.css 15.9 kB
build/styles/block-editor/style.css 18.7 kB
build/styles/block-editor/style.min.css 15.9 kB
build/styles/block-library/accordion-heading/style-rtl.css 346 B
build/styles/block-library/accordion-heading/style-rtl.min.css 325 B
build/styles/block-library/accordion-heading/style.css 346 B
build/styles/block-library/accordion-heading/style.min.css 325 B
build/styles/block-library/accordion-item/style-rtl.css 239 B
build/styles/block-library/accordion-item/style-rtl.min.css 180 B
build/styles/block-library/accordion-item/style.css 238 B
build/styles/block-library/accordion-item/style.min.css 180 B
build/styles/block-library/accordion-panel/style-rtl.css 110 B
build/styles/block-library/accordion-panel/style-rtl.min.css 99 B
build/styles/block-library/accordion-panel/style.css 110 B
build/styles/block-library/accordion-panel/style.min.css 99 B
build/styles/block-library/accordion/style-rtl.css 69 B
build/styles/block-library/accordion/style-rtl.min.css 62 B
build/styles/block-library/accordion/style.css 69 B
build/styles/block-library/accordion/style.min.css 62 B
build/styles/block-library/archives/style-rtl.css 101 B
build/styles/block-library/archives/style-rtl.min.css 90 B
build/styles/block-library/archives/style.css 101 B
build/styles/block-library/archives/style.min.css 90 B
build/styles/block-library/audio/editor-rtl.css 166 B
build/styles/block-library/audio/editor-rtl.min.css 149 B
build/styles/block-library/audio/editor.css 166 B
build/styles/block-library/audio/editor.min.css 151 B
build/styles/block-library/audio/style-rtl.css 945 B
build/styles/block-library/audio/style-rtl.min.css 132 B
build/styles/block-library/audio/style.css 945 B
build/styles/block-library/audio/style.min.css 132 B
build/styles/block-library/audio/theme-rtl.css 967 B
build/styles/block-library/audio/theme-rtl.min.css 134 B
build/styles/block-library/audio/theme.css 967 B
build/styles/block-library/audio/theme.min.css 134 B
build/styles/block-library/avatar/editor-rtl.css 127 B
build/styles/block-library/avatar/editor-rtl.min.css 115 B
build/styles/block-library/avatar/editor.css 127 B
build/styles/block-library/avatar/editor.min.css 115 B
build/styles/block-library/avatar/style-rtl.css 117 B
build/styles/block-library/avatar/style-rtl.min.css 104 B
build/styles/block-library/avatar/style.css 117 B
build/styles/block-library/avatar/style.min.css 104 B
build/styles/block-library/breadcrumbs/style-rtl.css 236 B
build/styles/block-library/breadcrumbs/style-rtl.min.css 206 B
build/styles/block-library/breadcrumbs/style.css 236 B
build/styles/block-library/breadcrumbs/style.min.css 206 B
build/styles/block-library/button/editor-rtl.css 306 B
build/styles/block-library/button/editor-rtl.min.css 265 B
build/styles/block-library/button/editor.css 317 B
build/styles/block-library/button/editor.min.css 265 B
build/styles/block-library/button/style-rtl.css 651 B
build/styles/block-library/button/style-rtl.min.css 596 B
build/styles/block-library/button/style.css 662 B
build/styles/block-library/button/style.min.css 596 B
build/styles/block-library/buttons/editor-rtl.css 391 B
build/styles/block-library/buttons/editor-rtl.min.css 291 B
build/styles/block-library/buttons/editor.css 391 B
build/styles/block-library/buttons/editor.min.css 291 B
build/styles/block-library/buttons/style-rtl.css 452 B
build/styles/block-library/buttons/style-rtl.min.css 349 B
build/styles/block-library/buttons/style.css 453 B
build/styles/block-library/buttons/style.min.css 349 B
build/styles/block-library/calendar/style-rtl.css 271 B
build/styles/block-library/calendar/style-rtl.min.css 239 B
build/styles/block-library/calendar/style.css 271 B
build/styles/block-library/calendar/style.min.css 239 B
build/styles/block-library/categories/editor-rtl.css 171 B
build/styles/block-library/categories/editor-rtl.min.css 132 B
build/styles/block-library/categories/editor.css 170 B
build/styles/block-library/categories/editor.min.css 131 B
build/styles/block-library/categories/style-rtl.css 226 B
build/styles/block-library/categories/style-rtl.min.css 169 B
build/styles/block-library/categories/style.css 235 B
build/styles/block-library/categories/style.min.css 169 B
build/styles/block-library/classic-rtl.css 402 B
build/styles/block-library/classic-rtl.min.css 358 B
build/styles/block-library/classic.css 402 B
build/styles/block-library/classic.min.css 358 B
build/styles/block-library/code/editor-rtl.css 59 B
build/styles/block-library/code/editor-rtl.min.css 53 B
build/styles/block-library/code/editor.css 59 B
build/styles/block-library/code/editor.min.css 53 B
build/styles/block-library/code/style-rtl.css 158 B
build/styles/block-library/code/style-rtl.min.css 140 B
build/styles/block-library/code/style.css 178 B
build/styles/block-library/code/style.min.css 140 B
build/styles/block-library/code/theme-rtl.css 135 B
build/styles/block-library/code/theme-rtl.min.css 122 B
build/styles/block-library/code/theme.css 135 B
build/styles/block-library/code/theme.min.css 122 B
build/styles/block-library/columns/editor-rtl.css 119 B
build/styles/block-library/columns/editor-rtl.min.css 108 B
build/styles/block-library/columns/editor.css 119 B
build/styles/block-library/columns/editor.min.css 108 B
build/styles/block-library/columns/style-rtl.css 1.3 kB
build/styles/block-library/columns/style-rtl.min.css 421 B
build/styles/block-library/columns/style.css 1.3 kB
build/styles/block-library/columns/style.min.css 421 B
build/styles/block-library/comment-author-avatar/editor-rtl.css 136 B
build/styles/block-library/comment-author-avatar/editor-rtl.min.css 124 B
build/styles/block-library/comment-author-avatar/editor.css 136 B
build/styles/block-library/comment-author-avatar/editor.min.css 124 B
build/styles/block-library/comment-author-name/style-rtl.css 79 B
build/styles/block-library/comment-author-name/style-rtl.min.css 72 B
build/styles/block-library/comment-author-name/style.css 79 B
build/styles/block-library/comment-author-name/style.min.css 72 B
build/styles/block-library/comment-content/style-rtl.css 137 B
build/styles/block-library/comment-content/style-rtl.min.css 120 B
build/styles/block-library/comment-content/style.css 137 B
build/styles/block-library/comment-content/style.min.css 120 B
build/styles/block-library/comment-date/style-rtl.css 72 B
build/styles/block-library/comment-date/style-rtl.min.css 65 B
build/styles/block-library/comment-date/style.css 72 B
build/styles/block-library/comment-date/style.min.css 65 B
build/styles/block-library/comment-edit-link/style-rtl.css 77 B
build/styles/block-library/comment-edit-link/style-rtl.min.css 70 B
build/styles/block-library/comment-edit-link/style.css 77 B
build/styles/block-library/comment-edit-link/style.min.css 70 B
build/styles/block-library/comment-reply-link/style-rtl.css 78 B
build/styles/block-library/comment-reply-link/style-rtl.min.css 71 B
build/styles/block-library/comment-reply-link/style.css 78 B
build/styles/block-library/comment-reply-link/style.min.css 71 B
build/styles/block-library/comment-template/style-rtl.css 213 B
build/styles/block-library/comment-template/style-rtl.min.css 191 B
build/styles/block-library/comment-template/style.css 213 B
build/styles/block-library/comment-template/style.min.css 191 B
build/styles/block-library/comments-pagination-numbers/editor-rtl.css 135 B
build/styles/block-library/comments-pagination-numbers/editor-rtl.min.css 122 B
build/styles/block-library/comments-pagination-numbers/editor.css 144 B
build/styles/block-library/comments-pagination-numbers/editor.min.css 121 B
build/styles/block-library/comments-pagination/editor-rtl.css 184 B
build/styles/block-library/comments-pagination/editor-rtl.min.css 168 B
build/styles/block-library/comments-pagination/editor.css 184 B
build/styles/block-library/comments-pagination/editor.min.css 168 B
build/styles/block-library/comments-pagination/style-rtl.css 224 B
build/styles/block-library/comments-pagination/style-rtl.min.css 201 B
build/styles/block-library/comments-pagination/style.css 236 B
build/styles/block-library/comments-pagination/style.min.css 201 B
build/styles/block-library/comments-title/editor-rtl.css 83 B
build/styles/block-library/comments-title/editor-rtl.min.css 75 B
build/styles/block-library/comments-title/editor.css 83 B
build/styles/block-library/comments-title/editor.min.css 75 B
build/styles/block-library/comments/editor-rtl.css 968 B
build/styles/block-library/comments/editor-rtl.min.css 842 B
build/styles/block-library/comments/editor.css 968 B
build/styles/block-library/comments/editor.min.css 842 B
build/styles/block-library/comments/style-rtl.css 754 B
build/styles/block-library/comments/style-rtl.min.css 637 B
build/styles/block-library/comments/style.css 752 B
build/styles/block-library/comments/style.min.css 637 B
build/styles/block-library/common-rtl.css 2.57 kB
build/styles/block-library/common-rtl.min.css 1.21 kB
build/styles/block-library/common.css 2.59 kB
build/styles/block-library/common.min.css 1.2 kB
build/styles/block-library/cover/editor-rtl.css 1.05 kB
build/styles/block-library/cover/editor-rtl.min.css 631 B
build/styles/block-library/cover/editor.css 1.05 kB
build/styles/block-library/cover/editor.min.css 631 B
build/styles/block-library/cover/style-rtl.css 2.5 kB
build/styles/block-library/cover/style-rtl.min.css 1.82 kB
build/styles/block-library/cover/style.css 2.51 kB
build/styles/block-library/cover/style.min.css 1.81 kB
build/styles/block-library/details/editor-rtl.css 72 B
build/styles/block-library/details/editor-rtl.min.css 65 B
build/styles/block-library/details/editor.css 72 B
build/styles/block-library/details/editor.min.css 65 B
build/styles/block-library/details/style-rtl.css 97 B
build/styles/block-library/details/style-rtl.min.css 86 B
build/styles/block-library/details/style.css 97 B
build/styles/block-library/details/style.min.css 86 B
build/styles/block-library/editor-elements-rtl.css 117 B
build/styles/block-library/editor-elements-rtl.min.css 75 B
build/styles/block-library/editor-elements.css 117 B
build/styles/block-library/editor-elements.min.css 75 B
build/styles/block-library/editor-rtl.css 12.5 kB
build/styles/block-library/editor-rtl.min.css 10.3 kB
build/styles/block-library/editor.css 12.5 kB
build/styles/block-library/editor.min.css 10.3 kB
build/styles/block-library/elements-rtl.css 84 B
build/styles/block-library/elements-rtl.min.css 54 B
build/styles/block-library/elements.css 84 B
build/styles/block-library/elements.min.css 54 B
build/styles/block-library/embed/editor-rtl.css 391 B
build/styles/block-library/embed/editor-rtl.min.css 331 B
build/styles/block-library/embed/editor.css 390 B
build/styles/block-library/embed/editor.min.css 331 B
build/styles/block-library/embed/style-rtl.css 1.29 kB
build/styles/block-library/embed/style-rtl.min.css 448 B
build/styles/block-library/embed/style.css 1.29 kB
build/styles/block-library/embed/style.min.css 448 B
build/styles/block-library/embed/theme-rtl.css 967 B
build/styles/block-library/embed/theme-rtl.min.css 133 B
build/styles/block-library/embed/theme.css 967 B
build/styles/block-library/embed/theme.min.css 133 B
build/styles/block-library/file/editor-rtl.css 352 B
build/styles/block-library/file/editor-rtl.min.css 324 B
build/styles/block-library/file/editor.css 353 B
build/styles/block-library/file/editor.min.css 324 B
build/styles/block-library/file/style-rtl.css 318 B
build/styles/block-library/file/style-rtl.min.css 278 B
build/styles/block-library/file/style.css 331 B
build/styles/block-library/file/style.min.css 278 B
build/styles/block-library/footnotes/style-rtl.css 220 B
build/styles/block-library/footnotes/style-rtl.min.css 198 B
build/styles/block-library/footnotes/style.css 219 B
build/styles/block-library/footnotes/style.min.css 197 B
build/styles/block-library/form-input/editor-rtl.css 286 B
build/styles/block-library/form-input/editor-rtl.min.css 265 B
build/styles/block-library/form-input/editor.css 285 B
build/styles/block-library/form-input/editor.min.css 264 B
build/styles/block-library/form-input/style-rtl.css 467 B
build/styles/block-library/form-input/style-rtl.min.css 366 B
build/styles/block-library/form-input/style.css 467 B
build/styles/block-library/form-input/style.min.css 366 B
build/styles/block-library/form-submission-notification/editor-rtl.css 368 B
build/styles/block-library/form-submission-notification/editor-rtl.min.css 344 B
build/styles/block-library/form-submission-notification/editor.css 368 B
build/styles/block-library/form-submission-notification/editor.min.css 341 B
build/styles/block-library/form-submit-button/style-rtl.css 77 B
build/styles/block-library/form-submit-button/style-rtl.min.css 69 B
build/styles/block-library/form-submit-button/style.css 77 B
build/styles/block-library/form-submit-button/style.min.css 69 B
build/styles/block-library/freeform/editor-rtl.css 1.12 kB
build/styles/block-library/freeform/editor-rtl.min.css 288 B
build/styles/block-library/freeform/editor.css 1.12 kB
build/styles/block-library/freeform/editor.min.css 288 B
build/styles/block-library/gallery/editor-rtl.css 1.46 kB
build/styles/block-library/gallery/editor-rtl.min.css 561 B
build/styles/block-library/gallery/editor.css 1.46 kB
build/styles/block-library/gallery/editor.min.css 564 B
build/styles/block-library/gallery/style-rtl.css 2.84 kB
build/styles/block-library/gallery/style-rtl.min.css 1.84 kB
build/styles/block-library/gallery/style.css 2.84 kB
build/styles/block-library/gallery/style.min.css 1.84 kB
build/styles/block-library/gallery/theme-rtl.css 941 B
build/styles/block-library/gallery/theme-rtl.min.css 108 B
build/styles/block-library/gallery/theme.css 941 B
build/styles/block-library/gallery/theme.min.css 108 B
build/styles/block-library/group/editor-rtl.css 772 B
build/styles/block-library/group/editor-rtl.min.css 335 B
build/styles/block-library/group/editor.css 772 B
build/styles/block-library/group/editor.min.css 335 B
build/styles/block-library/group/style-rtl.css 120 B
build/styles/block-library/group/style-rtl.min.css 103 B
build/styles/block-library/group/style.css 120 B
build/styles/block-library/group/style.min.css 103 B
build/styles/block-library/group/theme-rtl.css 468 B
build/styles/block-library/group/theme-rtl.min.css 79 B
build/styles/block-library/group/theme.css 468 B
build/styles/block-library/group/theme.min.css 79 B
build/styles/block-library/heading/style-rtl.css 604 B
build/styles/block-library/heading/style-rtl.min.css 205 B
build/styles/block-library/heading/style.css 604 B
build/styles/block-library/heading/style.min.css 205 B
build/styles/block-library/html/editor-rtl.css 1.29 kB
build/styles/block-library/html/editor-rtl.min.css 464 B
build/styles/block-library/html/editor.css 1.3 kB
build/styles/block-library/html/editor.min.css 464 B
build/styles/block-library/icon/editor-rtl.css 776 B
build/styles/block-library/icon/editor-rtl.min.css 377 B
build/styles/block-library/icon/editor.css 776 B
build/styles/block-library/icon/editor.min.css 377 B
build/styles/block-library/icon/style-rtl.css 218 B
build/styles/block-library/icon/style-rtl.min.css 154 B
build/styles/block-library/icon/style.css 218 B
build/styles/block-library/icon/style.min.css 154 B
build/styles/block-library/image/editor-rtl.css 1.64 kB
build/styles/block-library/image/editor-rtl.min.css 782 B
build/styles/block-library/image/editor.css 1.64 kB
build/styles/block-library/image/editor.min.css 780 B
build/styles/block-library/image/style-rtl.css 2.92 kB
build/styles/block-library/image/style-rtl.min.css 1.86 kB
build/styles/block-library/image/style.css 2.92 kB
build/styles/block-library/image/style.min.css 1.85 kB
build/styles/block-library/image/theme-rtl.css 971 B
build/styles/block-library/image/theme-rtl.min.css 137 B
build/styles/block-library/image/theme.css 971 B
build/styles/block-library/image/theme.min.css 137 B
build/styles/block-library/latest-comments/style-rtl.css 392 B
build/styles/block-library/latest-comments/style-rtl.min.css 352 B
build/styles/block-library/latest-comments/style.css 390 B
build/styles/block-library/latest-comments/style.min.css 352 B
build/styles/block-library/latest-posts/editor-rtl.css 154 B
build/styles/block-library/latest-posts/editor-rtl.min.css 139 B
build/styles/block-library/latest-posts/editor.css 153 B
build/styles/block-library/latest-posts/editor.min.css 138 B
build/styles/block-library/latest-posts/style-rtl.css 1.36 kB
build/styles/block-library/latest-posts/style-rtl.min.css 520 B
build/styles/block-library/latest-posts/style.css 1.37 kB
build/styles/block-library/latest-posts/style.min.css 520 B
build/styles/block-library/list/style-rtl.css 498 B
build/styles/block-library/list/style-rtl.min.css 107 B
build/styles/block-library/list/style.css 498 B
build/styles/block-library/list/style.min.css 107 B
build/styles/block-library/loginout/style-rtl.css 68 B
build/styles/block-library/loginout/style-rtl.min.css 61 B
build/styles/block-library/loginout/style.css 68 B
build/styles/block-library/loginout/style.min.css 61 B
build/styles/block-library/math/editor-rtl.css 491 B
build/styles/block-library/math/editor-rtl.min.css 105 B
build/styles/block-library/math/editor.css 502 B
build/styles/block-library/math/editor.min.css 105 B
build/styles/block-library/math/style-rtl.css 70 B
build/styles/block-library/math/style-rtl.min.css 61 B
build/styles/block-library/math/style.css 70 B
build/styles/block-library/math/style.min.css 61 B
build/styles/block-library/media-text/editor-rtl.css 389 B
build/styles/block-library/media-text/editor-rtl.min.css 321 B
build/styles/block-library/media-text/editor.css 389 B
build/styles/block-library/media-text/editor.min.css 320 B
build/styles/block-library/media-text/style-rtl.css 873 B
build/styles/block-library/media-text/style-rtl.min.css 552 B
build/styles/block-library/media-text/style.css 901 B
build/styles/block-library/media-text/style.min.css 550 B
build/styles/block-library/more/editor-rtl.css 796 B
build/styles/block-library/more/editor-rtl.min.css 393 B
build/styles/block-library/more/editor.css 798 B
build/styles/block-library/more/editor.min.css 393 B
build/styles/block-library/navigation-link/editor-rtl.css 1.28 kB
build/styles/block-library/navigation-link/editor-rtl.min.css 710 B
build/styles/block-library/navigation-link/editor.css 1.27 kB
build/styles/block-library/navigation-link/editor.min.css 713 B
build/styles/block-library/navigation-link/style-rtl.css 579 B
build/styles/block-library/navigation-link/style-rtl.min.css 190 B
build/styles/block-library/navigation-link/style.css 579 B
build/styles/block-library/navigation-link/style.min.css 188 B
build/styles/block-library/navigation-overlay-close/style-rtl.css 260 B
build/styles/block-library/navigation-overlay-close/style-rtl.min.css 237 B
build/styles/block-library/navigation-overlay-close/style.css 260 B
build/styles/block-library/navigation-overlay-close/style.min.css 237 B
build/styles/block-library/navigation-submenu/editor-rtl.css 1.12 kB
build/styles/block-library/navigation-submenu/editor-rtl.min.css 295 B
build/styles/block-library/navigation-submenu/editor.css 1.12 kB
build/styles/block-library/navigation-submenu/editor.min.css 294 B
build/styles/block-library/navigation/editor-rtl.css 3.28 kB
build/styles/block-library/navigation/editor-rtl.min.css 2.28 kB
build/styles/block-library/navigation/editor.css 3.29 kB
build/styles/block-library/navigation/editor.min.css 2.28 kB
build/styles/block-library/navigation/style-rtl.css 3.59 kB
build/styles/block-library/navigation/style-rtl.min.css 2.52 kB
build/styles/block-library/navigation/style.css 3.59 kB
build/styles/block-library/navigation/style.min.css 2.5 kB
build/styles/block-library/nextpage/editor-rtl.css 799 B
build/styles/block-library/nextpage/editor-rtl.min.css 392 B
build/styles/block-library/nextpage/editor.css 800 B
build/styles/block-library/nextpage/editor.min.css 392 B
build/styles/block-library/page-list/editor-rtl.css 1.18 kB
build/styles/block-library/page-list/editor-rtl.min.css 356 B
build/styles/block-library/page-list/editor.css 1.18 kB
build/styles/block-library/page-list/editor.min.css 356 B
build/styles/block-library/page-list/style-rtl.css 207 B
build/styles/block-library/page-list/style-rtl.min.css 192 B
build/styles/block-library/page-list/style.css 207 B
build/styles/block-library/page-list/style.min.css 192 B
build/styles/block-library/paragraph/editor-rtl.css 315 B
build/styles/block-library/paragraph/editor-rtl.min.css 292 B
build/styles/block-library/paragraph/editor.css 314 B
build/styles/block-library/paragraph/editor.min.css 292 B
build/styles/block-library/paragraph/style-rtl.css 746 B
build/styles/block-library/paragraph/style-rtl.min.css 341 B
build/styles/block-library/paragraph/style.css 752 B
build/styles/block-library/paragraph/style.min.css 340 B
build/styles/block-library/playlist-track/style-rtl.css 453 B
build/styles/block-library/playlist-track/style-rtl.min.css 420 B
build/styles/block-library/playlist-track/style.css 453 B
build/styles/block-library/playlist-track/style.min.css 420 B
build/styles/block-library/playlist/editor-rtl.css 120 B
build/styles/block-library/playlist/editor-rtl.min.css 112 B
build/styles/block-library/playlist/editor.css 120 B
build/styles/block-library/playlist/editor.min.css 112 B
build/styles/block-library/playlist/style-rtl.css 1.52 kB
build/styles/block-library/playlist/style-rtl.min.css 1.42 kB
build/styles/block-library/playlist/style.css 1.52 kB
build/styles/block-library/playlist/style.min.css 1.42 kB
build/styles/block-library/post-author-biography/style-rtl.css 96 B
build/styles/block-library/post-author-biography/style-rtl.min.css 86 B
build/styles/block-library/post-author-biography/style.css 96 B
build/styles/block-library/post-author-biography/style.min.css 86 B
build/styles/block-library/post-author-name/style-rtl.css 76 B
build/styles/block-library/post-author-name/style-rtl.min.css 69 B
build/styles/block-library/post-author-name/style.css 76 B
build/styles/block-library/post-author-name/style.min.css 69 B
build/styles/block-library/post-author/editor-rtl.css 490 B
build/styles/block-library/post-author/editor-rtl.min.css 104 B
build/styles/block-library/post-author/editor.css 490 B
build/styles/block-library/post-author/editor.min.css 104 B
build/styles/block-library/post-author/style-rtl.css 213 B
build/styles/block-library/post-author/style-rtl.min.css 188 B
build/styles/block-library/post-author/style.css 214 B
build/styles/block-library/post-author/style.min.css 189 B
build/styles/block-library/post-comments-count/style-rtl.css 79 B
build/styles/block-library/post-comments-count/style-rtl.min.css 72 B
build/styles/block-library/post-comments-count/style.css 79 B
build/styles/block-library/post-comments-count/style.min.css 72 B
build/styles/block-library/post-comments-form/editor-rtl.css 104 B
build/styles/block-library/post-comments-form/editor-rtl.min.css 96 B
build/styles/block-library/post-comments-form/editor.css 104 B
build/styles/block-library/post-comments-form/editor.min.css 96 B
build/styles/block-library/post-comments-form/style-rtl.css 585 B
build/styles/block-library/post-comments-form/style-rtl.min.css 525 B
build/styles/block-library/post-comments-form/style.css 584 B
build/styles/block-library/post-comments-form/style.min.css 525 B
build/styles/block-library/post-comments-link/style-rtl.css 78 B
build/styles/block-library/post-comments-link/style-rtl.min.css 71 B
build/styles/block-library/post-comments-link/style.css 78 B
build/styles/block-library/post-comments-link/style.min.css 71 B
build/styles/block-library/post-content/style-rtl.css 68 B
build/styles/block-library/post-content/style-rtl.min.css 61 B
build/styles/block-library/post-content/style.css 68 B
build/styles/block-library/post-content/style.min.css 61 B
build/styles/block-library/post-date/style-rtl.css 69 B
build/styles/block-library/post-date/style-rtl.min.css 62 B
build/styles/block-library/post-date/style.css 69 B
build/styles/block-library/post-date/style.min.css 62 B
build/styles/block-library/post-excerpt/editor-rtl.css 78 B
build/styles/block-library/post-excerpt/editor-rtl.min.css 71 B
build/styles/block-library/post-excerpt/editor.css 78 B
build/styles/block-library/post-excerpt/editor.min.css 71 B
build/styles/block-library/post-excerpt/style-rtl.css 171 B
build/styles/block-library/post-excerpt/style-rtl.min.css 155 B
build/styles/block-library/post-excerpt/style.css 171 B
build/styles/block-library/post-excerpt/style.min.css 155 B
build/styles/block-library/post-featured-image/editor-rtl.css 1.14 kB
build/styles/block-library/post-featured-image/editor-rtl.min.css 719 B
build/styles/block-library/post-featured-image/editor.css 1.14 kB
build/styles/block-library/post-featured-image/editor.min.css 717 B
build/styles/block-library/post-featured-image/style-rtl.css 392 B
build/styles/block-library/post-featured-image/style-rtl.min.css 347 B
build/styles/block-library/post-featured-image/style.css 392 B
build/styles/block-library/post-featured-image/style.min.css 347 B
build/styles/block-library/post-navigation-link/style-rtl.css 234 B
build/styles/block-library/post-navigation-link/style-rtl.min.css 215 B
build/styles/block-library/post-navigation-link/style.css 245 B
build/styles/block-library/post-navigation-link/style.min.css 214 B
build/styles/block-library/post-template/style-rtl.css 1.27 kB
build/styles/block-library/post-template/style-rtl.min.css 441 B
build/styles/block-library/post-template/style.css 1.27 kB
build/styles/block-library/post-template/style.min.css 441 B
build/styles/block-library/post-terms/style-rtl.css 108 B
build/styles/block-library/post-terms/style-rtl.min.css 96 B
build/styles/block-library/post-terms/style.css 108 B
build/styles/block-library/post-terms/style.min.css 96 B
build/styles/block-library/post-time-to-read/style-rtl.css 77 B
build/styles/block-library/post-time-to-read/style-rtl.min.css 70 B
build/styles/block-library/post-time-to-read/style.css 77 B
build/styles/block-library/post-time-to-read/style.min.css 70 B
build/styles/block-library/post-title/style-rtl.css 175 B
build/styles/block-library/post-title/style-rtl.min.css 162 B
build/styles/block-library/post-title/style.css 175 B
build/styles/block-library/post-title/style.min.css 162 B
build/styles/block-library/preformatted/style-rtl.css 511 B
build/styles/block-library/preformatted/style-rtl.min.css 125 B
build/styles/block-library/preformatted/style.css 511 B
build/styles/block-library/preformatted/style.min.css 125 B
build/styles/block-library/pullquote/editor-rtl.css 146 B
build/styles/block-library/pullquote/editor-rtl.min.css 133 B
build/styles/block-library/pullquote/editor.css 146 B
build/styles/block-library/pullquote/editor.min.css 133 B
build/styles/block-library/pullquote/style-rtl.css 765 B
build/styles/block-library/pullquote/style-rtl.min.css 365 B
build/styles/block-library/pullquote/style.css 764 B
build/styles/block-library/pullquote/style.min.css 365 B
build/styles/block-library/pullquote/theme-rtl.css 195 B
build/styles/block-library/pullquote/theme-rtl.min.css 176 B
build/styles/block-library/pullquote/theme.css 195 B
build/styles/block-library/pullquote/theme.min.css 176 B
build/styles/block-library/query-pagination-numbers/editor-rtl.css 134 B
build/styles/block-library/query-pagination-numbers/editor-rtl.min.css 121 B
build/styles/block-library/query-pagination-numbers/editor.css 144 B
build/styles/block-library/query-pagination-numbers/editor.min.css 118 B
build/styles/block-library/query-pagination/editor-rtl.css 168 B
build/styles/block-library/query-pagination/editor-rtl.min.css 154 B
build/styles/block-library/query-pagination/editor.css 168 B
build/styles/block-library/query-pagination/editor.min.css 154 B
build/styles/block-library/query-pagination/style-rtl.css 254 B
build/styles/block-library/query-pagination/style-rtl.min.css 237 B
build/styles/block-library/query-pagination/style.css 265 B
build/styles/block-library/query-pagination/style.min.css 237 B
build/styles/block-library/query-title/style-rtl.css 71 B
build/styles/block-library/query-title/style-rtl.min.css 64 B
build/styles/block-library/query-title/style.css 71 B
build/styles/block-library/query-title/style.min.css 64 B
build/styles/block-library/query-total/style-rtl.css 71 B
build/styles/block-library/query-total/style-rtl.min.css 64 B
build/styles/block-library/query-total/style.css 71 B
build/styles/block-library/query-total/style.min.css 64 B
build/styles/block-library/query/editor-rtl.css 1.28 kB
build/styles/block-library/query/editor-rtl.min.css 438 B
build/styles/block-library/query/editor.css 1.28 kB
build/styles/block-library/query/editor.min.css 438 B
build/styles/block-library/quote/style-rtl.css 255 B
build/styles/block-library/quote/style-rtl.min.css 238 B
build/styles/block-library/quote/style.css 256 B
build/styles/block-library/quote/style.min.css 238 B
build/styles/block-library/quote/theme-rtl.css 253 B
build/styles/block-library/quote/theme-rtl.min.css 233 B
build/styles/block-library/quote/theme.css 254 B
build/styles/block-library/quote/theme.min.css 236 B
build/styles/block-library/read-more/style-rtl.css 146 B
build/styles/block-library/read-more/style-rtl.min.css 131 B
build/styles/block-library/read-more/style.css 146 B
build/styles/block-library/read-more/style.min.css 131 B
build/styles/block-library/reset-rtl.css 936 B
build/styles/block-library/reset-rtl.min.css 467 B
build/styles/block-library/reset.css 936 B
build/styles/block-library/reset.min.css 467 B
build/styles/block-library/rss/editor-rtl.css 144 B
build/styles/block-library/rss/editor-rtl.min.css 126 B
build/styles/block-library/rss/editor.css 144 B
build/styles/block-library/rss/editor.min.css 126 B
build/styles/block-library/rss/style-rtl.css 1.11 kB
build/styles/block-library/rss/style-rtl.min.css 284 B
build/styles/block-library/rss/style.css 1.12 kB
build/styles/block-library/rss/style.min.css 283 B
build/styles/block-library/search/editor-rtl.css 217 B
build/styles/block-library/search/editor-rtl.min.css 199 B
build/styles/block-library/search/editor.css 217 B
build/styles/block-library/search/editor.min.css 199 B
build/styles/block-library/search/style-rtl.css 1.1 kB
build/styles/block-library/search/style-rtl.min.css 665 B
build/styles/block-library/search/style.css 1.1 kB
build/styles/block-library/search/style.min.css 666 B
build/styles/block-library/search/theme-rtl.css 130 B
build/styles/block-library/search/theme-rtl.min.css 113 B
build/styles/block-library/search/theme.css 130 B
build/styles/block-library/search/theme.min.css 113 B
build/styles/block-library/separator/editor-rtl.css 106 B
build/styles/block-library/separator/editor-rtl.min.css 100 B
build/styles/block-library/separator/editor.css 106 B
build/styles/block-library/separator/editor.min.css 100 B
build/styles/block-library/separator/style-rtl.css 284 B
build/styles/block-library/separator/style-rtl.min.css 248 B
build/styles/block-library/separator/style.css 297 B
build/styles/block-library/separator/style.min.css 248 B
build/styles/block-library/separator/theme-rtl.css 226 B
build/styles/block-library/separator/theme-rtl.min.css 195 B
build/styles/block-library/separator/theme.css 226 B
build/styles/block-library/separator/theme.min.css 195 B
build/styles/block-library/shortcode/editor-rtl.css 1.1 kB
build/styles/block-library/shortcode/editor-rtl.min.css 286 B
build/styles/block-library/shortcode/editor.css 1.1 kB
build/styles/block-library/shortcode/editor.min.css 286 B
build/styles/block-library/site-logo/editor-rtl.css 1.12 kB
build/styles/block-library/site-logo/editor-rtl.min.css 696 B
build/styles/block-library/site-logo/editor.css 1.12 kB
build/styles/block-library/site-logo/editor.min.css 692 B
build/styles/block-library/site-logo/style-rtl.css 239 B
build/styles/block-library/site-logo/style-rtl.min.css 218 B
build/styles/block-library/site-logo/style.css 238 B
build/styles/block-library/site-logo/style.min.css 218 B
build/styles/block-library/site-tagline/editor-rtl.css 94 B
build/styles/block-library/site-tagline/editor-rtl.min.css 87 B
build/styles/block-library/site-tagline/editor.css 94 B
build/styles/block-library/site-tagline/editor.min.css 87 B
build/styles/block-library/site-tagline/style-rtl.css 72 B
build/styles/block-library/site-tagline/style-rtl.min.css 65 B
build/styles/block-library/site-tagline/style.css 72 B
build/styles/block-library/site-tagline/style.min.css 65 B
build/styles/block-library/site-title/editor-rtl.css 93 B
build/styles/block-library/site-title/editor-rtl.min.css 85 B
build/styles/block-library/site-title/editor.css 93 B
build/styles/block-library/site-title/editor.min.css 85 B
build/styles/block-library/site-title/style-rtl.css 153 B
build/styles/block-library/site-title/style-rtl.min.css 143 B
build/styles/block-library/site-title/style.css 153 B
build/styles/block-library/site-title/style.min.css 143 B
build/styles/block-library/social-link/editor-rtl.css 346 B
build/styles/block-library/social-link/editor-rtl.min.css 314 B
build/styles/block-library/social-link/editor.css 348 B
build/styles/block-library/social-link/editor.min.css 314 B
build/styles/block-library/social-links/editor-rtl.css 737 B
build/styles/block-library/social-links/editor-rtl.min.css 339 B
build/styles/block-library/social-links/editor.css 738 B
build/styles/block-library/social-links/editor.min.css 338 B
build/styles/block-library/social-links/style-rtl.css 1.57 kB
build/styles/block-library/social-links/style-rtl.min.css 1.51 kB
build/styles/block-library/social-links/style.css 1.57 kB
build/styles/block-library/social-links/style.min.css 1.51 kB
build/styles/block-library/spacer/editor-rtl.css 774 B
build/styles/block-library/spacer/editor-rtl.min.css 346 B
build/styles/block-library/spacer/editor.css 774 B
build/styles/block-library/spacer/editor.min.css 346 B
build/styles/block-library/spacer/style-rtl.css 55 B
build/styles/block-library/spacer/style-rtl.min.css 48 B
build/styles/block-library/spacer/style.css 55 B
build/styles/block-library/spacer/style.min.css 48 B
build/styles/block-library/style-rtl.css 21.6 kB
build/styles/block-library/style-rtl.min.css 18.1 kB
build/styles/block-library/style.css 21.7 kB
build/styles/block-library/style.min.css 18 kB
build/styles/block-library/tab-list/editor-rtl.css 107 B
build/styles/block-library/tab-list/editor-rtl.min.css 97 B
build/styles/block-library/tab-list/editor.css 107 B
build/styles/block-library/tab-list/editor.min.css 97 B
build/styles/block-library/tab-panel/style-rtl.css 238 B
build/styles/block-library/tab-panel/style-rtl.min.css 215 B
build/styles/block-library/tab-panel/style.css 238 B
build/styles/block-library/tab-panel/style.min.css 215 B
build/styles/block-library/tab-panels/style-rtl.css 76 B
build/styles/block-library/tab-panels/style-rtl.min.css 65 B
build/styles/block-library/tab-panels/style.css 76 B
build/styles/block-library/tab-panels/style.min.css 65 B
build/styles/block-library/tab/editor-rtl.css 160 B
build/styles/block-library/tab/editor-rtl.min.css 148 B
build/styles/block-library/tab/editor.css 160 B
build/styles/block-library/tab/editor.min.css 148 B
build/styles/block-library/tab/style-rtl.css 397 B
build/styles/block-library/tab/style-rtl.min.css 352 B
build/styles/block-library/tab/style.css 398 B
build/styles/block-library/tab/style.min.css 356 B
build/styles/block-library/table-of-contents/style-rtl.css 89 B
build/styles/block-library/table-of-contents/style-rtl.min.css 83 B
build/styles/block-library/table-of-contents/style.css 89 B
build/styles/block-library/table-of-contents/style.min.css 83 B
build/styles/block-library/table/editor-rtl.css 1.25 kB
build/styles/block-library/table/editor-rtl.min.css 394 B
build/styles/block-library/table/editor.css 1.25 kB
build/styles/block-library/table/editor.min.css 394 B
build/styles/block-library/table/style-rtl.css 1.06 kB
build/styles/block-library/table/style-rtl.min.css 641 B
build/styles/block-library/table/style.css 1.06 kB
build/styles/block-library/table/style.min.css 640 B
build/styles/block-library/table/theme-rtl.css 985 B
build/styles/block-library/table/theme-rtl.min.css 152 B
build/styles/block-library/table/theme.css 985 B
build/styles/block-library/table/theme.min.css 152 B
build/styles/block-library/tabs/style-rtl.css 64 B
build/styles/block-library/tabs/style-rtl.min.css 57 B
build/styles/block-library/tabs/style.css 64 B
build/styles/block-library/tabs/style.min.css 57 B
build/styles/block-library/tag-cloud/style-rtl.css 283 B
build/styles/block-library/tag-cloud/style-rtl.min.css 248 B
build/styles/block-library/tag-cloud/style.css 283 B
build/styles/block-library/tag-cloud/style.min.css 248 B
build/styles/block-library/template-part/editor-rtl.css 1.2 kB
build/styles/block-library/template-part/editor-rtl.min.css 368 B
build/styles/block-library/template-part/editor.css 1.2 kB
build/styles/block-library/template-part/editor.min.css 368 B
build/styles/block-library/template-part/theme-rtl.css 492 B
build/styles/block-library/template-part/theme-rtl.min.css 113 B
build/styles/block-library/template-part/theme.css 492 B
build/styles/block-library/template-part/theme.min.css 113 B
build/styles/block-library/term-count/style-rtl.css 70 B
build/styles/block-library/term-count/style-rtl.min.css 63 B
build/styles/block-library/term-count/style.css 70 B
build/styles/block-library/term-count/style.min.css 63 B
build/styles/block-library/term-description/style-rtl.css 138 B
build/styles/block-library/term-description/style-rtl.min.css 126 B
build/styles/block-library/term-description/style.css 138 B
build/styles/block-library/term-description/style.min.css 126 B
build/styles/block-library/term-name/style-rtl.css 69 B
build/styles/block-library/term-name/style-rtl.min.css 62 B
build/styles/block-library/term-name/style.css 69 B
build/styles/block-library/term-name/style.min.css 62 B
build/styles/block-library/term-template/editor-rtl.css 267 B
build/styles/block-library/term-template/editor-rtl.min.css 225 B
build/styles/block-library/term-template/editor.css 267 B
build/styles/block-library/term-template/editor.min.css 225 B
build/styles/block-library/term-template/style-rtl.css 124 B
build/styles/block-library/term-template/style-rtl.min.css 114 B
build/styles/block-library/term-template/style.css 124 B
build/styles/block-library/term-template/style.min.css 114 B
build/styles/block-library/text-columns/editor-rtl.css 481 B
build/styles/block-library/text-columns/editor-rtl.min.css 95 B
build/styles/block-library/text-columns/editor.css 481 B
build/styles/block-library/text-columns/editor.min.css 95 B
build/styles/block-library/text-columns/style-rtl.css 177 B
build/styles/block-library/text-columns/style-rtl.min.css 165 B
build/styles/block-library/text-columns/style.css 177 B
build/styles/block-library/text-columns/style.min.css 165 B
build/styles/block-library/theme-rtl.css 1.59 kB
build/styles/block-library/theme-rtl.min.css 715 B
build/styles/block-library/theme.css 1.6 kB
build/styles/block-library/theme.min.css 719 B
build/styles/block-library/verse/style-rtl.css 155 B
build/styles/block-library/verse/style-rtl.min.css 137 B
build/styles/block-library/verse/style.css 155 B
build/styles/block-library/verse/style.min.css 137 B
build/styles/block-library/video/editor-rtl.css 839 B
build/styles/block-library/video/editor-rtl.min.css 428 B
build/styles/block-library/video/editor.css 840 B
build/styles/block-library/video/editor.min.css 428 B
build/styles/block-library/video/style-rtl.css 1.02 kB
build/styles/block-library/video/style-rtl.min.css 202 B
build/styles/block-library/video/style.css 1.02 kB
build/styles/block-library/video/style.min.css 202 B
build/styles/block-library/video/theme-rtl.css 967 B
build/styles/block-library/video/theme-rtl.min.css 134 B
build/styles/block-library/video/theme.css 967 B
build/styles/block-library/video/theme.min.css 134 B
build/styles/commands/style-rtl.css 2.07 kB
build/styles/commands/style-rtl.min.css 1.17 kB
build/styles/commands/style.css 2.06 kB
build/styles/commands/style.min.css 1.17 kB
build/styles/components/style-rtl.css 17.8 kB
build/styles/components/style-rtl.min.css 14.7 kB
build/styles/components/style.css 17.9 kB
build/styles/components/style.min.css 14.8 kB
build/styles/customize-widgets/style-rtl.css 2.35 kB
build/styles/customize-widgets/style-rtl.min.css 1.44 kB
build/styles/customize-widgets/style.css 2.35 kB
build/styles/customize-widgets/style.min.css 1.44 kB
build/styles/edit-post/classic-rtl.css 1.29 kB
build/styles/edit-post/classic-rtl.min.css 425 B
build/styles/edit-post/classic.css 1.31 kB
build/styles/edit-post/classic.min.css 428 B
build/styles/edit-post/experimental-admin-bar-in-editor-rtl.css 550 B
build/styles/edit-post/experimental-admin-bar-in-editor-rtl.min.css 513 B
build/styles/edit-post/experimental-admin-bar-in-editor.css 551 B
build/styles/edit-post/experimental-admin-bar-in-editor.min.css 514 B
build/styles/edit-post/style-rtl.css 3.8 kB
build/styles/edit-post/style-rtl.min.css 2.48 kB
build/styles/edit-post/style.css 3.81 kB
build/styles/edit-post/style.min.css 2.49 kB
build/styles/edit-site/experimental-admin-bar-in-editor-rtl.css 502 B
build/styles/edit-site/experimental-admin-bar-in-editor-rtl.min.css 474 B
build/styles/edit-site/experimental-admin-bar-in-editor.css 502 B
build/styles/edit-site/experimental-admin-bar-in-editor.min.css 474 B
build/styles/edit-site/style-rtl.css 21.3 kB
build/styles/edit-site/style-rtl.min.css 17.4 kB
build/styles/edit-site/style.css 21.3 kB
build/styles/edit-site/style.min.css 17.4 kB
build/styles/edit-widgets/style-rtl.css 4.85 kB
build/styles/edit-widgets/style-rtl.min.css 3.52 kB
build/styles/edit-widgets/style.css 4.85 kB
build/styles/edit-widgets/style.min.css 3.52 kB
build/styles/editor/style-rtl.css 29.4 kB
build/styles/editor/style-rtl.min.css 24.9 kB
build/styles/editor/style.css 29.4 kB
build/styles/editor/style.min.css 24.9 kB
build/styles/format-library/style-rtl.css 735 B
build/styles/format-library/style-rtl.min.css 326 B
build/styles/format-library/style.css 746 B
build/styles/format-library/style.min.css 326 B
build/styles/list-reusable-blocks/style-rtl.css 1.03 kB
build/styles/list-reusable-blocks/style-rtl.min.css 210 B
build/styles/list-reusable-blocks/style.css 1.03 kB
build/styles/list-reusable-blocks/style.min.css 211 B
build/styles/media-utils/style-rtl.css 2.12 kB
build/styles/media-utils/style-rtl.min.css 1.2 kB
build/styles/media-utils/style.css 2.11 kB
build/styles/media-utils/style.min.css 1.2 kB
build/styles/notices/style-rtl.css 121 B
build/styles/notices/style-rtl.min.css 106 B
build/styles/notices/style.css 121 B
build/styles/notices/style.min.css 106 B
build/styles/nux/style-rtl.css 1.48 kB
build/styles/nux/style-rtl.min.css 622 B
build/styles/nux/style.css 1.5 kB
build/styles/nux/style.min.css 618 B
build/styles/patterns/style-rtl.css 1.46 kB
build/styles/patterns/style-rtl.min.css 611 B
build/styles/patterns/style.css 1.46 kB
build/styles/patterns/style.min.css 611 B
build/styles/preferences/style-rtl.css 1.26 kB
build/styles/preferences/style-rtl.min.css 415 B
build/styles/preferences/style.css 1.26 kB
build/styles/preferences/style.min.css 415 B
build/styles/reusable-blocks/style-rtl.css 1.11 kB
build/styles/reusable-blocks/style-rtl.min.css 275 B
build/styles/reusable-blocks/style.css 1.11 kB
build/styles/reusable-blocks/style.min.css 275 B
build/styles/widgets/style-rtl.css 2.05 kB
build/styles/widgets/style-rtl.min.css 1.16 kB
build/styles/widgets/style.css 2.06 kB
build/styles/widgets/style.min.css 1.16 kB

compressed-size-action

Copy link
Copy Markdown
Contributor

@andrewserong andrewserong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is testing well for me! I was going to ask how heavy the upstream library is, and then I noticed that it's from your own repo, so I assume you're quite comfortable with it 😄

The main question I have is to do with the idea that if most uploaded JPEGs are not UltraHDR, how expensive is the operation to detect it? If it's very cheap, then this seems like a great addition. I've left a comment, but before I looked at the code, my assumption is that this kind of operation would flag if it succeeds / does something, but wouldn't warn if it can't find an UltraHDR data.

What do you think?

This is all still behind an experiment of course, so don't let my questions here stop you from progressing! (Also I'll be AFK early next week, so apologies if my reply is delayed until mid-week)

Comment on lines +460 to +464
} catch ( error ) {
// If UltraHDR detection fails, continue with regular upload
// eslint-disable-next-line no-console
console.warn( 'UltraHDR detection failed:', error );
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting this warning for uploading normal (non UltraHDR) jpegs from my desktop. Given that the majority of jpegs won't be ultra HDR, should we just fail silently here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is mainly for debugging purposes and I will remove before merging to trunk.

@adamsilverstein
Copy link
Copy Markdown
Member Author

Nice, this is testing well for me! I was going to ask how heavy the upstream library is, and then I noticed that it's from your own repo, so I assume you're quite comfortable with it 😄

I am comfortable with it working based on the tests, although I also plan to ask for help doing manual testing to verify it properly handles real world images.

The main question I have is to do with the idea that if most uploaded JPEGs are not UltraHDR, how expensive is the operation to detect it? If it's very cheap, then this seems like a great addition. I've left a comment, but before I looked at the code, my assumption is that this kind of operation would flag if it succeeds / does something, but wouldn't warn if it can't find an UltraHDR data.

That is a great question and worth investigating more. I will review the detection logic to see if it can be optimized. Also, I'm still not certain about what we should output. My assumption is that UltraHDR JPEGs are decoder compatible with existing JPEGs so we would want to output UltraHDR for uploaded UltraHDR. Then again, some users may prefer to use the SDR version for their website exclusively because they want smaller file sizes and don't care about HDR. We might need a new way for developers to implement that since the mime type is still image/jpeg and out=r image_editor_output_format filter is based on transforming mime types. I plan to ask photography expert and UltraHDR fan @gregbenz for advice in this regard once I have a completely testable solution.

This is all still behind an experiment of course, so don't let my questions here stop you from progressing! (Also I'll be AFK early next week, so apologies if my reply is delayed until mid-week)

Hopefully for something fun!

@gregbenz
Copy link
Copy Markdown

@adamsilverstein libultrahdr includes a probe() method to validate that required components are present without decoding.
google/libultrahdr#368

I haven't tested it for performance, but it may serve as inspiration.

Gain maps require an auxiliary image. You could check the header and reject if that's missing.

If it exists, you could then further check for a supported gain map (ie a more robust check, but you've already quickly skipped most images that aren't relevant). There are two kinds of map encoding supported by libultra: (a) ISO standard gain maps and (b) gain maps encoded with the Android XMP spec.

The ISO encoding is widely used for new images now and has been for a while in most encoders. Many now dual encode (as the auxiliary image is the same and you're just writing redundant data - binary in the aux image for ISO and standard XMP for the Android spec). The only thing you'd miss by skipping XMP would be older images captured on Android or exported with old versions of Adobe software (Apple has a proprietary method they used pre-ISO and it is not supported by libultra). I believe skipping XMP would generally be ok to do, as it is a very limited edge case (and the impact would be that transcoding falls back to SDR rather than total failure).

@gregbenz
Copy link
Copy Markdown

@adamsilverstein If the source includes a supported gain map, the output should preserve it by default. SharpJS is working towards a keepGainMap() method which should do this, however, I'm not sure how much guidance libvips needs. Coordinating with SharpJS may make sense here, as both efforts are likely chasing the same goals for default transcoding (ie ability to do basic crop/resize/compress while retaining an output which shows high fidelity to the original).

Questions for transcoding will inevitably come up around tuning (compression of the base image / map). Testing to make sure the final result is ok based on the compression applied to both the base and map will be an important step to validate quality vs size objectives. Existing approaches for the base image probably translate well, and this is probably mostly a question of how to compress the map.

Aside from that, most of the options chosen for encoding should remain as they were in the source. The metadata should be unchanged (HDR capacity, offsets, ranges, etc). The map scaling (1:1 vs 1:2 or 1:4) and number of channels (1 for luminosity only map vs 3 for full color) should remain the same. It should not alter sub-sampling (ie keep 444 if that's how it was encoded as the map is not a color image and the assumptions behind sub-sampling are not applicable in this domain, and can cause artifacts if altered).

An affordance for aggressive compression of the image (including loss of HDR) may be useful for some users / workflows, but is not required and could get complicated. There are also other ways beyond stripping the map which can compress the image without stripping HDR, but they involve quality tradeoffs that would need careful assessment. For example, you could downgrade the map from 1:1 resolution in full color to a 1:2 map with luminosity only. That will cause loss of high frequency detail in the HDR rendition, as well as color error (which may be a small or significant issue depending on the relationship of the SDR to the HDR rendition).

Due to the effort, complexity, and risk of confusion here, it may be best that initial support just preserve the gain map and not use more complex options to compress the image further. That can be managed now via the encoding of the file uploaded to WordPress (upload SDR if you only want SDR, phone captures are already low resolution luminosity maps, etc). Advanced transcoding for compression might best be left for 3rd-party plugins to address.

@adamsilverstein
Copy link
Copy Markdown
Member Author

@adamsilverstein libultrahdr includes a probe() method to validate that required components are present without decoding.

great, thanks for the tip - i will take a look at that.

Gain maps require an auxiliary image. You could check the header and reject if that's missing.

👍🏼

Due to the effort, complexity, and risk of confusion here, it may be best that initial support just preserve the gain map and not use more complex options to compress the image further.

Right, be default we will always try to use the uploaded format for the output (so uploaded UltraHDR should output UltraHDR). My pondering was more about how would enable developers to choose to extract only the SDR image for output/front end if thats what they wanted. The current output mapping won't work, so we may need a more explicit filter to choose HDR or SDR encoding when an UltraHDR is uploaded.

@adamsilverstein
Copy link
Copy Markdown
Member Author

@adamsilverstein libultrahdr includes a probe() method to validate that required components are present without decoding.

great, thanks for the tip - i will take a look at that.

I created an issue to add a probe mode to lib-open-ultrahdr:
adamsilverstein/lib-open-ultrahdr#5

@adamsilverstein
Copy link
Copy Markdown
Member Author

@adamsilverstein libultrahdr includes a probe() method to validate that required components are present without decoding.

Thanks again for the tip @gregbenz - I added the probe feature in adamsilverstein/lib-open-ultrahdr#6 based on the libultrahdr approach

@adamsilverstein
Copy link
Copy Markdown
Member Author

adamsilverstein commented Jan 30, 2026

The main question I have is to do with the idea that if most uploaded JPEGs are not UltraHDR, how expensive is the operation to detect it? If it's very cheap, then this seems like a great addition. I've left a comment, but before I looked at the code, my assumption is that this kind of operation would flag if it succeeds / does something, but wouldn't warn if it can't find an UltraHDR data.

Thanks again for the question @andrewserong - it turns out libultrahdr has a probe feature explicitly to determine this without the expensive decoding phase. I added a similar feature to lib-open-ultrahdr in adamsilverstein/lib-open-ultrahdr#6 and will update the PR to leverage that for detection early in the flow.

@adamsilverstein adamsilverstein self-assigned this Mar 17, 2026
@adamsilverstein adamsilverstein added the [Status] In Progress Tracking issues with work in progress label Mar 17, 2026
Cover the new UltraHDR pipeline at three levels.

Vips unit (packages/vips/src/test/ultrahdr.ts): mock wasm-vips and
verify getUltraHdrInfo returns dims + log2-stop capacity for valid
inputs, returns null on missing gain map / decode failure, and falls
back to zero capacity when the metadata field is absent. Verify
resizeImage with isUltraHdr=true routes through uhdrloadBuffer +
thumbnailImage + uhdrsaveBuffer instead of newFromBuffer +
thumbnailBuffer + writeToBuffer.

Upload Media unit (packages/upload-media/src/store/test/
private-actions.js): mock vipsGetUltraHdrInfo and exercise the
detectUltraHdr thunk. Cover: positive detection writes
attachment.meta.ultrahdr + hdr_capacity, no metadata change when not
UltraHDR, graceful pass-through when probing throws, normalization
when REST returns meta as []  (rather than {}), and early return
when the queue item is missing.

E2E (test/e2e/specs/editor/various/client-side-media-processing.spec
.js): upload a synthesized 1024x768 UltraHDR JPEG fixture, fetch the
medium sub-size from REST, and re-probe it through wasm-vips to
confirm the gain map survived the resize. The fixture is generated
deterministically by .gen-ultrahdr-fixture.mjs (committed alongside
so it can be regenerated without vendoring a third-party binary).
Comment thread packages/vips/src/index.ts Outdated
smartCrop = false,
quality = 0.82
quality = 0.82,
isUltraHdr = false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this. Since uhdrload*() has a higher priority than jpegload*(), you can continue using vips.Image.newFromBuffer() (or vips.Image.thumbnailBuffer()). Likewise, jpegsave*() automatically delegates to uhdrsave* when the image contains a gainmap or uses the scRGB color space.

Here's an example to help you get started:
https://gist.github.com/kleisauke/f90c05b839ef871cbb97b294e9435bf7

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic, thank you!

Comment thread packages/vips/src/index.ts Outdated
Comment thread packages/vips/src/index.ts Outdated
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to crop the gainmap, if present. An example is available here:
https://www.libvips.org/API/current/uhdr.html#a-la-carte-processing

adamsilverstein and others added 2 commits May 9, 2026 16:57
Co-authored-by: Kleis Auke Wolthuizen <github@kleisauke.nl>
Address kleisauke's review on PR #74873:

- Drop the explicit isUltraHdr branching in resizeImage. uhdrload* has
  higher priority than jpegload* in libvips, so newFromBuffer and
  thumbnailBuffer auto-detect UltraHDR JPEGs and decode the gain map
  alongside the base image. jpegsave* delegates to uhdrsave* on output
  when a gain map is attached, so writeToBuffer handles the save side
  too. Removes the parameter from vipsResizeImage at every layer.

- Crop the gain map alongside the main image on positional crop. Scale
  crop coordinates to the gain map's resolution, since the gain map can
  be smaller than the main image. Follows libvips's a-la-carte
  processing example:
  https://www.libvips.org/API/current/uhdr.html#a-la-carte-processing

- Clean up the keep:'icc|gainmap' save option formatting that was
  applied as a raw suggestion in the previous commit. Extend the
  ForeignKeep type to include 'gainmap' and pipe-combined values.

Update tests to cover the simplified path, the new gain-map crop
branch, and the keep:'icc|gainmap' save option.
@adamsilverstein
Copy link
Copy Markdown
Member Author

Thanks again for the review @kleisauke — addressed all three points in f17ac14:

  1. Drop isUltraHdr flag, rely on uhdrload*/uhdrsave* priority. resizeImage now uses plain newFromBuffer/thumbnailBuffer to load and writeToBuffer('.jpg', …) to save — libvips auto-routes UltraHDR JPEGs through uhdrload/uhdrsave based on loader priority and gain-map presence. The isUltraHdr parameter is removed from resizeImage, vipsResizeImage (worker), and the upload-media util.

  2. Crop the gain map alongside the main image. applyResizeAndCrop now follows the à la carte pattern: when the cropped image has a gainmap, it scales crop coordinates by gainmap.{width,height} / image.{width,height}, crops the gain map, then copy().setImage('gainmap', …) on the result. Skipped when no gain map is present.

  3. keep: 'icc|gainmap' formatting fix. Cleaned up the indentation/comment duplication from the suggestion-merge commit and extended the local ForeignKeep type to accept 'gainmap' plus pipe-combined values.

Tests in packages/vips/src/test/ultrahdr.ts cover the simplified path, the gain-map-aware crop, and the save option. All 211 vips/upload-media unit tests pass; lint and tsc are clean.

Apply prettier formatting and add eslint-disable directives for the
legitimate console output and wasm-vips import (the script is a
manually-run fixture generator, not part of CI).
The cache pins decoded image references, which prevents libheif from
releasing its AVIF decoder state across iterations. On a 3000x2000
AVIF input, the WASM heap exhausts after a few runs and the AVIF
encode fails with 'heif: Memory allocation error'. Calling
Cache.max(0) once after init resolves it; the cache offered no value
here since each iteration uses a fresh thumbnail call.
Resolve conflicts:

- packages/upload-media/CHANGELOG.md: keep UltraHDR Enhancement under
  Unreleased, with the new 0.31.0 scaled-suffix bug fix entry below.
- packages/vips/CHANGELOG.md: keep UltraHDR New Features under Unreleased,
  followed by the 1.6.0 release header.
- packages/upload-media/src/store/private-actions.ts: keep UltraHDR
  detection step at the top of prepareItem(), and adopt trunk's removal
  of the client-side bigImageSizeThreshold ResizeCrop. Threshold scaling
  now happens as a sideload in generateThumbnails(), so the original is
  uploaded unchanged and the un-suffixed basename feeds sub-size naming.
@adamsilverstein
Copy link
Copy Markdown
Member Author

@gregbenz this should be ready for testing and should also be testable using Playground as we resolved the incompatibility there. Try https://playground.wordpress.net/?gutenberg-pr=74873

@gregbenz
Copy link
Copy Markdown

gregbenz commented May 15, 2026

@adamsilverstein Thank you!

I am seeing that the basic functionality works. I drag and drop HDR JPGs and am able to pick smaller than full sizes and see HDR.

I see a couple of issues:

  • The down-scaled image is low quality. Where in the code base here are the parameters set for quality, etc? Looks like it needs some tweaking. As a reference, I'm seeing good results with wasm-vips as implemented here: https://gregbenzphotography.com/test/wasm-vips-hdr-demo/
  • When I use the crop tool (the visual icon over the image), the result discards HDR. Cropping works fine for me on the same demo URL, so this should just be a matter of how wasm-vips is being invoked to get cropping support.

My quick test in the Playground: https://playground.wordpress.net/scope:kind-quiet-country/2026/05/15/greg-hdr-test/

@adamsilverstein
Copy link
Copy Markdown
Member Author

adamsilverstein commented May 15, 2026

Thanks for testing @gregbenz

The down-scaled image is low quality. Where in the code base here are the parameters set for quality, etc?

This should default to 82 quality and is adjustable using a code filter, there is no UI built into WordPress to adjust, but you can likely install a plugin to add that. eg install https://wordpress.org/plugins/image-quality/ on the playground instance.

Separately while testing this I noticed a bug where the srcset isn't being generated correctly, even though I see all of the sub-sized images created on the backend. I am investigating this separately as it affects trunk and must have been introduced recently.

When I use the crop tool (the visual icon over the image), the result discards HDR. Cropping works fine for me on the same demo URL, so this should just be a matter of how wasm-vips is being invoked to get cropping support.

I haven't worked on the cropping functionality at all, I know there is active work on that at the moment. It might be worth testing this in the new experimental media editor, accessible under the Gutenberg->Experiments menu:

image

@gregbenz
Copy link
Copy Markdown

gregbenz commented May 18, 2026

@adamsilverstein I am seeing that the editor does not match the rendered page. When editing, there is no srcset and the lowest res image is used. It is rather low quality.

When viewing the published page, a srcset is used and what I see shows a vastly better image. It looks the same size on screen, but is appears to be pulling from a higher res image and downsampling in the browser.

Shouldn't the editor use srcset to render a preview closer to the live page?

Here is the rendered image element:

<img decoding="async" width="150" height="150" src="https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-150x150.jpg" alt="" class="wp-image-13" srcset="https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-150x150.jpg 150w, https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-768x768.jpg 768w, https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-1024x1024.jpg 1024w, https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-300x300.jpg 300w, https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz.jpg 1080w" sizes="(max-width: 150px) 100vw, 150px">

@gregbenz
Copy link
Copy Markdown

@adamsilverstein I'm not seeing that image-quality plugin impact results. If I install it and set it to 1% or 100% quality and then upload an image to a post, I see the same results. Perhaps the way the quality setting is passed normally does not flow through here? Or I may not be using it properly in this context.

However, I think the quality issue I see is something else. When I test my own implementation of wasm-vips (https://gregbenzphotography.com/test/wasm-vips-hdr-demo/), I get a much higher quality result for the 150x150 thumbnail at 82%. My image is 25K vs 13K when WordPress beta does the resizing. The quality factor applied to the gain map does not appear consistent what is being applied to the base image (my relevant JS for transcoding via wasm-vips can be seen with a link at the bottom of that page). That said, I'm not getting down to 13KB without vastly lower quality settings, so something is not apples to apples here.

Try using the "load P3 sample" on my site. That same image resized in the WordPress playground shows soft green text near the top. The quality from the WP beta may ultimately be worth it given the size (the loss of quality here is much less for image content than this part of the test pattern), but I think it would be good to understand the discrepancy.

Separately for testing efficiently: In the playground, I'm not sure how to download the resized asset (the way the URL shows on page is not standard and the browser shows an error when saving: "file wasn't available on site", and the media library only shows the full-sized asset). I found a very convoluted solution via JS, but if you have any tips to pull the transcoded image, that would be helpful. The colon in the image URL in the playground seems to be an issue.

@adamsilverstein
Copy link
Copy Markdown
Member Author

@adamsilverstein I'm not seeing that image-quality plugin impact results. If I install it and set it to 1% or 100% quality and then upload an image to a post, I see the same results. Perhaps the way the quality setting is passed normally does not flow through here? Or I may not be using it properly in this context.

However, I think the quality issue I see is something else. When I test my own implementation of wasm-vips (https://gregbenzphotography.com/test/wasm-vips-hdr-demo/), I get a much higher quality result for the 150x150 thumbnail at 82%. My image is 25K vs 13K when WordPress beta does the resizing. The quality factor applied to the gain map does not appear consistent what is being applied to the base image (my relevant JS for transcoding via wasm-vips can be seen with a link at the bottom of that page). That said, I'm not getting down to 13KB without vastly lower quality settings, so something is not apples to apples here.

Hmm, maybe the quality setting isn't being applied to the gain map? I'll have to look into what options there are.

Try using the "load P3 sample" on my site. That same image resized in the WordPress playground shows soft green text near the top. The quality from the WP beta may ultimately be worth it given the size (the loss of quality here is much less for image content than this part of the test pattern), but I think it would be good to understand the discrepancy.

can you give me a link to the image or upload it here?

Separately for testing efficiently: In the playground, I'm not sure how to download the resized asset (the way the URL shows on page is not standard and the browser shows an error when saving: "file wasn't available on site", and the media library only shows the full-sized asset). I found a very convoluted solution via JS, but if you have any tips to pull the transcoded image, that would be helpful. The colon in the image URL in the playground seems to be an issue.

You should be able to use the urls in the html srcset to download each image, except your urls do look odd, eg https://playground.wordpress.net/scope:creative-sunny-town/wp-content/uploads/2026/05/ISO-JPG-P3-transcoding-test-Greg-Benz-1024x1024.jpg the scope part seems different than what I'm used to. Can you test with a regular jpeg in playground, this may not be related to the code we are trying to test. cc: @adamziel may know better what to expect here.

I can try to set up a regular test environment for you with this PR active, it may work differently than in playground.

@gregbenz
Copy link
Copy Markdown

@adamsilverstein See gainmapQuality in gregbenzphotography.com/test/wasm-vips-hdr-demo/wasm-vips-hdr-transcode.js for how I'm controlling it independently of the base quality (I set same as default but my demo page allows independent control).

The "scope:" in the image URL shows up with standard JPGs, I'm assuming this is the nature of the playground environment.

@adamsilverstein
Copy link
Copy Markdown
Member Author

hmmm. i thought we already returned the filtered wp_editor_set_quality value from the original upload. we may need to implement that, similar to #75784.

with that in place, we can:

  • sideload the original gif
  • the rest api response will contain the correct image quality to use for the image. in the rest callback the filter is applied with the mime type
  • if the client side is going to generate multiple sub sizes, the endpoint runs the filter against each size so it can include the size context (see https://developer.wordpress.org/reference/hooks/wp_editor_set_quality/). the quality setting is returned for each size where it does not match the default.

# Conflicts:
#	packages/upload-media/src/store/private-actions.ts
@adamsilverstein
Copy link
Copy Markdown
Member Author

hmmm. i thought we already returned the filtered wp_editor_set_quality value from the original upload. we may need to implement that, similar to #75784.

Working on a fix in #78419

Resolve conflicts:
- packages/vips/src/index.ts: keep getUltraHdrInfo; drop batchResizeImage
  (removed in trunk's 2.0.0 breaking change, #77247).
- packages/vips/CHANGELOG.md: keep UltraHDR entries under Unreleased;
  place trunk's 2.0.0 (2026-05-27) breaking change section below.
- packages/upload-media/CHANGELOG.md: keep UltraHDR enhancement under
  Unreleased; place trunk's 0.32.0 (2026-05-27) bug fix section below.
@adamsilverstein
Copy link
Copy Markdown
Member Author

adamsilverstein commented May 27, 2026

Thanks for the careful reviews, @kleisauke and @andrewserong! Just rebased on trunk (resolving the 2.0.0 batchResizeImage removal). Here's where things stand on the open threads — all of them are addressed in the current revision:

@kleisaukepackages/vips/src/index.ts

  1. Drop isUltraHdr routing — confirmed. resizeImage now uses plain vips.Image.newFromBuffer() / vips.Image.thumbnailBuffer() and lets libvips's uhdrload*() priority handle detection. No more isUltraHdr flag on the API. (packages/vips/src/index.ts L417, L432)
  2. keep: 'icc|gainmap' — applied in buildSaveOptions, with the comment you suggested. (L341-L361)
  3. Crop the gainmap on positional cropapplyResizeAndCrop now scales the crop rect to the gainmap's resolution and re-attaches it via setImage('gainmap', ...) on a copy() of the cropped main image (matching the à-la-carte processing example). (L308-L331)

The only remaining UltraHDR-specific helper in @wordpress/vips is getUltraHdrInfo() — it's still useful in @wordpress/upload-media to (a) record HDR metadata on the attachment (ultrahdr: true, hdr_capacity) and (b) gate format transcoding so we don't accidentally convert UltraHDR JPEGs to AVIF/WebP and strip the gain map.

@andrewserongpackages/upload-media/src/store/

  1. CreateUltraHdr usage — gone entirely (grep returns no matches anywhere in packages/). The current code only uses OperationType.DetectUltraHdr, which is queued once in prepareItem and dispatched in the operation loop.
  2. detectUltraHdr re-queuing operations — no longer does that. The current thunk just probes the file, marks the item in an ultraHdrItems Set, writes ultrahdr/hdr_capacity to attachment meta, and calls finishOperation. Operation queueing is centralized in prepareItem. (private-actions.ts L813-L852)
  3. try/catch scope — narrowed to just the probe (arrayBuffer() + vipsGetUltraHdrInfo()). The dispatch happens outside the try. (L821-L826)
  4. Debug warning for non-UltraHDR JPEGs — removed. The catch block is now silent (with a comment) since most JPEGs aren't UltraHDR and that's the expected path.

Re-requesting review when you both have a moment 🙏

adamsilverstein and others added 2 commits May 27, 2026 15:17
getVips() calls vipsInstance.Cache.max(0) to disable libvips's
operation cache. Without it in the wasm-vips mock, the first
getUltraHdrInfo test threw inside getVips, never invoking
uhdrloadBuffer. Because the queued mockReturnValueOnce values
were not consumed and jest.clearAllMocks() does not drain them,
the next tests then read stale mock returns and produced
unexpected results.
Copy link
Copy Markdown

@kleisauke kleisauke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a WordPress expert, but the wasm-vips part and its usage w.r.t. UltraHDR processing looks good to me.

@adamsilverstein
Copy link
Copy Markdown
Member Author

@gregbenz this is ready for additional testing

@andrewserong
Copy link
Copy Markdown
Contributor

Thanks for the updates @adamsilverstein! Just double-checking but is the intention that generated sub-size images retain their gain maps? In manual testing (with one Greg's lovely photos: https://gregbenzphotography.com/hdr-gain-map-gallery/) it appears that the uploaded file has the gain map, but if I go to view the generated subsize jpegs on my phone (the only HDR display I have unfortunately!), they appear to be rendering in SDR and the highlights are no longer super bright.

Is it working for you? I tried running npm install again to keep my environment up to date and rebuilt my local env to double check, but it's possible I might have missed something.

(Code-wise this is looking nice, good work simplifying things!)


### Enhancement

- UltraHDR (ISO 21496-1 gain map) JPEGs are now detected and resized via libvips's native `uhdrload`/`uhdrsave` pipeline. The standalone `open-ultrahdr` and `open-ultrahdr-wasm` dependencies have been removed; gain maps are preserved automatically through the existing resize step ([#74873](https://github.com/WordPress/gutenberg/pull/74873)).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standalone open-ultrahdr and open-ultrahdr-wasm dependencies have been removed;

Tiniest of nits for this changelog entry, mightn't even be worth updating, but we never landed those did we? We can likely remove that sentence.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right! will do.

Comment on lines +4 to -7
const { promisify } = require( 'util' );
const { confirm } = require( '@inquirer/prompts' );
const checkSync = require( 'check-node-version' );
const tools = require( 'check-node-version/tools' );
const { promisify } = require( 'util' );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not an issue at all, but this change seems unintentional / a stray leftover from when we needed to build the separate libraries?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, will restore.

Comment on lines +66 to +72
/**
* Tracks parent item IDs whose source file is an UltraHDR JPEG so that
* sub-size resize operations can route through libvips's uhdrload/uhdrsave
* to preserve the gain map. Entries are cleared when the parent finalizes.
*/
const ultraHdrItems = new Set< QueueItemId >();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably so minor it's not really worth mentioning, but I noticed with a Claude-assisted review that the items in this Set get cleared when the processing is successful, but not when it's cancelled. It doesn't seem that having the set increase over time will cause any issues, but just thought I'd mention it in case it's worth clearing when we cancel an item. Though that appears to happen in actions.ts rather than private-actions.ts so would involve sharing the set across multiple modules, which might not be ideal.

In any case, probably not much of an issue, but thought I'd flag it just in case 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Client Side Media Media processing in the browser with WASM [Status] In Progress Tracking issues with work in progress [Type] Enhancement A suggestion for improvement.

Projects

Status: 🔎 Needs Review

Development

Successfully merging this pull request may close these issues.

Add UltraHDR isupport

4 participants