Skip to content
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

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

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
823357c
feat(server): extract full-size previews from RAW images
eligao Dec 2, 2024
04c4e97
feat(web): load fullsize preview for RAW images when zoomed in
eligao Dec 2, 2024
6294980
refactor: tweaks for code review
eligao Dec 3, 2024
5026ceb
refactor: rename "converted" preview/assets to "fullsize"
eligao Dec 15, 2024
ffc2524
feat(web/server): fullsize preview for non-web-friendly images
eligao Dec 16, 2024
735df67
feat: tweaks for code review
eligao Dec 17, 2024
d9131f4
feat(server): require ASSET_DOWNLOAD premission for fullsize previews
eligao Dec 17, 2024
f630c52
test: fix types and interfaces
eligao Dec 17, 2024
8a7d298
chore: gen open-api
eligao Dec 17, 2024
b540803
feat(server): keep only essential exif in fullsize preview
eligao Dec 17, 2024
60dae62
chore: regen openapi
eligao Dec 17, 2024
cfe36b5
test: revert unnecessary timeout
eligao Dec 17, 2024
eee4823
feat: move full-size preview config to standalone entry
eligao Dec 22, 2024
a2397ce
feat(i18n): update en texts
eligao Dec 22, 2024
20fe3e5
fix: don't return fullsizePath when disabled
eligao Dec 23, 2024
b654a08
test: full-size previews
eligao Dec 23, 2024
4ea389c
test(web): full-size previews
eligao Dec 23, 2024
2a76355
chore: make open-api
eligao Dec 24, 2024
5b3b1e6
feat(server): redirect to preview/original URL when fullsize thumbnai…
eligao Dec 24, 2024
4dff398
fix(server): delete fullsize preview image on thumbnail regen after f…
eligao Dec 24, 2024
c7914c2
refactor(server): AssetRepository.deleteFiles with Kysely
eligao Jan 23, 2025
88e4dc8
fix(server): type of MediaRepository.writeExif
eligao Jan 23, 2025
ac9240e
minor simplification
mertalev Jan 25, 2025
528fe27
minor styling changes and condensed wording
mertalev Jan 25, 2025
b250f73
simplify
mertalev Jan 25, 2025
c26eaa9
Merge branch 'main' into feat/raw-fullsize-preview
eligao Jan 27, 2025
bd62c2f
chore: reuild open-api
eligao Jan 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions e2e/src/api/specs/asset.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,7 @@ describe('/asset', () => {

for (const { id, status } of assets) {
expect(status).toBe(AssetMediaStatus.Created);
// longer timeout as the thumbnail generation from full-size raw files can take a while
await utils.waitForWebsocketEvent({ event: 'assetUpload', id });
}

Expand Down
2 changes: 1 addition & 1 deletion e2e/src/web/specs/photo-viewer.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ test.describe('Photo Viewer', () => {
const { x, y, width, height } = box!;
await page.mouse.move(x + width / 2, y + height / 2);
await page.mouse.wheel(0, -1);
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('original');
await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('fullsize');
});

test('reloads photo when checksum changes', async ({ page }) => {
Expand Down
9 changes: 7 additions & 2 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@
"forcing_refresh_library_files": "Forcing refresh of all library files",
"image_format": "Format",
"image_format_description": "WebP produces smaller files than JPEG, but is slower to encode.",
"image_fullsize_enabled": "Enable full-size image generation",
"image_fullsize_enabled_description": "Generate full-size image for non-web-friendly formats. When \"Prefer embedded preview\" is enabled, embedded previews are used directly without conversion. Does not affect web-friendly formats like JPEG.",
"image_fullsize_quality_description": "Full-size image quality from 1-100. Higher is better, but produces larger files.",
"image_fullsize_title": "Full-size Image Settings",
"image_fullsize_description": "Full-size image with stripped metadata, used when zoomed in",
"image_prefer_embedded_preview": "Prefer embedded preview",
"image_prefer_embedded_preview_setting_description": "Use embedded previews in RAW photos as the input to image processing when available. This can produce more accurate colors for some images, but the quality of the preview is camera-dependent and the image may have more compression artifacts.",
"image_prefer_embedded_preview_setting_description": "Use embedded previews in RAW photos as the input to image processing and when available. This can produce more accurate colors for some images, but the quality of the preview is camera-dependent and the image may have more compression artifacts.",
"image_prefer_wide_gamut": "Prefer wide gamut",
"image_prefer_wide_gamut_setting_description": "Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colorspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid color shifts.",
"image_preview_description": "Medium-size image with stripped metadata, used when viewing a single asset and for machine learning",
Expand Down Expand Up @@ -1350,4 +1355,4 @@
"yes": "Yes",
"you_dont_have_any_shared_links": "You don't have any shared links",
"zoom_image": "Zoom Image"
}
}
1 change: 1 addition & 0 deletions mobile/openapi/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mobile/openapi/lib/api.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions mobile/openapi/lib/api_client.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions mobile/openapi/lib/model/asset_media_size.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions mobile/openapi/lib/model/path_type.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion mobile/openapi/lib/model/system_config_image_dto.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions open-api/immich-openapi-specs.json
Original file line number Diff line number Diff line change
Expand Up @@ -8406,6 +8406,7 @@
},
"AssetMediaSize": {
"enum": [
"fullsize",
"preview",
"thumbnail"
],
Expand Down Expand Up @@ -10187,6 +10188,7 @@
"PathType": {
"enum": [
"original",
"fullsize",
"preview",
"thumbnail",
"encoded_video",
Expand Down Expand Up @@ -11903,6 +11905,31 @@
],
"type": "object"
},
"SystemConfigGeneratedFullsizeImageDto": {
"properties": {
"enabled": {
"type": "boolean"
},
"format": {
"allOf": [
{
"$ref": "#/components/schemas/ImageFormat"
}
]
},
"quality": {
"maximum": 100,
"minimum": 1,
"type": "integer"
}
},
"required": [
"enabled",
"format",
"quality"
],
"type": "object"
},
"SystemConfigGeneratedImageDto": {
"properties": {
"format": {
Expand Down Expand Up @@ -11941,6 +11968,9 @@
"extractEmbedded": {
"type": "boolean"
},
"fullsize": {
"$ref": "#/components/schemas/SystemConfigGeneratedFullsizeImageDto"
},
"preview": {
"$ref": "#/components/schemas/SystemConfigGeneratedImageDto"
},
Expand All @@ -11951,6 +11981,7 @@
"required": [
"colorspace",
"extractEmbedded",
"fullsize",
"preview",
"thumbnail"
],
Expand Down
8 changes: 8 additions & 0 deletions open-api/typescript-sdk/src/fetch-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,11 @@ export type SystemConfigFFmpegDto = {
transcode: TranscodePolicy;
twoPass: boolean;
};
export type SystemConfigGeneratedFullsizeImageDto = {
enabled: boolean;
format: ImageFormat;
quality: number;
};
export type SystemConfigGeneratedImageDto = {
format: ImageFormat;
quality: number;
Expand All @@ -1131,6 +1136,7 @@ export type SystemConfigGeneratedImageDto = {
export type SystemConfigImageDto = {
colorspace: Colorspace;
extractEmbedded: boolean;
fullsize: SystemConfigGeneratedFullsizeImageDto;
preview: SystemConfigGeneratedImageDto;
thumbnail: SystemConfigGeneratedImageDto;
};
Expand Down Expand Up @@ -3464,6 +3470,7 @@ export enum AssetJobName {
TranscodeVideo = "transcode-video"
}
export enum AssetMediaSize {
Fullsize = "fullsize",
Preview = "preview",
Thumbnail = "thumbnail"
}
Expand Down Expand Up @@ -3514,6 +3521,7 @@ export enum PathEntityType {
}
export enum PathType {
Original = "original",
Fullsize = "fullsize",
Preview = "preview",
Thumbnail = "thumbnail",
EncodedVideo = "encoded_video",
Expand Down
Loading
Loading