feat: use solid fills with rle compressed images#52
feat: use solid fills with rle compressed images#52Ddystopia wants to merge 2 commits intoembedded-graphics:mainfrom
Conversation
|
I did nothing new, just moved code to methods to reuse them from both |
|
I like the performance improvement this brings, but the code is getting a bit repetitive. I think we should try to refactor it to make it easier to maintain in the future. Here is my suggestion: |
9dea866 to
6cc5879
Compare
|
What would you say about this api? |
a021e6f to
169a74d
Compare
169a74d to
7774e7d
Compare
rfuest
left a comment
There was a problem hiding this comment.
What would you say about this api?
Much better. I like the way the RLE decoding and conversion into pixels are now more decoupled and I think we can make the RLE state handling even simpler now (see comments below).
| }; | ||
| } | ||
| return Some(RawU8::from(value)); | ||
| // total pixels represented by this run |
There was a problem hiding this comment.
At least for the RLE8 case I don't think we need the RLE state anymore. If you take a look at, for example, the way RleState::Running is handled. The state is set to running in RleState::Starting, just to be immediately reset back to Starting in the next loop iteration. And the number of pixels is first decremented by one to then be incremented by one again.
| // alternating pattern -> only one pixel of this color now | ||
| if remaining == 0 { | ||
| self.rle_state = RleState::Starting; | ||
| } else { | ||
| self.rle_state = RleState::Running { | ||
| remaining: remaining.saturating_sub(1), | ||
| value, | ||
| is_odd, | ||
| }; | ||
| } | ||
| return Some((RawU4::from(nibble_value), 1)); |
There was a problem hiding this comment.
For the alternating case it might be worth looking into returning an enum instead of the tuple from the runs iterators. Something like:
enum RleRun<R> {
Solid {
color: R,
count: usize,
},
Alternating {
colors: [R; 2],
count: usize,
}
}This would make it possible to draw the alternating pattern with DrawTarget::draw_contiguous, instead of drawing individual pixels.
| pub fn runs(&mut self) -> &mut I { | ||
| &mut self.runs | ||
| } |
There was a problem hiding this comment.
I think this should be called as_runs and a to_runs method could also be useful:
| pub fn runs(&mut self) -> &mut I { | |
| &mut self.runs | |
| } | |
| pub fn as_runs(&mut self) -> &mut I { | |
| &mut self.runs | |
| } | |
| pub fn to_runs(self) -> I { | |
| self.runs | |
| } |
| loop { | ||
| let (raw, count) = match self.run.as_mut() { | ||
| Some(run) => run, | ||
| None => { | ||
| self.run = Some(self.runs.next()?); | ||
| self.run.as_mut().unwrap() | ||
| } | ||
| }; | ||
| if *count > 0 { | ||
| *count -= 1; | ||
| return Some(*raw); | ||
| } else { | ||
| self.run = None; | ||
| } | ||
| } |
There was a problem hiding this comment.
There is no need to use an Option for the current run, because count == 0 can be used to describe the same state as None.
By changing the struct to:
pub struct RleColors<C, I: Iterator<Item = (C, usize)>> {
runs: I,
color: C,
count: usize,
}(color can be initialized to C::default() in the constructor)
the next method can be simplified to:
| loop { | |
| let (raw, count) = match self.run.as_mut() { | |
| Some(run) => run, | |
| None => { | |
| self.run = Some(self.runs.next()?); | |
| self.run.as_mut().unwrap() | |
| } | |
| }; | |
| if *count > 0 { | |
| *count -= 1; | |
| return Some(*raw); | |
| } else { | |
| self.run = None; | |
| } | |
| } | |
| loop { | |
| if self.count == 0 { | |
| (self.color, self.count) = self.runs.next()?; | |
| } | |
| if self.count > 0 { | |
| self.count -= 1; | |
| return Some(self.color); | |
| } | |
| } |
Thank you for helping out with tinybmp development! Please:
CHANGELOG.mdentry in the Unreleased section under the appropriate heading (Added, Fixed, etc) if your changes affect the public APIrustfmton the projectjust build(Linux/macOS only) and make sure it passes. If you use Windows, check that CI passes once you've opened the PR.PR description
Added a
next_solid_chunkfor rle colors, it allows to make use offill_solidthat gave a huge performance boost on my mcu.