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

Palette sorting #193

Merged
merged 4 commits into from
Sep 10, 2019
Merged
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ matrix:
env: TARGET=x86_64-apple-darwin
cache: cargo
- os: linux
rust: 1.34.0
rust: 1.36.0
env: TARGET=x86_64-unknown-linux-gnu
cache: cargo
- os: linux
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ cargo build --release
cp target/release/oxipng /usr/local/bin
```

The current minimum supported Rust version is **1.34.0**. Oxipng may compile on earlier versions of Rust,
The current minimum supported Rust version is **1.36.0**. Oxipng may compile on earlier versions of Rust,
but there is no guarantee.

Oxipng follows Semantic Versioning.
Expand Down
29 changes: 26 additions & 3 deletions src/reduction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,24 @@ pub fn reduced_palette(png: &PngImage) -> Option<PngImage> {
}
}

let mut used_enumerated : Vec<(usize, &bool)>= used.iter().enumerate().collect();
used_enumerated.sort_by(|a, b| {
Copy link
Owner

Choose a reason for hiding this comment

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

You can use itertools to make this a little more concise.

//Sort by ascending alpha and descending luma.
let color_val = |i| {
let color = palette.get(i).copied()
.unwrap_or_else(|| RGBA8::new(0, 0, 0, 255));
((color.a as i32) << 18)
// These are coefficients for standard sRGB to luma conversion
- (color.r as i32) * 299
- (color.g as i32) * 587
- (color.b as i32) * 114
};
color_val(a.0).cmp(&color_val(b.0))
});

let mut next_index = 0u16;
let mut seen = HashMap::with_capacity(palette.len());
for (i, (used, palette_map)) in used.iter().cloned().zip(palette_map.iter_mut()).enumerate()
for (i, used) in used_enumerated.iter().cloned()
{
if !used {
continue;
Expand All @@ -75,12 +90,12 @@ pub fn reduced_palette(png: &PngImage) -> Option<PngImage> {
.unwrap_or_else(|| RGBA8::new(0, 0, 0, 255));
match seen.entry(color) {
Vacant(new) => {
*palette_map = Some(next_index as u8);
palette_map[i] = Some(next_index as u8);
new.insert(next_index as u8);
next_index += 1;
}
Occupied(remap_to) => {
*palette_map = Some(*remap_to.get());
palette_map[i] = Some(*remap_to.get())
}
}
}
Expand Down Expand Up @@ -211,6 +226,14 @@ pub fn reduce_color_type(png: &PngImage) -> Option<PngImage> {
}
}

//Make sure that palette gets sorted. Ideally, this should be done within reduced_color_to_palette.
if should_reduce_bit_depth && reduced.ihdr.color_type == ColorType::Indexed {
if let Some(r) = reduced_palette(&reduced) {
reduced = Cow::Owned(r);
should_reduce_bit_depth = true;
}
}

if should_reduce_bit_depth {
// Some conversions will allow us to perform bit depth reduction that
// wasn't possible before
Expand Down