// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
use std::{
io::IoSliceMut,
ops::{Deref, Range},
};
// General implementation strategy: // - Anything that is not a section is read into a small buffer. // - As soon as we know section sizes, data is read directly into sections. // When the start of the populated range in `buf` goes past half of its length, // the data in the buffer is moved back to the beginning.
impl SmallBuffer { pub(super) fn refill(
&mutself, mut get_input: impl FnMut(&mut [IoSliceMut]) -> Result<usize, std::io::Error>,
max: Option<usize>,
) -> Result<usize> { letmut total = 0; loop { ifself.range.start >= self.buf.len() / 2 { let start = self.range.start; let len = self.range.len(); let (pre, post) = self.buf.split_at_mut(start);
pre[0..len].copy_from_slice(&post[0..len]); self.range.start -= start; self.range.end -= start;
} ifself.range.len() >= self.buf.len() / 2 { break;
} let stop = iflet Some(max) = max { self.range
.end
.saturating_add(max.saturating_sub(total))
.min(self.buf.len())
} else { self.buf.len()
}; let num = get_input(&mut [IoSliceMut::new(&mutself.buf[self.range.end..stop])])?;
total += num; self.range.end += num; if num == 0 { break;
}
}
Ok(total)
}
pub(super) fn take(&mutself, mut buffers: &mut [IoSliceMut]) -> usize { letmut num = 0; while !self.range.is_empty() { let Some((buf, rest)) = buffers.split_first_mut() else { break;
};
buffers = rest; let len = self.range.len().min(buf.len()); // Only copy 'len' bytes, not the entire range, to avoid panic when buf is smaller than range
buf[..len].copy_from_slice(&self.buf[self.range.start..self.range.start + len]); self.range.start += len;
num += len;
}
num
}
pub(super) fn enlarge(&mutself) { // Note: we need a *4 here because doubling the buffer size might still not allow refill() to make progress. self.buf.resize(self.buf.len() * 4, 0);
}
impl Deref for SmallBuffer { type Target = [u8]; fn deref(&self) -> &Self::Target {
&self.buf[self.range.clone()]
}
}
impl JxlDecoderInner { /// Process more of the input file. /// This function will return when reaching the next decoding stage (i.e. finished decoding /// file/frame header, or finished decoding a frame). /// If called when decoding a frame with `None` for buffers, the frame will still be read, /// but pixel data will not be produced. #[inline(never)] pubfn process(
&mutself,
input: &mutdyn JxlBitstreamInput,
buffers: Option<&mut [JxlOutputBuffer]>,
) -> Result<ProcessingResult<(), ()>> {
ProcessingResult::new(self.codestream_parser.process(
&mutself.box_parser,
input,
&self.options,
buffers, false,
))
}
/// Draws all the pixels we have data for. Returns `true` if any new pixels /// were written to `buffers` since the previous call to `flush_pixels`; /// returns `false` if no new rendering has happened, in which case the /// contents of `buffers` are unchanged from the caller's perspective. pubfn flush_pixels(&mutself, buffers: &mut [JxlOutputBuffer]) -> Result<bool> { letmut input: &[u8] = &[]; matchself.codestream_parser.process(
&mutself.box_parser,
&mut input,
&self.options,
Some(buffers), true,
) {
Ok(()) | Err(crate::error::Error::OutOfBounds(_)) => { let updated = self.codestream_parser.pixels_dirty; self.codestream_parser.pixels_dirty = false;
Ok(updated)
}
Err(e) => Err(e),
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.