Skip to content

Commit 65626a8

Browse files
committed
Merge branch 'asynch-infobar'
2 parents c329cf8 + a19b067 commit 65626a8

File tree

6 files changed

+102
-22
lines changed

6 files changed

+102
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- animate keypress zoom
1010
- use NN sampling for zoom with gtk 4.10+
1111
- add colour management
12+
- add async infobar updates
1213

1314
## 2.5.1, 23/7/23
1415

meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ configure_file(
3737
configuration: config_h,
3838
)
3939

40-
vips_dep = dependency('vips', version: '>=8.11')
40+
# need vips_thread_execute()
41+
vips_dep = dependency('vips', version: '>=8.15')
4142
gtk_dep = dependency('gtk4')
4243
m_dep = cc.find_library('m')
4344

src/imagewindow.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,3 +1611,4 @@ image_window_get_mouse_position( ImageWindow *win,
16111611
imagedisplay_gtk_to_image( VIPSDISP_IMAGEDISPLAY( win->imagedisplay ),
16121612
win->last_x_gtk, win->last_y_gtk, x_image, y_image );
16131613
}
1614+

src/infobar.c

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ struct _Infobar {
1919
GtkWidget *mag;
2020

2121
GSList *value_widgets;
22+
23+
// a background pixel value fetch is in progress
24+
gboolean updating;
2225
};
2326

2427
G_DEFINE_TYPE( Infobar, infobar, GTK_TYPE_WIDGET );
@@ -137,18 +140,96 @@ infobar_status_value_set_array( Infobar *infobar, double *d )
137140
}
138141
}
139142

143+
/* Asynchronous update of the pixel value ... we need this off the main thread
144+
* or we get awful hitching for some formats.
145+
*/
146+
typedef struct _PixelUpdate {
147+
// what we update, where we get the pixel data
148+
Infobar *infobar;
149+
TileSource *tile_source;
150+
151+
// fetch params
152+
int image_x;
153+
int image_y;
154+
double *vector;
155+
int n;
156+
gboolean result;
157+
} PixelUpdate;
158+
159+
static void
160+
infobar_update_free( PixelUpdate *update )
161+
{
162+
update->infobar->updating = FALSE;
163+
164+
VIPS_UNREF( update->infobar );
165+
VIPS_UNREF( update->tile_source );
166+
VIPS_FREE( update->vector );
167+
VIPS_FREE( update );
168+
}
169+
170+
// runs back in the main thread again ... update the screen
171+
static gboolean
172+
infobar_update_pixel_cb( void *a )
173+
{
174+
PixelUpdate *update = (PixelUpdate *) a;
175+
176+
if( update->result )
177+
infobar_status_value_set_array( update->infobar, update->vector );
178+
179+
infobar_update_free( update );
180+
181+
return( FALSE );
182+
}
183+
184+
// runs in a bg thread
185+
static void
186+
infobar_get_pixel( void *a, void *b )
187+
{
188+
PixelUpdate *update = (PixelUpdate *) a;
189+
190+
update->result = tile_source_get_pixel( update->tile_source,
191+
update->image_x, update->image_y, &update->vector, &update->n );
192+
193+
g_idle_add( infobar_update_pixel_cb, update );
194+
}
195+
196+
// fetch the mouse position pixel and update the screen in a bg thread
197+
static void
198+
infobar_update_pixel( Infobar *infobar )
199+
{
200+
if( !infobar->updating ) {
201+
ImageWindow *win = infobar->win;
202+
PixelUpdate *update = g_new0( PixelUpdate, 1 );
203+
204+
double x_image;
205+
double y_image;
206+
207+
update->infobar = infobar;
208+
update->tile_source = image_window_get_tile_source( win );
209+
image_window_get_mouse_position( infobar->win, &x_image, &y_image );
210+
update->image_x = (int) x_image;
211+
update->image_y = (int) y_image;
212+
infobar->updating = TRUE;
213+
214+
// must stay valid until we are done
215+
g_object_ref( update->infobar );
216+
g_object_ref( update->tile_source );
217+
218+
if( vips_thread_execute( "pixel", infobar_get_pixel, update ) )
219+
// if we can't run a bg task, we must free the update
220+
infobar_update_free( update );
221+
}
222+
}
223+
140224
void
141225
infobar_status_update( Infobar *infobar )
142226
{
143-
TileSource *tile_source = image_window_get_tile_source( infobar->win );
144227
double scale = image_window_get_scale( infobar->win );
145228

146229
char str[64];
147230
VipsBuf buf = VIPS_BUF_STATIC( str );
148231
double image_x;
149232
double image_y;
150-
double *vector;
151-
int n;
152233

153234
#ifdef DEBUG
154235
printf( "infobar_status_update:\n" );
@@ -166,13 +247,6 @@ infobar_status_update( Infobar *infobar )
166247
vips_buf_all( &buf ) );
167248
vips_buf_rewind( &buf );
168249

