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 bit order and direction support to ImageRaw and Framebuffer #711

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from

Conversation

rfuest
Copy link
Member

@rfuest rfuest commented Nov 16, 2022

This draft PR contains the latest WIP version of my experiment with adding bit order and direction settings to ImageRaw and Framebuffer.

Closes #697

@jamwaffles
Copy link
Member

Hey Ralf, I just pushed some changes to this branch. Hopefully that's ok with you. If not, please let me know and I'll fork this PR into a new one.

I'll see if I can integrate FrameBuffer into ssd1306 and check the output on a real display 🤞

src/image/image_raw.rs Outdated Show resolved Hide resolved
@rfuest
Copy link
Member Author

rfuest commented Nov 24, 2022

Hopefully that's ok with you. If not, please let me know and I'll fork this PR into a new one.

Sure that is OK. Great to see some progress on this.

I'll see if I can integrate FrameBuffer into ssd1306 and check the output on a real display crossed_fingers

Good luck! While you are at it you could also try to use the rotation or orientation types from https://github.com/embedded-graphics/display-driver-hal, if you like.

I think we should release a first alpha after this PR is merged to make it easier to depend on the new features.

@jamwaffles
Copy link
Member

I've just added horizontal/vertical support for < 8BPP, using this PR in ssd1306 as a test bench.

TODO

  • Vertical direction for 16BPP and above, mostly for completeness' sake. I don't know of a display that uses this but maybe there's one out there...
  • Unit tests

src/framebuffer.rs Outdated Show resolved Hide resolved
src/framebuffer.rs Outdated Show resolved Hide resolved
src/framebuffer.rs Outdated Show resolved Hide resolved
@rfuest
Copy link
Member Author

rfuest commented Nov 24, 2022

Should we revert the change I made in e-g 0.7 that ImageRaw::new only takes the width as an argument? IMO this doesn't work very well with horizontal and vertical images, where you need to specify the width in one case and the height in the other.

I would suggest to change the ImageRaw::new constructor to fn new(data: &[u8], size: Size) -> Result<Self, ImageRawError> and return an error, if the image data isn't large enough. This does work for vertical and horizontal images and provides better feedback to the user, if the data is incorrectly sized.

But we would also need an additional constructor, that could be used in const context, because you cannot unwrap the result of ImageRaw::new. This constructor would shrink the image if the data is too short, instead of returning an error.

src/framebuffer.rs Outdated Show resolved Hide resolved
@rfuest
Copy link
Member Author

rfuest commented Nov 24, 2022

One more difference between ImageRaw and Framebuffer: ImageRaw does support color types without Msb0/Lsb0 or BigEndian/LittleEndian annotations, which Framebuffer doesn't. In this case ImageRaw defaults to Msb0 and LittleEndian. Do you prefer that the bit order/byte order must be explicitly set or should we have one default order?

@rfuest rfuest marked this pull request as ready for review December 23, 2022 19:24
Copy link
Member

@jamwaffles jamwaffles left a comment

Choose a reason for hiding this comment

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

This PR is enormous. Did it suffer from a little scope creep? I'm getting a bit concerned by the number of traits e-g has now. I appreciate we might need them all but I still think it's worth raising.

Looks like the CI has a doc check failure, nothing too difficult.

src/mono_font/mod.rs Show resolved Hide resolved
@rfuest
Copy link
Member Author

rfuest commented Dec 25, 2022

Did it suffer from a little scope creep?

A bit, but most changes are directly related to finishing and optimizing the framebuffer implementation. I needed a working framebuffer implementation for other projects and didn't want to wait any longer.

I'm getting a bit concerned by the number of traits e-g has now. I appreciate we might need them all but I still think it's worth raising.

If you have any concrete examples of traits which aren't necessary we could discuss to remove them.

@rfuest
Copy link
Member Author

rfuest commented May 15, 2023

I've just updated the branch to the latest master version. While I'm not sure what my involvement with the e-g project will be in the future I would like to get this PR, or at least part of it, merged.
@bugadani I've noticed that you did recently start to contribute to e-g again, would you perhaps be interested in looking at the PR? A fresh set of eyes might help to get this PR over the line.

@bugadani
Copy link
Member

@rfuest I think my contributions will be limited to bugfixes going forward, but I'm happy to take a look at this. I'll need to familiarize myself with the situation, though, which will take some time.

Copy link
Member

@bugadani bugadani left a comment

Choose a reason for hiding this comment

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

This was an experience for sure.

I'm not convinced ColorType is a good addition. It feels like extreme deduplication that just causes trait-bloat and overcomplicates things. I have similar feelings for StorablePixelColor.

Running clippy on the PR gives me 16 warnings. I don't know how many are from this PR, but you might want to clean up the ones introduced here.

core/src/draw_target.rs Outdated Show resolved Hide resolved
core/src/pixelcolor/mod.rs Show resolved Hide resolved
#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
pub enum DataOrderEnum {
/// Default data order.
Default,
Copy link
Member

Choose a reason for hiding this comment

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

Instead of an indirect terminology, can we use MostSignificantFirst / LeastSignificantFirst here?

Also, I think deny(missing_docs) is a terrible idea if that results in multiplying trivial comments like the one above.

Copy link
Member Author

Choose a reason for hiding this comment

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

Instead of an indirect terminology, can we use MostSignificantFirst / LeastSignificantFirst here?

I don't like this either, but for bits the default order is Msb0 and for bytes it is LittleEndian.

src/array.rs Outdated Show resolved Hide resolved
src/array.rs Show resolved Hide resolved
src/framebuffer/array.rs Outdated Show resolved Hide resolved
assert_eq!(framebuffer.data(), &expected_data);
}
}
macro_rules! impl_framebuffer_tests {
Copy link
Member

Choose a reason for hiding this comment

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

I have to say, this really feels like a test suite that needs some tests to test itself, but I also understand the motivation of not wanting to write the same thing 15 times over.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have to say, this really feels like a test suite that needs some tests to test itself, ...

It's not great, but I couldn't come up with something better.

..., but I also understand the motivation of not wanting to write the same thing 15 times over.

Make that 56 times 😉.

{
let size = self.size();

Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this part shrink the area to the image and try to draw that? Just doing nothing might be surprising for users.

Copy link
Member Author

Choose a reason for hiding this comment

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

Users aren't supposed to call this method directly. area should never be outside the image.

Copy link
Member

Choose a reason for hiding this comment

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

If that's the case, taking the condition should be unreachable!()

Copy link
Member Author

Choose a reason for hiding this comment

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

You are probably right, but I haven't looked at this code in detail for a long time and don't want to change it in this PR, without taking a closer look first.

src/image/mod.rs Show resolved Hide resolved
@@ -110,8 +111,11 @@ impl<T: StyledDimensions<S>, S> Dimensions for Styled<T, S> {
}
}

impl<T: StyledDrawable<S>, S> Drawable for Styled<T, S> {
type Color = T::Color;
impl<T: StyledDrawable<S>, S: ColorType> ColorType for Styled<T, S> {
Copy link
Member

Choose a reason for hiding this comment

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

And this was the point where I started wondering if ColorType should have been blanket-implemented for every drawable instead, and if you should have kept Drawable::Color. There are breaking changes, and there are soul-breaking changes, and this feels the latter.

Copy link
Member Author

Choose a reason for hiding this comment

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

The ColorType trait was the change I wasn't sure about. It was inspired by the ErrorType trait in embedded-hal. I like the idea of having one common place to specify the color type, instead of associated color types in 6 separate traits, but it causes a lot of changes.

There are breaking changes, and there are soul-breaking changes, and this feels the latter.

That might be a little dramatic. Would this affect the average user? And most library authors should only need to change a few lines of code.

Copy link
Member

Choose a reason for hiding this comment

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

That might be a little dramatic.

Of course, that came after an hour and a half of reading the PR :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Of course, that came after an hour and a half of reading the PR :)

OK, I can understand that and thanks for taking the time to review this PR, which should never have gotten so huge.

@rfuest
Copy link
Member Author

rfuest commented May 16, 2023

I've updated the changelog, because the entries were still included in the 0.5 section. From my point of view the PR should be ready to be merged, if there is no more opposition against the ColorType change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a way to specify packing direction for framebuffer
3 participants