diff --git a/src/codecs/openexr.rs b/src/codecs/openexr.rs index 3f20fcfdd0..ace4ecdcfe 100644 --- a/src/codecs/openexr.rs +++ b/src/codecs/openexr.rs @@ -152,10 +152,10 @@ impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for OpenExrDecoder { } // reads with or without alpha, depending on `self.alpha_preference` and `self.alpha_present_in_file` - fn read_image_with_progress( + fn read_image_with_progress( self, unaligned_bytes: &mut [u8], - progress_callback: F, + mut progress_callback: F, ) -> ImageResult<()> { let blocks_in_header = self.selected_exr_header().chunk_count as u64; let channel_count = self.color_type().channel_count() as usize; diff --git a/src/image.rs b/src/image.rs index c578bad970..33be9775e3 100644 --- a/src/image.rs +++ b/src/image.rs @@ -686,8 +686,8 @@ pub trait ImageDecoder<'a>: Sized { self.read_image_with_progress(buf, |_| {}) } - /// Same as `read_image` but periodically calls the provided callback to give updates on loading - /// progress. + /// Same as `read_image_with_progress_mut`, but the callback cannot mutate state. + /// Use `read_image_with_progress_mut` if you want to mutate your state from within the callback. fn read_image_with_progress( self, buf: &mut [u8], @@ -720,6 +720,22 @@ pub trait ImageDecoder<'a>: Sized { Ok(()) } + /// Same as `read_image` but periodically calls the provided callback to give updates on loading + /// progress. + // TODO find a way to have only _mut versions, eliminating refcells + fn read_image_with_progress_mut( + self, + buf: &mut [u8], + progress_callback: F, + ) -> ImageResult<()> { + let mutable_callback_cell = std::cell::RefCell::new(progress_callback); + self.read_image_with_progress(buf, |progress| { + if let Ok(mut progress_callback) = mutable_callback_cell.try_borrow_mut() { + progress_callback(progress) + } + }) + } + /// Set decoding limits for this decoder. See [`Limits`] for the different kinds of /// limits that is possible to set. /// @@ -755,6 +771,17 @@ pub trait ImageDecoderRect<'a>: ImageDecoder<'a> + Sized { self.read_rect_with_progress(x, y, width, height, buf, |_| {}) } + /// Same as `read_rect_with_progress_mut`, but the callback is not mutable. + fn read_rect_with_progress( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + buf: &mut [u8], + progress_callback: F, + ) -> ImageResult<()>; + /// Decode a rectangular section of the image, periodically reporting progress. /// /// The output buffer will be filled with fields specified by @@ -767,7 +794,8 @@ pub trait ImageDecoderRect<'a>: ImageDecoder<'a> + Sized { /// /// This function will panic if the output buffer isn't at least /// `color_type().bytes_per_pixel() * color_type().channel_count() * width * height` bytes long. - fn read_rect_with_progress( + // TODO find a way to have only _mut versions, eliminating refcells + fn read_rect_with_progress_mut( &mut self, x: u32, y: u32, @@ -775,7 +803,14 @@ pub trait ImageDecoderRect<'a>: ImageDecoder<'a> + Sized { height: u32, buf: &mut [u8], progress_callback: F, - ) -> ImageResult<()>; + ) -> ImageResult<()> { + let mutable_callback_cell = std::cell::RefCell::new(progress_callback); + self.read_rect_with_progress(x, y, width, height, buf, |progress| { + if let Ok(mut progress_callback) = mutable_callback_cell.try_borrow_mut() { + progress_callback(progress) + } + }) + } } /// AnimationDecoder trait