169-
if( tile_source_get_pixel( tile_source, &vector, &n,
170-
image_x, image_y ) ) {
171-
infobar_status_value_set_array( infobar, vector );
172-
g_free( vector );
173-
}
174-
175-
vips_buf_rewind( &buf );
176250
vips_buf_appendf( &buf, "Magnification " );
177251
if( scale >= 1.0 )
178252
vips_buf_appendf( &buf, "%d:1", (int) scale );
@@ -181,6 +255,8 @@ infobar_status_update( Infobar *infobar )
181255
gtk_label_set_text( GTK_LABEL( infobar->mag ),
182256
vips_buf_all( &buf ) );
183257

258+
// queue bg update of pixel value
259+
infobar_update_pixel( infobar );
184260
}
185261

186262
static void

src/tilesource.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,8 @@ tile_source_get_base_image( TileSource *tile_source )
18761876
}
18771877

18781878
gboolean
1879-
tile_source_get_pixel( TileSource *tile_source,
1880-
double **vector, int *n, int x, int y )
1879+
tile_source_get_pixel( TileSource *tile_source, int image_x, int image_y,
1880+
double **vector, int *n )
18811881
{
18821882
if( !tile_source->loaded ||
18831883
!tile_source->image )
@@ -1886,21 +1886,22 @@ tile_source_get_pixel( TileSource *tile_source,
18861886
/* x and y are in base image coordinates, so we need to scale by the
18871887
* current z.
18881888
*/
1889-
x /= 1 << tile_source->current_z;
1890-
y /= 1 << tile_source->current_z;
1889+
image_x /= 1 << tile_source->current_z;
1890+
image_y /= 1 << tile_source->current_z;
18911891

18921892
/* Block outside the image.
18931893
*/
1894-
if( x < 0 ||
1895-
y < 0 ||
1896-
x >= tile_source->display->Xsize ||
1897-
y >= tile_source->display->Ysize )
1894+
if( image_x < 0 ||
1895+
image_y < 0 ||
1896+
image_x >= tile_source->display->Xsize ||
1897+
image_y >= tile_source->display->Ysize )
18981898
return( FALSE );
18991899

19001900
/* The ->display image is cached in a sink screen, so this will be
19011901
* reasonably quick, even for things like svg and pdf.
19021902
*/
1903-
if( vips_getpoint( tile_source->display, vector, n, x, y, NULL ) )
1903+
if( vips_getpoint( tile_source->display,
1904+
vector, n, image_x, image_y, NULL ) )
19041905
return( FALSE );
19051906

19061907
return( TRUE );

src/tilesource.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ GFile *tile_source_get_file( TileSource *tile_source );
235235

236236
VipsImage *tile_source_get_image( TileSource *tile_source );
237237
VipsImage *tile_source_get_base_image( TileSource *tile_source );
238-
gboolean tile_source_get_pixel( TileSource *tile_source,
239-
double **vector, int *n, int x, int y );
238+
gboolean tile_source_get_pixel( TileSource *tile_source,
239+
int image_x, int image_y, double **vector, int *n );
240240
TileSource *tile_source_duplicate( TileSource *tile_source );
241241

242242
#endif /*__TILE_SOURCE_H*/

0 commit comments

Comments
 (0)