Iterate with fewer temp allocations

This commit is contained in:
Kornel Lesiński 2018-07-16 13:41:59 +01:00
parent c530bba261
commit eb75989333
2 changed files with 36 additions and 36 deletions

View file

@ -295,7 +295,7 @@ impl PngData {
}
_ => unreachable!(),
}
last_line = line.data;
last_line = line.data.to_vec();
last_pass = line.pass;
}
filtered
@ -322,17 +322,17 @@ impl PngData {
for line in self.scan_lines() {
reduced.push(line.filter);
for (i, byte) in line.data.iter().enumerate() {
for (i, &byte) in line.data.iter().enumerate() {
if i % 2 == 0 {
// High byte
high_byte = *byte;
high_byte = byte;
} else {
// Low byte
if high_byte != *byte {
if high_byte != byte {
// Can't reduce, exit early
return false;
}
reduced.push(*byte);
reduced.push(byte);
}
}
}
@ -406,8 +406,8 @@ impl PngData {
let mut seen = HashSet::with_capacity(indexed_palette.len());
for line in self.scan_lines() {
match self.ihdr_data.bit_depth {
BitDepth::Eight => for byte in &line.data {
seen.insert(*byte);
BitDepth::Eight => for &byte in line.data {
seen.insert(byte);
},
BitDepth::Four => {
let bitvec = BitVec::from_bytes(&line.data);
@ -489,52 +489,52 @@ impl PngData {
for line in self.scan_lines() {
new_data.push(line.filter);
match self.ihdr_data.bit_depth {
BitDepth::Eight => for byte in &line.data {
if let Some(new_idx) = index_map.get(byte) {
new_data.push(*new_idx);
BitDepth::Eight => for &byte in line.data {
if let Some(&new_idx) = index_map.get(&byte) {
new_data.push(new_idx);
} else {
new_data.push(*byte);
new_data.push(byte);
}
},
BitDepth::Four => for byte in &line.data {
let upper = *byte & 0b1111_0000;
let lower = *byte & 0b0000_1111;
BitDepth::Four => for &byte in line.data {
let upper = byte & 0b1111_0000;
let lower = byte & 0b0000_1111;
let mut new_byte = 0u8;
new_byte |= if let Some(new_idx) = index_map.get(&(upper >> 4)) {
*new_idx << 4
new_byte |= if let Some(&new_idx) = index_map.get(&(upper >> 4)) {
new_idx << 4
} else {
upper
};
new_byte |= if let Some(new_idx) = index_map.get(&lower) {
*new_idx
new_byte |= if let Some(&new_idx) = index_map.get(&lower) {
new_idx
} else {
lower
};
new_data.push(new_byte);
},
BitDepth::Two => for byte in &line.data {
let one = *byte & 0b1100_0000;
let two = *byte & 0b0011_0000;
let three = *byte & 0b0000_1100;
let four = *byte & 0b0000_0011;
BitDepth::Two => for &byte in line.data {
let one = byte & 0b1100_0000;
let two = byte & 0b0011_0000;
let three = byte & 0b0000_1100;
let four = byte & 0b0000_0011;
let mut new_byte = 0u8;
new_byte |= if let Some(new_idx) = index_map.get(&(one >> 6)) {
*new_idx << 6
new_byte |= if let Some(&new_idx) = index_map.get(&(one >> 6)) {
new_idx << 6
} else {
one
};
new_byte |= if let Some(new_idx) = index_map.get(&(two >> 4)) {
*new_idx << 4
new_byte |= if let Some(&new_idx) = index_map.get(&(two >> 4)) {
new_idx << 4
} else {
two
};
new_byte |= if let Some(new_idx) = index_map.get(&(three >> 2)) {
*new_idx << 2
new_byte |= if let Some(&new_idx) = index_map.get(&(three >> 2)) {
new_idx << 2
} else {
three
};
new_byte |= if let Some(new_idx) = index_map.get(&four) {
*new_idx
new_byte |= if let Some(&new_idx) = index_map.get(&four) {
new_idx
} else {
four
};

View file

@ -12,7 +12,7 @@ pub struct ScanLines<'a> {
}
impl<'a> Iterator for ScanLines<'a> {
type Item = ScanLine;
type Item = ScanLine<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.end == self.png.raw_data.len() {
None
@ -109,7 +109,7 @@ impl<'a> Iterator for ScanLines<'a> {
}
Some(ScanLine {
filter: self.png.raw_data[self.start],
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
data: &self.png.raw_data[(self.start + 1)..self.end],
pass: current_pass,
})
} else {
@ -122,7 +122,7 @@ impl<'a> Iterator for ScanLines<'a> {
self.end = self.start + bytes_per_line + 1;
Some(ScanLine {
filter: self.png.raw_data[self.start],
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
data: &self.png.raw_data[(self.start + 1)..self.end],
pass: None,
})
}
@ -131,11 +131,11 @@ impl<'a> Iterator for ScanLines<'a> {
#[derive(Debug, Clone)]
/// A scan line in a PNG image
pub struct ScanLine {
pub struct ScanLine<'a> {
/// The filter type used to encode the current scan line (0-4)
pub filter: u8,
/// The byte data for the current scan line, encoded with the filter specified in the `filter` field
pub data: Vec<u8>,
pub data: &'a[u8],
/// The current pass if the image is interlaced
pub pass: Option<u8>,
}