Skip to content

feat: original-sized previews for non-web-friendly images #14446

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Mar 31, 2025

Conversation

eligao
Copy link
Contributor

@eligao eligao commented Dec 2, 2024

Implementation details:

  • Server: extract and keep the original-sized preview image for non-web-friendly images

  • OpenAPI: a new AssetMediaSize.FULLSIZE size is available under the viewThumbnail API

    • It returns the AssetFileType.FULLSIZE file when available
    • Or redirects to the original file when it's web-friendly
    • Or otherwise redirects back to AssetFileSize.PREVIEW
      • Happens when an image is not web-friendly and a FULLSIZE preview is not yet generated.
    • HTTP 302 is used here to make full use of caching
  • Web: photo-viewer

    • When zoomed in, the browser loads the AssetMediaSize.FULLSIZE preview via the viewThumbnail API
    • This applies to ALL images, instead of previously only loading the original file for web-friendly images.
    • The server will determine what to return or redirect, simplifying the logic on the client, and the client never knows if a fullsize preview is available anyway.
    • This file can be right-clicked and downloaded/copied for sharing.

Some future ideas:

  • Load the FULLSIZE image inthe mobile client. Unfortunately I'm not familiar with flutter yet.
  • Download the RAW as JPEG with full EXIF preserved, for easier sharing
  • Trim the RAW originals and keep the JPEG only, freeing up storage space

@eligao eligao changed the title feat/raw fullsize preview feat: original-sized previews for RAW images Dec 2, 2024
@eligao eligao force-pushed the feat/raw-fullsize-preview branch from f2b631a to 54b91b4 Compare December 2, 2024 16:35
Copy link
Member

@mertalev mertalev left a comment

Choose a reason for hiding this comment

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

Thank you for the PR! I mostly looked at the server code, where I think it needs some more polishing.

Re: caching, this also affects the case where the user zooms in and no extracted image exists, right? It will load the preview again.

@eligao eligao force-pushed the feat/raw-fullsize-preview branch 5 times, most recently from 076d59d to a7a9b4d Compare December 3, 2024 21:24
@eligao eligao force-pushed the feat/raw-fullsize-preview branch from a7a9b4d to 34592b3 Compare December 3, 2024 21:29
@eligao
Copy link
Contributor Author

eligao commented Dec 6, 2024

any more comments from maintainers to get this merged, so that I can continue with previews of other images?
@danieldietzler @alextran1502

@alextran1502
Copy link
Member

@eligao no rush here

@mertalev
Copy link
Member

mertalev commented Dec 6, 2024

I think we should wait until we're done with hot fixes for the current release.

@michelheusschen
Copy link
Collaborator

michelheusschen commented Dec 7, 2024

For a DNG image with a resolution of 5376x3956 and 41.3MiB in size, the following variants are generated using the default settings:

Variant Format Resolution Size
Thumbnail webp 5280x3956 887KiB
Preview jpeg 5280x3956 1794KiB
Original jpeg 5280x3956 1794KiB

These generated variants seem larger than expected and don't match the configured settings, with the preview and original being identical. It's also strange that the resolution has slightly changed.

@eligao
Copy link
Contributor Author

eligao commented Dec 7, 2024

For a DNG image with a resolution of 5376x3956 and 41.3MiB in size, the following variants are generated using the default settings:

Variant Format Resolution Size
Thumbnail webp 5280x3956 887KiB
Preview jpeg 5280x3956 1794KiB
Original jpeg 5280x3956 1794KiB
These generated variants seem larger than expected and don't match the configured settings, with the preview and original being identical. It's also strange that the resolution has slightly increased.

nice catch, the file sizes are indeed wrong, let me fix that and add checks to tests.
as for the sizes being slightly different, it's likely due to the crop tags in exif:
image

@mertalev
Copy link
Member

Hi again @eligao! We've been talking about the PR and think there are a few changes it'll need for it to be merge-able.

  1. It should apply to all images that aren't web compatible (using the same list as web, ignoring that Safari can view HEIF images)
  2. It should be configurable in the image settings, similar to the thumbnail and preview sections
    • There should be an "enabled" toggle that is disabled by default
    • The target format should be configurable in the case where an embedded image is not used and a new image has to be generated
  3. Rename the "converted" enum to "fullsize"

@eligao eligao force-pushed the feat/raw-fullsize-preview branch from ebcfe9c to e22a123 Compare December 16, 2024 20:37
@eligao eligao changed the title feat: original-sized previews for RAW images [WIP] feat: original-sized previews for non-web-friendly images Dec 16, 2024
@eligao eligao changed the title [WIP] feat: original-sized previews for non-web-friendly images feat: original-sized previews for non-web-friendly images Dec 17, 2024
@eligao eligao force-pushed the feat/raw-fullsize-preview branch from 8d43411 to 4cee0c7 Compare December 17, 2024 16:45
@mertalev
Copy link
Member

mertalev commented Feb 4, 2025

Just a heads up that I will be away for the next two weeks and won't be able to test this until I'm back. But feel free to continue working on it! I'm happy for it to be merged once the bugs are fixed and someone can confirm that it works as expected.

@mertalev
Copy link
Member

mertalev commented Mar 5, 2025

Hey @eligao, just checking in! Were you able to take a look at the issues raised above? Is there anything I can do to help bring this PR to the finish line?

@eligao
Copy link
Contributor Author

