diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 287c3f8f1ba9..8d2bf2a6afb6 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -65,7 +65,12 @@ changes (where available).
## Bug Fixes
-- N/A
+- Honor the default configuration preference "never" for "use raw
+ instead of jpeg from size": for unaltered images, always generate
+ thumbnails/previews from embedded JPEGs rather than processing the
+ raw file. If you prefer the prior behavior, which processed the raw
+ file rather than upscale the embedded JPEG for higher resolution
+ thumbnails/previews, use the new configuration option "auto".
## Lua
diff --git a/data/darktableconfig.xml.in b/data/darktableconfig.xml.in
index 5cfe9440cb32..e554e34b492c 100644
--- a/data/darktableconfig.xml.in
+++ b/data/darktableconfig.xml.in
@@ -1332,7 +1332,7 @@
plugins/lighttable/thumbnail_raw_min_level
-
+
@@ -1343,11 +1343,12 @@
+
never
- use raw file instead of embedded JPEG from size
- if the thumbnail size is greater than this value, it will be processed using raw file instead of the embedded preview JPEG (better but slower).\nif you want all thumbnails and pre-rendered images in best quality you should choose the *always* option.\n(more comments in the manual)
+ for unaltered images, use raw file instead of embedded JPEG from size
+ if the thumbnail size is greater than this value, it will be processed using raw file instead of the embedded preview JPEG (better but slower).\nif you want all thumbnails and pre-rendered images in best quality you should choose the *always* option.\nfor the quickest display, choose the *never* option\nthe *auto* option prefers the embedded JPEG except when the when thumb size exceeds the resolution of the embedded JPEG\n(more comments in the manual)plugins/lighttable/thumbnail_hq_min_level
diff --git a/src/common/mipmap_cache.c b/src/common/mipmap_cache.c
index 19cc83122ca4..c1667dc4d050 100644
--- a/src/common/mipmap_cache.c
+++ b/src/common/mipmap_cache.c
@@ -1,6 +1,6 @@
/*
This file is part of darktable,
- Copyright (C) 2011-2025 darktable developers.
+ Copyright (C) 2011-2026 darktable developers.
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1215,6 +1215,7 @@ dt_mipmap_size_t dt_mipmap_cache_get_min_mip_from_pref(const char *value)
if(strcmp(value, "WQXGA") == 0) return DT_MIPMAP_5;
if(strcmp(value, "4K") == 0) return DT_MIPMAP_6;
if(strcmp(value, "5K") == 0) return DT_MIPMAP_7;
+ if(strcmp(value, "auto") == 0) return DT_MIPMAP_8;
return DT_MIPMAP_NONE;
}
@@ -1504,16 +1505,16 @@ static void _init_8(uint8_t *buf,
res = dt_imageio_large_thumbnail(filename, &tmp, &thumb_width, &thumb_height, color_space);
if(!res)
{
- // if the thumbnail is not large enough, we compute one
+ // use embedded JPEG if it is large enough or conf requests
+ // always use, otherwise compute one
const dt_image_t *img2 = dt_image_cache_get(imgid, 'r');
const int imgwd = img2->width;
const int imght = img2->height;
dt_image_cache_read_release(img2);
- if(thumb_width < wd
- && thumb_height < ht
- && thumb_width < imgwd - 4
- && thumb_height < imght - 4)
- {
+ const gboolean always_use_thumb = (min_s == DT_MIPMAP_NONE);
+ const gboolean thumb_lt_mip = ((thumb_width < wd) && (thumb_height < ht));
+ const gboolean thumb_lt_raw = ((thumb_width < imgwd - 4) && (thumb_height < imght - 4));
+ if (!always_use_thumb && thumb_lt_mip && thumb_lt_raw) {
res = TRUE;
}
else
diff --git a/src/dtgtk/culling.c b/src/dtgtk/culling.c
index e3e77ccf1225..6ff6e3a323d1 100644
--- a/src/dtgtk/culling.c
+++ b/src/dtgtk/culling.c
@@ -1,6 +1,6 @@
/*
This file is part of darktable,
- Copyright (C) 2020-2023 darktable developers.
+ Copyright (C) 2020-2026 darktable developers.
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1155,8 +1155,10 @@ static void _thumbs_prefetch(dt_culling_t *table)
maxw = MAX(maxw, th->width);
maxh = MAX(maxh, th->height);
}
+ const int32_t mipwidth = maxw * darktable.gui->ppd;
+ const int32_t mipheight = maxh * darktable.gui->ppd;
dt_mipmap_size_t mip =
- dt_mipmap_cache_get_matching_size(maxw, maxh);
+ dt_mipmap_cache_get_matching_size(mipwidth, mipheight);
// prefetch next image
gchar *query;
diff --git a/src/dtgtk/thumbtable.c b/src/dtgtk/thumbtable.c
index 83ee83d15ca3..142ee0d1bd9d 100644
--- a/src/dtgtk/thumbtable.c
+++ b/src/dtgtk/thumbtable.c
@@ -1669,13 +1669,13 @@ static void _thumbs_ask_for_discard(dt_thumbtable_t *table)
dt_conf_get_string_const("plugins/lighttable/thumbnail_hq_min_level");
dt_mipmap_size_t hql =
dt_mipmap_cache_get_min_mip_from_pref(hq);
+
const char *embedded =
dt_conf_get_string_const("plugins/lighttable/thumbnail_raw_min_level");
-
dt_mipmap_size_t embeddedl = dt_mipmap_cache_get_min_mip_from_pref(embedded);
- int min_level = 8;
- int max_level = 0;
+ int min_level = DT_MIPMAP_8;
+ int max_level = DT_MIPMAP_0;
if(hql != table->pref_hq)
{
min_level = MIN(table->pref_hq, hql);
@@ -1687,6 +1687,15 @@ static void _thumbs_ask_for_discard(dt_thumbtable_t *table)
max_level = MAX(max_level, MAX(table->pref_embedded, embeddedl));
}
+ // switching between auto/never options
+ if (max_level == DT_MIPMAP_NONE && min_level == DT_MIPMAP_8)
+ {
+ // err on side of discarding too many thumbnails: a quick
+ // survey of vintage raw files shows a lowest res embedded
+ // JPEG of 1616x1080 (found in 2011 & 2014 Sony)
+ min_level = DT_MIPMAP_4;
+ }
+
sqlite3_stmt *stmt = NULL;
if(min_level < max_level)
@@ -1722,7 +1731,7 @@ static void _thumbs_ask_for_discard(dt_thumbtable_t *table)
while(sqlite3_step(stmt) == SQLITE_ROW)
{
const dt_imgid_t imgid = sqlite3_column_int(stmt, 0);
- for(int i = max_level - 1; i >= min_level; i--)
+ for(int i = max_level; i >= min_level; i--)
{
dt_mipmap_cache_remove_at_size(imgid, i);
}