Skip to content

Move image save operation off the main thread - #63

Open
kleisauke wants to merge 2 commits into
libvips:masterfrom
kleisauke:libvips-pr-5092-compat
Open

Move image save operation off the main thread#63
kleisauke wants to merge 2 commits into
libvips:masterfrom
kleisauke:libvips-pr-5092-compat

Conversation

@kleisauke

@kleisauke kleisauke commented Jul 9, 2026

Copy link
Copy Markdown
Member

Required for libvips/libvips#5165.

The revised save_options_eval() is similar to:

vipsdisp/src/imagewindow.c

Lines 453 to 523 in e387036

typedef struct _EvalUpdate {
Imagewindow *win;
int eta;
int percent;
} EvalUpdate;
static gboolean
imagewindow_eval_idle(void *user_data)
{
EvalUpdate *update = (EvalUpdate *) user_data;
Imagewindow *win = update->win;
char str[256];
VipsBuf buf = VIPS_BUF_STATIC(str);
vips_buf_appendf(&buf, "%d%% complete, %d seconds to go",
update->percent, update->eta);
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(win->progress),
vips_buf_all(&buf));
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(win->progress),
update->percent / 100.0);
g_object_unref(win);
g_free(update);
return FALSE;
}
static void
imagewindow_eval(VipsImage *image,
VipsProgress *progress, Imagewindow *win)
{
double time_now;
EvalUpdate *update;
/* We can be ^Q'd during load. This is NULLed in _dispose.
*/
if (!win->progress_timer)
return;
time_now = g_timer_elapsed(win->progress_timer, NULL);
/* Throttle to 10Hz.
*/
if (time_now - win->last_progress_time < 0.1)
return;
win->last_progress_time = time_now;
#ifdef DEBUG_VERBOSE
printf("imagewindow_eval: %d%%\n", progress->percent);
#endif /*DEBUG_VERBOSE*/
/* This can come from the background load thread, so we can't update
* the UI directly.
*/
update = g_new(EvalUpdate, 1);
update->win = win;
update->percent = progress->percent;
update->eta = progress->eta;
/* We don't want win to vanish before we process this update. The
* matching unref is in the handler above.
*/
g_object_ref(win);
g_idle_add(imagewindow_eval_idle, update);
}

@kleisauke

Copy link
Copy Markdown
Member Author

FWIW, I think we should also consider re-syncing vipsdisp with nip4. For example, I noticed that we could cherry-pick commit libvips/nip4@b546407.

vipsdisp/src/infobar.c

Lines 225 to 238 in e387036

/* Block outside the image.
*/
if (update->image_x >= 0 &&
update->image_y >= 0 &&
update->image_x < image->Xsize &&
update->image_y < image->Ysize)
/* Fetch from image, even though this can be very slow.
* This is run in a bg thread, so speed should not matter too much.
*/
update->result = !vips_getpoint(image,
&update->vector, &update->n,
update->image_x, update->image_y,
"unpack_complex", TRUE,
NULL);

@jcupitt

jcupitt commented Aug 11, 2026

Copy link
Copy Markdown
Member

FWIW, I think we should also consider re-syncing vipsdisp with nip4.

Yes, they are drifting apart :(

Maybe a better solution would be to make vipsdisp into another executable generated from the nip4 source tree? We already make nip4 and snip (just the programming language).

I've got a branch of nip4 that moves all the region handling out of the main image UI class, so I think making a standalone viewer from the same sources wouldn't be that hard. Though I've not tried!

@kleisauke

Copy link
Copy Markdown
Member Author

nip4 is distributed under a different license than vipsdisp. So, distributing vipsdisp within the nip4 source tree could(?) raise licensing concerns for users who expect vipsdisp to be distributed under the MIT license.

@jcupitt

jcupitt commented Aug 11, 2026

Copy link
Copy Markdown
Member

Oh, that's true. You're right, I guess it should stay a separate project.

I suppose moving region handling out of imageui at least makes it simpler to copy-paste the sources across.

@kleisauke kleisauke mentioned this pull request Aug 16, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants