@@ -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
2427G_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+
140224void
141225infobar_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
186262static void
0 commit comments