Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the decoding of jpeg2000 #7

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.rs.bk
/Cargo.lock
/target/
.DS_Store
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ readme = "README.md"
[dependencies]
byteorder = "1"
png = { version = "0.16", optional = true }
jpeg2k = "0.6.6"


[features]
default = ["pngio"]
Expand Down
29 changes: 11 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ The table below indicates which types are currently supported; see
https://en.wikipedia.org/wiki/Apple_Icon_Image_format#Icon_types for more
information about each type.

The biggest limitation at this time is that a number of the newer icon types
can be encoded with either PNG or JPEG 2000 data, but this library does not yet
support JPEG 2000; attempting to decode such an icon will result an an error
value being returned (although you can still decode other icons from the same
ICNS file). The reason for this is that I don't currently know of any JPEG
2000 libraries for Rust; if one exists, please feel free to file a bug or send
a pull request.

| OSType | Description | Supported? |
|--------|-----------------------------------------|------------|
Expand All @@ -85,17 +78,17 @@ a pull request.
| `h8mk` | 48×48 8-bit mask | Yes |
| `it32` | 128×128 24-bit icon | Yes |
| `t8mk` | 128×128 8-bit mask | Yes |
| `icp4` | 16x16 32-bit PNG/JP2 icon | PNG only |
| `icp5` | 32x32 32-bit PNG/JP2 icon | PNG only |
| `icp6` | 64x64 32-bit PNG/JP2 icon | PNG only |
| `ic07` | 128x128 32-bit PNG/JP2 icon | PNG only |
| `ic08` | 256×256 32-bit PNG/JP2 icon | PNG only |
| `ic09` | 512×512 32-bit PNG/JP2 icon | PNG only |
| `ic10` | 512x512@2x "retina" 32-bit PNG/JP2 icon | PNG only |
| `ic11` | 16x16@2x "retina" 32-bit PNG/JP2 icon | PNG only |
| `ic12` | 32x32@2x "retina" 32-bit PNG/JP2 icon | PNG only |
| `ic13` | 128x128@2x "retina" 32-bit PNG/JP2 icon | PNG only |
| `ic14` | 256x256@2x "retina" 32-bit PNG/JP2 icon | PNG only |
| `icp4` | 16x16 32-bit PNG/JP2 icon | Yes |
CharlieS1103 marked this conversation as resolved.
Show resolved Hide resolved
| `icp5` | 32x32 32-bit PNG/JP2 icon | Yes |
| `icp6` | 64x64 32-bit PNG/JP2 icon | Yes |
| `ic07` | 128x128 32-bit PNG/JP2 icon | Yes |
| `ic08` | 256×256 32-bit PNG/JP2 icon | Yes |
| `ic09` | 512×512 32-bit PNG/JP2 icon | Yes |
| `ic10` | 512x512@2x "retina" 32-bit PNG/JP2 icon | Yes |
| `ic11` | 16x16@2x "retina" 32-bit PNG/JP2 icon | Yes |
| `ic12` | 32x32@2x "retina" 32-bit PNG/JP2 icon | Yes |
| `ic13` | 128x128@2x "retina" 32-bit PNG/JP2 icon | Yes |
| `ic14` | 256x256@2x "retina" 32-bit PNG/JP2 icon | Yes |

## License

Expand Down
37 changes: 32 additions & 5 deletions src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,41 @@ impl IconElement {
let width = icon_type.pixel_width();
let height = icon_type.pixel_width();
match icon_type.encoding() {
#[cfg(feature = "pngio")]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line needs to be restored so that the crate can still build with the pngio feature disabled.

Encoding::JP2PNG => {
let image: Image;
if self.data.starts_with(&JPEG_2000_FILE_MAGIC_NUMBER) {
let msg = "element to be decoded contains JPEG 2000 \
data, which is not yet supported";
return Err(Error::new(ErrorKind::InvalidInput, msg));
let j2k_image = match jpeg2k::Image::from_bytes(&self.data) {
Ok(image) => image,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
e,
))
}
};
let alpha_default = 255u8; // Full opacity
let pixels =
j2k_image.get_pixels(Some(alpha_default)).map_err(
|e| io::Error::new(io::ErrorKind::InvalidData, e),
)?;

let pixel_format = match pixels.format {
jpeg2k::ImageFormat::L8 => PixelFormat::Gray,
jpeg2k::ImageFormat::La8 => PixelFormat::GrayAlpha,
jpeg2k::ImageFormat::Rgb8 => PixelFormat::RGB,
jpeg2k::ImageFormat::Rgba8 => PixelFormat::RGBA,
};

image = Image::from_data(
pixel_format,
pixels.width,
pixels.height,
pixels.data,
)?;
} else {
image = Image::read_png(io::Cursor::new(&self.data))?;
}
let image = Image::read_png(io::Cursor::new(&self.data))?;

if image.width() != width || image.height() != height {
let msg = format!("decoded PNG has wrong dimensions \
({}x{} instead of {}x{})",
Expand Down
11 changes: 2 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,9 @@
//!
//! # Limitations
//!
//! The ICNS format allows some icon types to be encoded either as PNG data or
//! as JPEG 2000 data; however, when encoding icons, this library always uses
//! PNG format, and when decoding icons, it cannot decode JPEG 2000 icons at
//! all (it will detect the JPEG 2000 header and return an error). The reason
//! for this is the apparent lack of JPEG 2000 libraries for Rust; if this ever
//! changes, please feel free to file a bug or a send a pull request.
//!
//! Additionally, this library does not yet support many of the older icon
//! This library does not yet support many of the older icon
//! types used by earlier versions of Mac OS (such as `ICN#`, a 32x32 black and
//! white icon). Again, pull requests (with suitable tests) are welcome.
//! white icon). Pull requests (with suitable tests) are welcome.
//!
//! # Example usage
//!
Expand Down
18 changes: 18 additions & 0 deletions tests/golden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@ fn encode_ic11() {
encoder_test("32x32.png", IconType::RGBA32_16x16_2x, "ic11.icns");
}

#[test]
fn decode_ic13() {
decoder_test("ic13.icns", IconType::RGBA32_128x128_2x, "256x256.png");
CharlieS1103 marked this conversation as resolved.
Show resolved Hide resolved
}

#[test]
fn decode_ic08(){
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test seems to be failing for me when I run it locally. (Hmm, looks like I need to set up CI for this repo.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure why, given the JP2000 decoding is working (which I'm not totally sure of as I tested it with a jp2000 file which I created of type ic10 and it didn't seem to function)
I believe that the test should've passed but I also have not spent much time in this repo overall.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just now enabled CI testing for this repo. If you rebase, we should be able to see the results of that.

decoder_test("ic08.icns", IconType::RGBA32_256x256, "256x256.png");
}

#[test]
fn decode_jpeg2000_256x256() {
decoder_test("loom.icns", IconType::RGBA32_512x512, "loom-512x512.png");
}


Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor style nitpick: Please remove the extra lines here (just one blank line between functions).



fn decoder_test(icns_name: &str, icon_type: IconType, png_name: &str) {
let family = load_icns_file(icns_name).unwrap();
let image = family.get_icon_with_type(icon_type).unwrap();
Expand Down
Binary file added tests/icns/ic08.icns
Binary file not shown.
Binary file added tests/icns/ic13.icns
Binary file not shown.
Binary file added tests/icns/loom.icns
Binary file not shown.
Binary file added tests/png/256x256.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/png/loom-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.