libdnrs: avoid data copies
This commit is contained in:
+11
-14
@@ -747,29 +747,28 @@ fn decode_raw(
|
||||
}
|
||||
|
||||
fn decode_image(
|
||||
data: Vec<u8>,
|
||||
data: &[u8],
|
||||
first_frame_only: bool,
|
||||
) -> Result<dnrs_decoder, String> {
|
||||
image_extras::register();
|
||||
|
||||
if let Ok(format) = image::guess_format(&data) {
|
||||
return decode_image_rs(&data, format, first_frame_only);
|
||||
if let Ok(format) = image::guess_format(data) {
|
||||
return decode_image_rs(data, format, first_frame_only);
|
||||
}
|
||||
#[cfg(feature = "jpeg2000")]
|
||||
if data.starts_with(&[0xff, 0x4f, 0xff, 0x51])
|
||||
|| data.starts_with(&[0, 0, 0, 12, b'j', b'P', b' ', b' '])
|
||||
{
|
||||
return decode_jpeg2000(&data);
|
||||
return decode_jpeg2000(data);
|
||||
}
|
||||
if let Ok(decoder) =
|
||||
image::codecs::tga::TgaDecoder::new(Cursor::new(data.as_slice()))
|
||||
if let Ok(decoder) = image::codecs::tga::TgaDecoder::new(Cursor::new(data))
|
||||
{
|
||||
return decoder_from_still("image-rs/Tga", decoder);
|
||||
}
|
||||
// XPM registers a signature with image, while XBM is C source with no
|
||||
// magic number and has to be tried explicitly.
|
||||
if let Ok(reader) =
|
||||
ImageReader::new(Cursor::new(data.as_slice())).with_guessed_format()
|
||||
ImageReader::new(Cursor::new(data)).with_guessed_format()
|
||||
{
|
||||
if let Ok((frame, metadata)) = decode_still(reader) {
|
||||
return decoder_from_frames(
|
||||
@@ -780,13 +779,11 @@ fn decode_image(
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Ok(decoder) =
|
||||
image_extras::xbm::XbmDecoder::new(Cursor::new(data.as_slice()))
|
||||
{
|
||||
if let Ok(decoder) = image_extras::xbm::XbmDecoder::new(Cursor::new(data)) {
|
||||
return decoder_from_still("image-extras/XBM", decoder);
|
||||
}
|
||||
#[cfg(feature = "raw")]
|
||||
if let Ok(rawfile) = libopenraw::rawfile_from_memory(data, None) {
|
||||
if let Ok(rawfile) = libopenraw::rawfile_from_memory(data.to_vec(), None) {
|
||||
return decode_raw(&rawfile);
|
||||
}
|
||||
Err("unrecognised image data".into())
|
||||
@@ -903,10 +900,10 @@ pub unsafe extern "C" fn dnrs_decoder_new(
|
||||
if length > isize::MAX as usize {
|
||||
return Err("input is too large".into());
|
||||
}
|
||||
let input = if length == 0 {
|
||||
Vec::new()
|
||||
let input: &[u8] = if length == 0 {
|
||||
&[]
|
||||
} else {
|
||||
unsafe { std::slice::from_raw_parts(data, length) }.to_vec()
|
||||
unsafe { std::slice::from_raw_parts(data, length) }
|
||||
};
|
||||
decode_image(input, first_frame_only)
|
||||
.map(|decoder| Box::into_raw(Box::new(decoder)))
|
||||
|
||||
+11
-1
@@ -43,7 +43,7 @@ enum dnrs_pixel_format {
|
||||
};
|
||||
|
||||
struct dnrs_document_info {
|
||||
const char *codec;
|
||||
const char *codec; ///< Borrowed from the decoder.
|
||||
uint32_t page_count;
|
||||
};
|
||||
|
||||
@@ -62,6 +62,8 @@ struct dnrs_page_info {
|
||||
size_t text_length;
|
||||
};
|
||||
|
||||
// Pixel data is owned by the caller, and released by dnrs_frame_clear(),
|
||||
// which also accepts a zero-initialized frame.
|
||||
struct dnrs_frame {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
@@ -73,16 +75,24 @@ struct dnrs_frame {
|
||||
};
|
||||
|
||||
const char *const *dnrs_mime_types(size_t *length);
|
||||
|
||||
// Decodes everything at once, so the input is only needed during the call.
|
||||
// Functions that fail return false or NULL, and set any non-NULL `error`,
|
||||
// which must then be freed with dnrs_error_free(). They reset it on success.
|
||||
struct dnrs_decoder *dnrs_decoder_new(const uint8_t *data, size_t length,
|
||||
bool first_frame_only, struct dnrs_error **error);
|
||||
bool dnrs_decoder_get_info(const struct dnrs_decoder *decoder,
|
||||
struct dnrs_document_info *info, struct dnrs_error **error);
|
||||
// Iteration only moves forward. False without an error means exhaustion.
|
||||
// Frames are those of the current page, which next_page() must select first.
|
||||
bool dnrs_decoder_next_page(struct dnrs_decoder *decoder,
|
||||
struct dnrs_page_info *page, struct dnrs_error **error);
|
||||
// Overwrites `frame`, which must be cleared first if it holds pixels.
|
||||
bool dnrs_decoder_next_frame(struct dnrs_decoder *decoder,
|
||||
struct dnrs_frame *frame, struct dnrs_error **error);
|
||||
const char *dnrs_error_message(const struct dnrs_error *error);
|
||||
void dnrs_frame_clear(struct dnrs_frame *frame);
|
||||
// Invalidates everything borrowed from it, but not frames already returned.
|
||||
void dnrs_decoder_free(struct dnrs_decoder *decoder);
|
||||
void dnrs_error_free(struct dnrs_error *error);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user