52 cairo_surface_t *surface = NULL;
54 gboolean pipe_ready =
FALSE;
58 const char *fail_reason =
"unknown";
62 int bw = 0, bh = 0, src_stride = 0, dst_stride = 0;
69 fail_reason =
"mipmap full unavailable";
75 fail_reason =
"pixelpipe init failed";
100 fail_reason =
"pixelpipe process failed";
107 fail_reason =
"backbuffer hash invalid";
114 fail_reason =
"cache peek failed";
120 src_stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, bw);
121 if(bw <= 0 || bh <= 0
124 fail_reason =
"invalid backbuffer";
128 surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, bw, bh);
131 fail_reason =
"cairo surface create failed";
137 dst = cairo_image_surface_get_data(surface);
138 dst_stride = cairo_image_surface_get_stride(surface);
139 for(
int y = 0; y < bh; y++)
140 memcpy(dst + (
size_t)y * dst_stride, (
const uint8_t *)data + (
size_t)y * src_stride, (
size_t)src_stride);
141 cairo_surface_mark_dirty(surface);
155 GList *history_override, GList *iop_order_override,
156 int32_t history_end_override)
169 dt_print(
DT_DEBUG_DEV,
"[dev_snapshot] capture failed: dt_dev_load_image failed for imgid=%d\n", imgid);
178 frozen->
history = history_override;
179 history_override = NULL;
182 iop_order_override = NULL;
184 for(GList *history = g_list_first(frozen->
history); history; history = g_list_next(history))
196 "[dev_snapshot] capture failed: unresolved module op=%s multi=%s priority=%d for imgid=%d\n",
216 if(iop_order_override) g_list_free_full(iop_order_override,
dt_free_gpointer);
226 float vis_x0,
float vis_y0,
float vis_x1,
float vis_y1)
233 if(render_scale < 1.0f)
245 const int src_w = cairo_image_surface_get_width(snap->
image);
246 const int src_h = cairo_image_surface_get_height(snap->
image);
253 const int tap_margin = (int)
mitchell->width + 1;
254 const float pad_x = 0.5f * (vis_x1 - vis_x0);
255 const float pad_y = 0.5f * (vis_y1 - vis_y0);
257 int want_x0 = (int)floorf(vis_x0 - pad_x) - tap_margin;
258 int want_y0 = (int)floorf(vis_y0 - pad_y) - tap_margin;
259 int want_x1 = (int)ceilf(vis_x1 + pad_x) + tap_margin;
260 int want_y1 = (int)ceilf(vis_y1 + pad_y) + tap_margin;
262 want_x0 = CLAMP(want_x0, 0, src_w);
263 want_y0 = CLAMP(want_y0, 0, src_h);
264 want_x1 = CLAMP(want_x1, want_x0, src_w);
265 want_y1 = CLAMP(want_y1, want_y0, src_h);
267 const int vis_ix0 = (int)floorf(vis_x0);
268 const int vis_iy0 = (int)floorf(vis_y0);
269 const int vis_ix1 = (int)ceilf(vis_x1);
270 const int vis_iy1 = (int)ceilf(vis_y1);
273 const gboolean crop_ok = scale_ok
286 const int crop_w =
MAX(1, want_x1 - want_x0);
287 const int crop_h =
MAX(1, want_y1 - want_y0);
288 const int dst_w =
MAX(1, (
int)roundf((
float)crop_w * render_scale));
289 const int dst_h =
MAX(1, (
int)roundf((
float)crop_h * render_scale));
297 cairo_surface_flush(snap->
image);
298 const uint8_t *src = cairo_image_surface_get_data(snap->
image);
299 const int src_stride = cairo_image_surface_get_stride(snap->
image);
300 for(
int y = 0; y < crop_h; y++)
302 const uint8_t *
row = src + (size_t)(y + want_y0) * src_stride + (size_t)want_x0 * 4;
303 float *frow = in_f + (size_t)y * crop_w * 4;
304 for(
int x = 0;
x < crop_w;
x++)
306 frow[
x * 4 + 0] = (float)
row[
x * 4 + 2] * (1.0f / 255.0f);
307 frow[
x * 4 + 1] = (float)
row[
x * 4 + 1] * (1.0f / 255.0f);
308 frow[
x * 4 + 2] = (float)
row[
x * 4 + 0] * (1.0f / 255.0f);
309 frow[
x * 4 + 3] = 0.0f;
317 const dt_iop_roi_t roi_in = { .
x = 0, .y = 0, .width = crop_w, .height = crop_h, .scale = 1.0f };
318 const dt_iop_roi_t roi_out = { .
x = 0, .y = 0, .width = dst_w, .height = dst_h, .scale = render_scale };
323 cairo_surface_t *display = cairo_image_surface_create(CAIRO_FORMAT_RGB24, dst_w, dst_h);
327 uint8_t *dst = cairo_image_surface_get_data(display);
328 const int dst_stride = cairo_image_surface_get_stride(display);
329 for(
int y = 0; y < dst_h; y++)
331 const float *frow = out_f + (size_t)y * dst_w * 4;
332 uint8_t *drow = dst + (size_t)y * dst_stride;
333 for(
int x = 0;
x < dst_w;
x++)
335 drow[
x * 4 + 2] = (uint8_t)CLAMP(frow[
x * 4 + 0] * 255.0f + 0.5f, 0.0f, 255.0f);
336 drow[
x * 4 + 1] = (uint8_t)CLAMP(frow[
x * 4 + 1] * 255.0f + 0.5f, 0.0f, 255.0f);
337 drow[
x * 4 + 0] = (uint8_t)CLAMP(frow[
x * 4 + 2] * 255.0f + 0.5f, 0.0f, 255.0f);
340 cairo_surface_mark_dirty(display);
353 double clip_x,
double clip_y,
double clip_w,
double clip_h)
356 if(clip_w <= 0.0 || clip_h <= 0.0)
return;
360 const float render_scale = zoom_level / snapshot_scale;
366 const int src_w = cairo_image_surface_get_width(snap->
image);
367 const int src_h = cairo_image_surface_get_height(snap->
image);
368 const float disp_logical_w = src_w / ppd;
369 const float disp_logical_h = src_h / ppd;
370 const double tx = 0.5 *
width - dev->
roi.
x * disp_logical_w * render_scale;
371 const double ty = 0.5 *
height - dev->
roi.
y * disp_logical_h * render_scale;
377 float vis_x0 = 0.0f, vis_y0 = 0.0f, vis_x1 = (float)src_w, vis_y1 = (
float)src_h;
378 if(isfinite(render_scale) && render_scale > 1e-6f)
380 vis_x0 = (clip_x - tx) * ppd / render_scale;
381 vis_y0 = (clip_y - ty) * ppd / render_scale;
382 vis_x1 = (clip_x + clip_w - tx) * ppd / render_scale;
383 vis_y1 = (clip_y + clip_h - ty) * ppd / render_scale;
393 const double crop_tx = use_mitchell ? snap->
crop_x * (
double)render_scale / ppd : 0.0;
394 const double crop_ty = use_mitchell ? snap->
crop_y * (
double)render_scale / ppd : 0.0;
397 cairo_rectangle(cri, clip_x, clip_y, clip_w, clip_h);
399 cairo_translate(cri, tx + crop_tx, ty + crop_ty);
400 if(!use_mitchell) cairo_scale(cri, render_scale, render_scale);
401 cairo_set_source_surface(cri, disp, 0.0, 0.0);
405 cairo_pattern_set_filter(cairo_get_source(cri), use_mitchell ? CAIRO_FILTER_NEAREST : CAIRO_FILTER_GOOD);
void cleanup(dt_imageio_module_format_t *self)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static float * dt_alloc_align_float(size_t pixels)
static void dt_free_gpointer(gpointer ptr)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_iop_module_t * dt_dev_get_module_instance(dt_develop_t *dev, const char *op, const char *multi_name, const int multi_priority)
Find a module instance by op name and instance metadata.
dt_iop_module_t * dt_dev_create_module_instance(dt_develop_t *dev, const char *op, const char *multi_name, const int multi_priority, gboolean use_next_priority)
Create a new module instance from an existing base .so.
void dt_dev_history_free_history(dt_develop_t *dev)
Free the whole history list attached to dev->history.
uint64_t dt_dev_history_compute_hash(dt_develop_t *dev)
Get the integrity checksum of the whole history stack. This should be done ONLY when history is chang...
void dt_dev_set_history_end_ext(struct dt_develop_t *dev, const uint32_t index)
Set the history end index (GUI perspective).
void dt_dev_pixelpipe_propagate_formats(dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_get_roi_out(dt_dev_pixelpipe_t *pipe, const int width_in, const int height_in, int *width, int *height)
static cairo_surface_t * _render(dt_develop_t *frozen, float scale)
void dt_dev_snapshot_draw(dt_dev_snapshot_t *snap, cairo_t *cri, struct dt_develop_t *dev, int32_t width, int32_t height, double clip_x, double clip_y, double clip_w, double clip_h)
void dt_dev_snapshot_clear(dt_dev_snapshot_t *snap)
gboolean dt_dev_snapshot_capture(dt_dev_snapshot_t *snap, int32_t imgid, float scale, GList *history_override, GList *iop_order_override, int32_t history_end_override)
static void _build_display_image(dt_dev_snapshot_t *snap, float render_scale, float vis_x0, float vis_y0, float vis_x1, float vis_y1)
void dt_dev_cleanup(dt_develop_t *dev)
dt_dev_image_storage_t dt_dev_load_image(dt_develop_t *dev, const int32_t imgid)
float dt_dev_get_zoom_level(const dt_develop_t *dev)
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached)
static void dt_dev_set_history_hash(dt_develop_t *dev, const uint64_t history_hash)
dt_iop_module_t * dt_iop_get_module_by_op_priority(GList *modules, const char *operation, const int multi_priority)
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
void dt_interpolation_resample(const struct dt_interpolation *itor, float *out, const dt_iop_roi_t *const roi_out, const float *const in, const dt_iop_roi_t *const roi_in)
@ DT_INTERPOLATION_MITCHELL
static float mitchell(const float x)
#define dt_mipmap_cache_get(A, B, C, D, E, F)
#define dt_mipmap_cache_release(A, B)
void dt_dev_pixelpipe_cache_ref_count_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Increase/Decrease the reference count on the cache line as to prevent LRU item removal....
gboolean dt_dev_pixelpipe_cache_ref_entry_by_hash(dt_dev_pixelpipe_cache_t *cache, const uint64_t hash, void **data, dt_pixel_cache_entry_t **entry)
Resolve and retain an existing cache entry by hash.
size_t dt_pixel_cache_entry_get_size(dt_pixel_cache_entry_t *entry)
Peek the size (in bytes) reserved for the host buffer of a cache entry.
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
Pixelpipe cache for storing intermediate results in the pixelpipe.
#define DT_PIXELPIPE_CACHE_HASH_INVALID
void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, int32_t imgid, int width, int height, float iscale, dt_mipmap_size_t size)
void dt_dev_pixelpipe_set_icc(dt_dev_pixelpipe_t *pipe, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
int dt_dev_pixelpipe_init_preview(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
void dt_dev_pixelpipe_create_nodes(dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_cleanup(dt_dev_pixelpipe_t *pipe)
int dt_dev_pixelpipe_process(dt_dev_pixelpipe_t *pipe, dt_iop_roi_t roi)
#define dt_dev_pixelpipe_synch_all(pipe)
static uint64_t dt_dev_backbuf_get_hash(const dt_backbuf_t *backbuf)
unsigned __int64 uint64_t
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
struct dt_gui_gtk_t * gui
struct dt_mipmap_cache_t * mipmap_cache
struct dt_develop_t * develop
dt_colorspaces_color_profile_type_t icc_type
dt_iop_color_intent_t icc_intent
cairo_surface_t * display_image
struct dt_dev_pixelpipe_t * preview_pipe
struct dt_develop_t::@17 roi
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))