Skip to content

Commit bd04e8c

Browse files
committed
Add SGI Image (.rgb) decoder
1 parent 8966982 commit bd04e8c

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

+769
-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
@@ -25,3 +25,7 @@ members = ["."]
2525
[[bin]]
2626
name = "fuzzer_script_pcx"
2727
path = "fuzzers/fuzzer_script_pcx.rs"
28+
29+
[[bin]]
30+
name = "fuzzer_script_sgi"
31+
path = "fuzzers/fuzzer_script_sgi.rs"

fuzz/fuzzers/fuzzer_script_sgi.rs

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

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)