-
Notifications
You must be signed in to change notification settings - Fork 10
Add support for image and GIF rendering #85
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
base: main
Are you sure you want to change the base?
Add support for image and GIF rendering #85
Conversation
Reviewer's GuideThis PR expands payload generation to support embedding static images and animated GIFs by leveraging the image crate, refactors the payload generator (typo fix and dimension constants), and adds the image dependency. Entity relationship diagram for Content enum variantserDiagram
CONTENT {
STRING Bitstring
STRING BitmapBase64
PATH BitmapFile
PATH ImageFile
PATH GifFile
}
CONTENT ||--o{ IMAGEFILE : contains
CONTENT ||--o{ GIFFILE : contains
Class diagram for updated Content enum and payload generationclassDiagram
class Content {
<<enum>>
Bitstring
BitmapBase64
BitmapFile
ImageFile
GifFile
}
class Args
class PayloadBuffer
class ImageReader
class GifDecoder
class Frame
class Pixel
class Point
class BinaryColor
Content <|-- ImageFile
Content <|-- GifFile
Args --> Content
Args --> PayloadBuffer
ImageReader --> ImageFile
GifDecoder --> GifFile
GifDecoder --> Frame
Frame --> PayloadBuffer
Pixel --> PayloadBuffer
Point --> Pixel
BinaryColor --> Pixel
Class diagram for generate_payload function changesclassDiagram
class generate_payload {
+DISPLAY_HEIGHT: u32
+DISPLAY_WIDTH: u32
+args: &mut Args
+returns: Result<PayloadBuffer>
}
generate_payload --> Content
generate_payload --> PayloadBuffer
generate_payload --> ImageReader
generate_payload --> GifDecoder
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @weberval - I've reviewed your changes - here's some feedback:
- The new image and GIF handling blocks share a lot of pixel‐drawing logic—consider extracting that into a helper function to avoid duplication.
- Avoid hard‐coded dimensions and magic numbers (e.g. 44, 11, 48, 31)—pull them into named constants or make them configurable for clarity.
- Replace the
expect
on GIF decoding with proper error propagation (using?
orwith_context
) to avoid unintended panics.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new image and GIF handling blocks share a lot of pixel‐drawing logic—consider extracting that into a helper function to avoid duplication.
- Avoid hard‐coded dimensions and magic numbers (e.g. 44, 11, 48, 31)—pull them into named constants or make them configurable for clarity.
- Replace the `expect` on GIF decoding with proper error propagation (using `?` or `with_context`) to avoid unintended panics.
## Individual Comments
### Comment 1
<location> `src/main.rs:231` </location>
<code_context>
let image = Image::new(&image_raw, Point::zero());
payload.add_message_drawable(style, &image);
}
+ Content::ImageFile { img_file } => {
+ let img_reader = ImageReader::open(img_file)?;
+ let img = img_reader
+ .decode()?
+ .resize(u32::MAX, 11, FilterType::Nearest)
+ .into_luma8();
+ let (width, height) = img.dimensions();
+ let mut buffer = payload.add_message(style, (width as usize + 7) / 8);
+ for y in 0..height {
+ for x in 0..width {
+ if img.get_pixel(x, y).0 > [31] {
+ Pixel(Point::new(x.try_into()?, y.try_into()?), BinaryColor::On)
+ .draw(&mut buffer)?;
+ }
+ }
+ }
</code_context>
<issue_to_address>
Potential edge case: image resizing may not preserve aspect ratio.
Resizing with `.resize(u32::MAX, 11, FilterType::Nearest)` may produce images with extremely large widths. Consider limiting the maximum width or enforcing an aspect ratio to avoid display issues with very wide images.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@sourcery-ai review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @weberval - I've reviewed your changes and they look great!
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location> `src/main.rs:271` </location>
<code_context>
+ );
+ }
+
+ let mut buffer = payload.add_message(
+ style,
+ ((DISPLAY_WIDTH as usize + 4) * frame_count).div_ceil(8),
+ );
+
+ for (i, frame) in frames.iter().enumerate() {
</code_context>
<issue_to_address>
Calculation for GIF buffer size may not be correct for all cases.
This calculation assumes a fixed 4-pixel gap between frames, which may not always apply. Please make the calculation adaptable or clearly document the assumptions.
Suggested implementation:
```rust
// Define the gap between frames in pixels. Adjust as needed.
const FRAME_GAP: usize = 4; // Assumes a 4-pixel gap between frames. Change if needed.
let mut buffer = payload.add_message(
style,
((DISPLAY_WIDTH as usize + FRAME_GAP) * frame_count).div_ceil(8),
);
```
```rust
for y in 0..DISPLAY_HEIGHT {
for x in 0..DISPLAY_WIDTH {
if buf.get_pixel(x, y).to_luma().0 > [31] {
Pixel(
Point::new(
(x as usize + i * (DISPLAY_WIDTH as usize + FRAME_GAP))
.try_into()?,
y.try_into()?,
),
```
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
"expected 11 lines in bitstring, found {} lines", | ||
lines.len() == DISPLAY_HEIGHT as usize, | ||
"expected {} lines in bitstring, found {} lines", | ||
DISPLAY_HEIGHT, | ||
lines.len() | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Calculation for GIF buffer size may not be correct for all cases.
This calculation assumes a fixed 4-pixel gap between frames, which may not always apply. Please make the calculation adaptable or clearly document the assumptions.
Suggested implementation:
// Define the gap between frames in pixels. Adjust as needed.
const FRAME_GAP: usize = 4; // Assumes a 4-pixel gap between frames. Change if needed.
let mut buffer = payload.add_message(
style,
((DISPLAY_WIDTH as usize + FRAME_GAP) * frame_count).div_ceil(8),
);
for y in 0..DISPLAY_HEIGHT {
for x in 0..DISPLAY_WIDTH {
if buf.get_pixel(x, y).to_luma().0 > [31] {
Pixel(
Point::new(
(x as usize + i * (DISPLAY_WIDTH as usize + FRAME_GAP))
.try_into()?,
y.try_into()?,
),
Summary by Sourcery
Implement image and animated GIF support by extending content variants, processing image/GIF frames into the payload buffer, rename payload generator function, and enforce display dimensions via constants
New Features:
Enhancements:
Build: