Skip to content

Commit 12ecb42

Browse files
committed
Add SGI Image (.rgb) decoder
1 parent 292a0c4 commit 12ecb42

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+768
-3
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ publish = false
88
include = ["src", "tests/reference.rs"]
99

1010
[features]
11-
default = ["pcx"]
11+
default = ["pcx", "sgi"]
1212
pcx = ["dep:pcx"]
13+
sgi = []
1314

1415
[dependencies]
1516
image = { version = "0.25.8", default-features = false }

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Decoding support for additional image formats beyond those provided by the [`ima
66
| Extension | File Format Description |
77
| --------- | -------------------- |
88
| PCX | [Wikipedia](https://en.wikipedia.org/wiki/PCX#PCX_file_format) |
9+
| RGB | [Wikipedia](https://en.wikipedia.org/wiki/Silicon_Graphics_Image) |
910

1011
## New Formats
1112

fuzz/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ version = "0.4"
2121
# Prevent this from interfering with workspaces
2222
[workspace]
2323
members = ["."]
24+
25+
[[bin]]
26+
name = "fuzzer_script_sgi"
27+
path = "fuzzers/fuzzer_script_sgi.rs"

fuzz/fuzzers/fuzzer_script_sgi.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![no_main]
2+
#[macro_use] extern crate libfuzzer_sys;
3+
4+
use std::io::Cursor;
5+
use image::ImageDecoder;
6+
7+
fuzz_target!(|data: &[u8]| {
8+
let reader = Cursor::new(data);
9+
let Ok(mut decoder) = image_extras::sgi::SgiDecoder::new(reader) else {
10+
return;
11+
};
12+
let mut limits = image::Limits::default();
13+
limits.max_alloc = Some(1024 * 1024); // 1 MiB
14+
if limits.reserve(decoder.total_bytes()).is_err() {
15+
return;
16+
}
17+
if decoder.set_limits(limits).is_err() {
18+
return;
19+
}
20+
let _ = std::hint::black_box(image::DynamicImage::from_decoder(decoder));
21+
});

src/lib.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,41 @@
1818
#[cfg(feature = "pcx")]
1919
pub mod pcx;
2020

21+
#[cfg(feature = "sgi")]
22+
pub mod sgi;
23+
2124
/// Register all enabled extra formats with the image crate.
2225
pub fn register() {
23-
let just_registered = image::hooks::register_decoding_hook(
26+
let just_registered_pcx = image::hooks::register_decoding_hook(
2427
"pcx".into(),
2528
Box::new(|r| Ok(Box::new(pcx::PCXDecoder::new(r)?))),
2629
);
27-
if just_registered {
30+
if just_registered_pcx {
2831
image::hooks::register_format_detection_hook("pcx".into(), &[0x0a, 0x0], Some(b"\xFF\xF8"));
2932
}
33+
34+
// SGI RGB images generally show up with a .rgb ending (whether or not they
35+
// have 3 channels), and sometimes .bw (when grayscale) and .rgba. The
36+
// extensions .sgi and .iris, while unambiguous, do not seem to have been
37+
// used much. The extension .rgb is also used for a variety of other files,
38+
// including bare image data, so to be sure it would be best to check both
39+
// extension and leading bytes
40+
let hook: for<'a> fn(
41+
image::hooks::GenericReader<'a>,
42+
) -> image::ImageResult<Box<dyn image::ImageDecoder + 'a>> =
43+
|r| Ok(Box::new(sgi::SgiDecoder::new(r)?));
44+
image::hooks::register_decoding_hook("bw".into(), Box::new(hook));
45+
image::hooks::register_decoding_hook("rgb".into(), Box::new(hook));
46+
image::hooks::register_decoding_hook("rgba".into(), Box::new(hook));
47+
image::hooks::register_decoding_hook("iris".into(), Box::new(hook));
48+
let just_registered_sgi = image::hooks::register_decoding_hook("sgi".into(), Box::new(hook));
49+
if just_registered_sgi {
50+
// The main signature bytes are technically just 01 da, but this is short
51+
// and the following storage and bpc fields are constrained well enough to
52+
// efficiently match them as well
53+
image::hooks::register_format_detection_hook("sgi".into(), b"\x01\xda\x00\x01", None);
54+
image::hooks::register_format_detection_hook("sgi".into(), b"\x01\xda\x01\x01", None);
55+
image::hooks::register_format_detection_hook("sgi".into(), b"\x01\xda\x00\x02", None);
56+
image::hooks::register_format_detection_hook("sgi".into(), b"\x01\xda\x01\x02", None);
57+
}
3058
}

0 commit comments

Comments
 (0)