eligao commented Mar 5, 2025

@mertalev thanks for checking in, sorry I've been busy recently but I still remember this PR. Let me update the branch and see if I can fix the small issues you mentioned above :)

@eligao
Copy link
Contributor Author

eligao commented Mar 5, 2025

@mertalev I've updated the branch and did some small fixes and tests:

  • The initial image shown is the preview and zooming in shows the fullsize.
  • The "Display original photos" user setting should not make it load the full-size image directly, otherwise it slows the browser down.

@mertalev
Copy link
Member

mertalev commented Mar 6, 2025

Nice! I'll do some testing with it tomorrow and see if we can get this merged :)

@eligao
Copy link
Contributor Author

eligao commented Mar 19, 2025

@mertalev just checking in, any further suggestions for this PR? 👀

Copy link
Member

@mertalev mertalev left a comment

Choose a reason for hiding this comment

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

The PR works as expected, tested on web with embedded preview enabled and disabled and format set to WebP and JPEG. Disabling the full-size feature and regenerating deletes both the file and the DB entry. Requesting a full-size image where there is none redirects to the preview and uses the cached preview (tested on Chrome).

@mertalev
Copy link
Member

I made two tweaks to the PR:

  1. Continue displaying the full-size/original image after zooming back out. It makes things smoother and avoids jarring effects like going from an HDR image back to SDR after zooming out.
  2. Display full-size/original image when opening the viewer if "display original photos" is enabled. You mentioned that it's slower, but this is the current behavior for e.g. high-res web compatible images. For users who want to see the originals whenever possible (hence opting in to this setting), it's better to avoid requiring a zoom.

@eligao
Copy link
Contributor Author

eligao commented Mar 26, 2025

@mertalev thanks for the tweaks :)

  1. Nice catch, I totally missed the case when zooming back out.
  2. Sounds good as long as it is the current behavior.

@eligao
Copy link
Contributor Author

eligao commented Mar 27, 2025

@danieldietzler any more suggestions before we can get this merged? 👀

@mertalev
Copy link
Member

mertalev commented Mar 27, 2025

We're planning to include it in 1.131.0, just needs testing from @alextran1502

@mertalev mertalev merged commit 5c80e87 into immich-app:main Mar 31, 2025
40 checks passed
@eligao eligao deleted the feat/raw-fullsize-preview branch March 31, 2025 18:30
kirill-dev-pro pushed a commit to kirill-dev-pro/immich-but-with-public-albums-within-instance that referenced this pull request Apr 6, 2025
…#14446)

* feat(server): extract full-size previews from RAW images

* feat(web): load fullsize preview for RAW images when zoomed in

* refactor: tweaks for code review

* refactor: rename "converted" preview/assets to "fullsize"

* feat(web/server): fullsize preview for non-web-friendly images

* feat: tweaks for code review

* feat(server): require ASSET_DOWNLOAD premission for fullsize previews

* test: fix types and interfaces

* chore: gen open-api

* feat(server): keep only essential exif in fullsize preview

* chore: regen openapi

* test: revert unnecessary timeout

* feat: move full-size preview config to standalone entry

* feat(i18n): update en texts

* fix: don't return fullsizePath when disabled

* test: full-size previews

* test(web): full-size previews

* chore: make open-api

* feat(server): redirect to preview/original URL when fullsize thumbnail not available

* fix(server): delete fullsize preview image on thumbnail regen after fullsize preview turned off

* refactor(server): AssetRepository.deleteFiles with Kysely

* fix(server): type of MediaRepository.writeExif

* minor simplification

* minor styling changes and condensed wording

* simplify

* chore: reuild open-api

* test(server): fix media.service tests

* test(web): fix photo-viewer test

* fix(server):  use fullsize image when requested

* fix file path extension

* formatting

* use fullsize when zooming back out or when "display original photos" is enabled

* simplify condition

---------

Co-authored-by: mertalev <[email protected]>
savely-krasovsky pushed a commit to savely-krasovsky/immich that referenced this pull request Jun 8, 2025
…#14446)

* feat(server): extract full-size previews from RAW images

* feat(web): load fullsize preview for RAW images when zoomed in

* refactor: tweaks for code review

* refactor: rename "converted" preview/assets to "fullsize"

* feat(web/server): fullsize preview for non-web-friendly images

* feat: tweaks for code review

* feat(server): require ASSET_DOWNLOAD premission for fullsize previews

* test: fix types and interfaces

* chore: gen open-api

* feat(server): keep only essential exif in fullsize preview

* chore: regen openapi

* test: revert unnecessary timeout

* feat: move full-size preview config to standalone entry

* feat(i18n): update en texts

* fix: don't return fullsizePath when disabled

* test: full-size previews

* test(web): full-size previews

* chore: make open-api

* feat(server): redirect to preview/original URL when fullsize thumbnail not available

* fix(server): delete fullsize preview image on thumbnail regen after fullsize preview turned off

* refactor(server): AssetRepository.deleteFiles with Kysely

* fix(server): type of MediaRepository.writeExif

* minor simplification

* minor styling changes and condensed wording

* simplify

* chore: reuild open-api

* test(server): fix media.service tests

* test(web): fix photo-viewer test

* fix(server):  use fullsize image when requested

* fix file path extension

* formatting

* use fullsize when zooming back out or when "display original photos" is enabled

* simplify condition

---------

Co-authored-by: mertalev <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants