Skip to content

Commit

Permalink
rework image final size
Browse files Browse the repository at this point in the history
  • Loading branch information
AlicVB committed Apr 25, 2019
1 parent e6fa5f4 commit 58106a3
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 83 deletions.
3 changes: 3 additions & 0 deletions src/common/history.c
Expand Up @@ -92,6 +92,7 @@ void dt_history_delete_on_image_ext(int32_t imgid, gboolean undo)

/* make sure mipmaps are recomputed */
dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
dt_image_reset_final_size(imgid);

/* remove darktable|style|* tags */
dt_tag_detach_by_string("darktable|style%", imgid);
Expand Down Expand Up @@ -167,6 +168,7 @@ int dt_history_load_and_apply(const int imgid, gchar *filename, int history_only

dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE);
dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
dt_image_reset_final_size(imgid);
}
return 0;
}
Expand Down Expand Up @@ -739,6 +741,7 @@ int dt_history_copy_and_paste_on_image(int32_t imgid, int32_t dest_imgid, gboole
dt_image_synch_xmp(dest_imgid);

dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid);
dt_image_reset_final_size(imgid);

/* update the aspect ratio if the current sorting is based on aspect ratio, otherwise the aspect ratio will be
recalculated when the mimpap will be recreated */
Expand Down
53 changes: 48 additions & 5 deletions src/common/image.c
Expand Up @@ -383,16 +383,54 @@ void dt_image_set_location_and_elevation(const int32_t imgid, dt_image_geoloc_t
dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE);
}

void dt_image_reset_final_size(const int32_t imgid)
{
dt_image_t *imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w');
imgtmp->final_width = imgtmp->final_height = 0;
dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED);
}

gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height)
{
dt_develop_t dev;
// get the img strcut
dt_image_t *imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'r');
dt_image_t img = *imgtmp;
dt_image_cache_read_release(darktable.image_cache, imgtmp);
// if we already have computed them
if(img.final_height > 0 && img.final_width > 0)
{
*width = img.final_width;
*height = img.final_height;
return 0;
}

// special case if we try to load embedded preview of raw file

// the orientation for this camera is not read correctly from exiv2, so we need
// to go the full path (as the thumbnail will be flipped the wrong way round)
const int incompatible = !strncmp(img.exif_maker, "Phase One", 9);
if(!img.verified_size && !dt_image_altered(imgid) && !dt_conf_get_bool("never_use_embedded_thumb")
&& !incompatible)
{
// we want to be sure to have the real image size.
// some raw files need a pass via rawspeed to get it.
char filename[PATH_MAX] = { 0 };
gboolean from_cache = TRUE;
dt_image_full_path(imgid, filename, sizeof(filename), &from_cache);
imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w');
dt_imageio_open(imgtmp, filename, NULL);
imgtmp->verified_size = 1;
img = *imgtmp;
dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED);
}

// and now we can do the pipe stuff to get final image size
dt_develop_t dev;
dt_dev_init(&dev, 0);
dt_dev_load_image(&dev, imgid);
const dt_image_t *img = &dev.image_storage;

dt_dev_pixelpipe_t pipe;
int wd = img->width, ht = img->height;
int wd = img.width, ht = img.height;
int res = dt_dev_pixelpipe_init_dummy(&pipe, wd, ht);
if(res)
{
Expand All @@ -409,8 +447,11 @@ gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height)
}
dt_dev_cleanup(&dev);

*width = wd;
*height = ht;
imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w');
imgtmp->final_width = *width = wd;
imgtmp->final_height = *height = ht;
dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED);

return res;
}

Expand Down Expand Up @@ -461,6 +502,7 @@ void dt_image_set_flip(const int32_t imgid, const dt_image_orientation_t orienta
sqlite3_finalize(stmt);

dt_mipmap_cache_remove(darktable.mipmap_cache, imgid);
dt_image_reset_final_size(imgid);
// write that through to xmp:
dt_image_write_sidecar_file(imgid);
}
Expand Down Expand Up @@ -1195,6 +1237,7 @@ uint32_t dt_image_import_lua(const int32_t film_id, const char *filename, gboole
void dt_image_init(dt_image_t *img)
{
img->width = img->height = img->verified_size = 0;
img->final_width = img->final_height = 0;
img->crop_x = img->crop_y = img->crop_width = img->crop_height = 0;
img->orientation = ORIENTATION_NULL;
img->legacy_flip.legacy = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/common/image.h
Expand Up @@ -153,7 +153,7 @@ typedef struct dt_image_t
// common stuff

// to understand this, look at comment for dt_histogram_roi_t
int32_t width, height, verified_size;
int32_t width, height, verified_size, final_width, final_height;
int32_t crop_x, crop_y, crop_width, crop_height;

// used by library
Expand Down Expand Up @@ -235,6 +235,7 @@ void dt_image_set_flip(const int32_t imgid, const dt_image_orientation_t user_fl
dt_image_orientation_t dt_image_get_orientation(const int imgid);
/** get max width and height of the final processed image with its current hisotry stack */
gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height);
void dt_image_reset_final_size(const int32_t imgid);
/** set image location lon/lat */
void dt_image_set_location(const int32_t imgid, dt_image_geoloc_t *geoloc);
/** get image location lon/lat */
Expand Down
60 changes: 6 additions & 54 deletions src/common/mipmap_cache.c
Expand Up @@ -317,47 +317,11 @@ void dt_mipmap_cache_allocate_dynamic(void *data, dt_cache_entry_t *entry)
{
if(mip == DT_MIPMAP_8)
{
const uint32_t imgid = get_imgid(entry->key);
if(!dt_image_altered(imgid))
{
// the image has not been been altered, so output size = input size
// and the orientation doesn't matter here
const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r');
entry->data_size = sizeof(struct dt_mipmap_buffer_dsc) + (img2->width + 4) * (img2->height + 4) * 4;
dt_image_cache_read_release(darktable.image_cache, img2);
}
else
{
// we first need to get the final output size of our image
// let's create a dummy pipe for that
const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r');
dt_image_t imgtmp = *img2;
dt_image_cache_read_release(darktable.image_cache, img2);
dt_develop_t dev;
dt_dev_init(&dev, 0);
dt_dev_load_image(&dev, imgid);
dt_dev_pixelpipe_t pipe;
const int res = dt_dev_pixelpipe_init_dummy(&pipe, imgtmp.width, imgtmp.height);
if(res)
{
// set mem pointer to 0, won't be used.
dt_dev_pixelpipe_set_input(&pipe, &dev, NULL, imgtmp.width, imgtmp.height, 1.0f);
dt_dev_pixelpipe_create_nodes(&pipe, &dev);
dt_dev_pixelpipe_synch_all(&pipe, &dev);
dt_dev_pixelpipe_get_dimensions(&pipe, &dev, pipe.iwidth, pipe.iheight, &pipe.processed_width,
&pipe.processed_height);
dt_dev_pixelpipe_cleanup(&pipe);
// we enlarge the output size by 4 to handle rounding errors in mipmap computation
entry->data_size
= sizeof(struct dt_mipmap_buffer_dsc) + (pipe.processed_width + 4) * (pipe.processed_height + 4) * 4;
}
else
{
// for some raison pipeline didn't succeed, let's allocate huge memory
entry->data_size = cache->buffer_size[mip];
}
dt_dev_cleanup(&dev);
}
int imgfw, imgfh;
imgfw = imgfh = 0;
// be sure that we have the right size values
dt_image_get_final_size(get_imgid(entry->key), &imgfw, &imgfh);
entry->data_size = sizeof(struct dt_mipmap_buffer_dsc) + (imgfw + 4) * (imgfh + 4) * 4;
}
else if(mip <= DT_MIPMAP_F)
{
Expand Down Expand Up @@ -1243,25 +1207,13 @@ static void _init_8(uint8_t *buf, uint32_t *width, uint32_t *height, float *isca
}
else
{
// we want to be sure to have the real image size.
// some raw files need a pass via rawspeed to get it.
dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r');
const int verified_size = img2->verified_size;
dt_image_cache_read_release(darktable.image_cache, img2);
if(!verified_size)
{
img2 = dt_image_cache_get(darktable.image_cache, imgid, 'w');
dt_imageio_open(img2, filename, NULL);
img2->verified_size = 1;
dt_image_cache_write_release(darktable.image_cache, img2, DT_IMAGE_CACHE_RELAXED);
}
uint8_t *tmp = 0;
int32_t thumb_width, thumb_height;
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
img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r');
const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r');
const int imgwd = img2->width;
const int imght = img2->height;
dt_image_cache_read_release(darktable.image_cache, img2);
Expand Down
1 change: 1 addition & 0 deletions src/common/styles.c
Expand Up @@ -756,6 +756,7 @@ void dt_styles_apply_to_image(const char *name, gboolean duplicate, int32_t imgi

/* remove old obsolete thumbnails */
dt_mipmap_cache_remove(darktable.mipmap_cache, newimgid);
dt_image_reset_final_size(newimgid);

/* if we have created a duplicate, reset collected images */
if(duplicate) dt_control_signal_raise(darktable.signals, DT_SIGNAL_COLLECTION_CHANGED);
Expand Down
2 changes: 1 addition & 1 deletion src/external/rawspeed
Submodule rawspeed updated 57 files
+16 −12 CMakeLists.txt
+6 −0 README.rst
+5 −3 bench/librawspeed/CMakeLists.txt
+2 −0 bench/librawspeed/decompressors/CMakeLists.txt
+2 −0 bench/librawspeed/interpolators/CMakeLists.txt
+1 −1 bench/librawspeed/metadata/CameraMetaDataBenchmark.cpp
+0 −70 cmake/Modules/GTEST_ADD_TESTS.cmake
+5 −4 cmake/Modules/GoogleBenchmark.cmake
+7 −5 cmake/Modules/GoogleBenchmark.cmake.in
+5 −4 cmake/Modules/GoogleTest.cmake
+7 −5 cmake/Modules/GoogleTest.cmake.in
+5 −4 cmake/Modules/LLVMOpenMP.cmake
+7 −5 cmake/Modules/LLVMOpenMP.cmake.in
+5 −4 cmake/Modules/Pugixml.cmake
+7 −5 cmake/Modules/Pugixml.cmake.in
+7 −6 cmake/Modules/Zlib.cmake
+7 −5 cmake/Modules/Zlib.cmake.in
+1 −1 cmake/Modules/run-xmllint.cmake
+21 −0 cmake/cmake-command-wrappers.cmake
+13 −4 cmake/sample-based-testing.cmake
+0 −3 cmake/src-dependencies.cmake
+27 −1 data/cameras.xml
+1 −1 docs/conf.py
+1 −0 docs/index.rst
+1 −0 docs/lnt/index.rst
+3 −3 fuzz/CMakeLists.txt
+1 −1 fuzz/corpora/CMakeLists.txt
+1 −1 fuzz/librawspeed/decoders/TiffDecoders/CMakeLists.txt
+1 −1 fuzz/librawspeed/decompressors/CMakeLists.txt
+2 −2 fuzz/librawspeed/decompressors/HuffmanTable/CMakeLists.txt
+14 −1 fuzz/librawspeed/decompressors/HuffmanTable/Dual.cpp
+1 −1 fuzz/librawspeed/parsers/CMakeLists.txt
+1 −1 fuzz/rawspeed/CMakeLists.txt
+2 −1 fuzz/rawspeed/main.cpp
+126 −0 lnt/CMakeLists.txt
+62 −0 lnt/README.rst
+5 −0 lnt/build-lit.local.cfg
+7 −0 lnt/lit.local.cfg
+0 −0 lnt/litsupport_rawspeed/__init__.py
+16 −0 lnt/litsupport_rawspeed/modules/__init__.py
+74 −0 lnt/litsupport_rawspeed/modules/rsbench.py
+35 −0 lnt/raw-sample-archive/CMakeLists.txt
+5 −0 lnt/raw-sample-archive/lit.local.cfg
+1 −0 lnt/raw-sample-archive/rsbench/CMakeLists.txt
+7 −0 lnt/raw-sample-archive/rsbench/lit.local.cfg
+2 −2 src/config.h.in
+19 −0 src/librawspeed/common/CMakeLists.txt
+39 −0 src/librawspeed/common/GetNumberOfProcessorCores.cpp
+5 −2 src/utilities/identify/CMakeLists.txt
+1 −12 src/utilities/identify/rawspeed-identify.cpp
+3 −1 src/utilities/rsbench/CMakeLists.txt
+1 −1 src/utilities/rsbench/main.cpp
+9 −5 src/utilities/rstest/CMakeLists.txt
+1 −12 src/utilities/rstest/rstest.cpp
+4 −5 test/librawspeed/CMakeLists.txt
+2 −2 test/librawspeed/metadata/CameraMetaDataTest.cpp
+2 −20 test/librawspeed/test/RawSpeed.cpp
2 changes: 2 additions & 0 deletions src/views/darkroom.c
Expand Up @@ -615,6 +615,7 @@ static void dt_dev_change_image(dt_develop_t *dev, const uint32_t imgid)
// if()
{
dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id);
dt_image_reset_final_size(dev->image_storage.id);
dt_image_synch_xmp(dev->image_storage.id);
}

Expand Down Expand Up @@ -2517,6 +2518,7 @@ void leave(dt_view_t *self)
// if()
{
dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id);
dt_image_reset_final_size(dev->image_storage.id);
// dump new xmp data
dt_image_synch_xmp(dev->image_storage.id);
}
Expand Down
22 changes: 19 additions & 3 deletions src/views/lighttable.c
Expand Up @@ -353,7 +353,7 @@ static inline void _destroy_preview_surface(dt_preview_surface_t *fp_surf)
fp_surf->imgid = -1;
fp_surf->w_lock = 0;

fp_surf->zoom_100 = 40.0f;
fp_surf->zoom_100 = 1001.0f; // dummy vaule to say it need recompute
fp_surf->w_fit = 0.0f;
fp_surf->h_fit = 0.0f;

Expand Down Expand Up @@ -1790,6 +1790,18 @@ static int expose_zoomable(dt_view_t *self, cairo_t *cr, int32_t width, int32_t
return missing;
}

static float _preview_get_zoom100(int32_t width, int32_t height, uint32_t imgid)
{
int w, h;
w = h = 0;
dt_image_get_final_size(imgid, &w, &h);
// 0.97f value come from dt_view_image_expose
float zoom_100 = fmaxf((float)w / ((float)width * 0.97f), (float)h / ((float)height * 0.97f));
if(zoom_100 < 1.0f) zoom_100 = 1.0f;

return zoom_100;
}

static int expose_expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx,
int32_t pointery, const dt_lighttable_layout_t layout)
{
Expand Down Expand Up @@ -2131,7 +2143,9 @@ static int expose_expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t he
params.full_surface_wd = &lib->fp_surf[i].width;
params.full_surface_ht = &lib->fp_surf[i].height;
params.full_surface_w_lock = &lib->fp_surf[i].w_lock;
params.full_zoom100 = &lib->fp_surf[i].zoom_100;
if(lib->fp_surf[i].zoom_100 >= 1000.0f || lib->fp_surf[i].imgid != images[i].imgid)
lib->fp_surf[i].zoom_100 = _preview_get_zoom100(images[i].width, images[i].height, images[i].imgid);
params.full_zoom100 = lib->fp_surf[i].zoom_100;
params.full_w1 = &lib->fp_surf[i].w_fit;
params.full_h1 = &lib->fp_surf[i].h_fit;
params.full_maxdx = &lib->fp_surf[i].max_dx;
Expand Down Expand Up @@ -2306,7 +2320,9 @@ static int expose_full_preview(dt_view_t *self, cairo_t *cr, int32_t width, int3
params.zoom = 1;
params.full_preview = TRUE;
params.full_zoom = lib->full_zoom;
params.full_zoom100 = &lib->fp_surf[0].zoom_100;
if(lib->fp_surf[0].zoom_100 >= 1000.0f || lib->fp_surf[0].imgid != lib->full_preview_id)
lib->fp_surf[0].zoom_100 = _preview_get_zoom100(width, height, lib->full_preview_id);
params.full_zoom100 = lib->fp_surf[0].zoom_100;
params.full_maxdx = &lib->fp_surf[0].max_dx;
params.full_maxdy = &lib->fp_surf[0].max_dy;
params.full_w1 = &lib->fp_surf[0].w_fit;
Expand Down
19 changes: 1 addition & 18 deletions src/views/view.c
Expand Up @@ -1095,11 +1095,9 @@ int dt_view_image_expose(dt_view_image_expose_t *vals)


dt_mipmap_cache_t *cache = darktable.mipmap_cache;
if(vals->full_surface_id && vals->full_zoom100 && *(vals->full_surface_id) != imgid)
*(vals->full_zoom100) = 40.0f;
float fz = 1.0f;
if(full_zoom > 0.0f) fz = full_zoom;
if(vals->full_zoom100 && *(vals->full_zoom100) > 0.0f) fz = fminf(*(vals->full_zoom100), fz);
if(vals->full_zoom100 > 0.0f) fz = fminf(vals->full_zoom100, fz);
dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(cache, imgwd * width * fz, imgwd * height * fz);


Expand Down Expand Up @@ -1139,21 +1137,6 @@ int dt_view_image_expose(dt_view_image_expose_t *vals)
buf_wd = *(vals->full_surface_wd);
buf_ht = *(vals->full_surface_ht);
}
// we want to sanitize full_zoom value to be sure not to exceed 100%
if(fz > 1.0f && buf_sizeok)
{
// is the mipmap loaded the full one ?
if(cache->max_width[mip] > buf_wd + 4 && cache->max_height[mip] > buf_ht + 4)
{
float zoom_100 = fmaxf((float)buf_wd / ((float)width * imgwd), (float)buf_ht / ((float)height * imgwd));
if(zoom_100 < 1.0f) zoom_100 = 1.0f;
if(vals->full_zoom100) *(vals->full_zoom100) = zoom_100;
if(fz > zoom_100)
{
fz = zoom_100;
}
}
}

if(draw_thumb_background)
{
Expand Down
2 changes: 1 addition & 1 deletion src/views/view.h
Expand Up @@ -167,7 +167,7 @@ typedef struct dt_view_image_expose_t
gboolean full_preview;
gboolean image_only;
float full_zoom;
float *full_zoom100;
float full_zoom100;
float *full_w1;
float *full_h1;
float full_x;
Expand Down

0 comments on commit 58106a3

Please sign in to comment.