-
Notifications
You must be signed in to change notification settings - Fork 11
feat: Export XBM Image file #79
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?
Conversation
Reviewer's GuideThis PR implements XBM file export by adding an encoder and file-saver integration, introduces a configurable EPD workflow for custom dimensions and color palettes (complete with UI dialog and dynamic dithering), refactors the movable background editor to compute canvas sizing and load images in memory, and updates various UI components and configuration to support these features. Sequence diagram for XBM export processsequenceDiagram
actor User
participant ImageEditor
participant XbmEncoder
participant FileSaver
participant ScaffoldMessenger
User->>ImageEditor: Clicks 'Export XBM'
ImageEditor->>ScaffoldMessenger: Show 'Exporting XBM files...'
loop For each non-white color
ImageEditor->>ImageEditor: extractColorPlaneAsImage(color, baseImage)
ImageEditor->>XbmEncoder: encode(colorPlaneImage, variableName)
XbmEncoder-->>ImageEditor: XBM string
ImageEditor->>FileSaver: saveFile(name, bytes, ext, mimeType)
end
ImageEditor->>ScaffoldMessenger: Show success/failure message
ER diagram for Epd and ConfigurableEpd data structure changeserDiagram
EPD ||--o{ CONFIGURABLE_EPD : extends
CONFIGURABLE_EPD {
int width
int height
string name
list colors
list namedProcessingMethods
}
NAMED_IMAGE_FILTER {
function filter
string name
}
CONFIGURABLE_EPD ||--o{ NAMED_IMAGE_FILTER : has
EPD {
int width
int height
string name
list colors
}
Class diagram for ConfigurableEpd and XbmEncoderclassDiagram
class Epd {
<<abstract>>
int width
int height
String name
List<Color> colors
String modelId
String imgPath
Driver controller
List<Function> processingMethods
extractColorPlaneAsImage(Color, img.Image)
}
class ConfigurableEpd {
int width
int height
String name
List<Color> colors
List<NamedImageFilter> namedProcessingMethods
List<Function> processingMethods
List<String> processingMethodNames
_addProcessingMethods()
_createDynamicPalette()
}
class NamedImageFilter {
Function(img.Image) filter
String name
}
class XbmEncoder {
static String encode(img.Image, String)
}
Epd <|-- ConfigurableEpd
ConfigurableEpd "1" *-- "*" NamedImageFilter
File-Level Changes
Assessment against linked issues
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 @Vishveshwara - I've reviewed your changes and found some issues that need to be addressed.
- This PR bundles dynamic canvas sizing, configurable EPD support, XBM export, and UI tweaks all in one—consider splitting into smaller focused PRs to make review and future maintenance easier.
- The image-flipping and export logic is duplicated between
_exportXbmFiles
and the transfer button handler—extract the flipping/apply calls into a single helper to avoid redundancy. - You’re recalculating canvas dimensions on every build; consider moving
_calculateCanvasDimensions
intodidChangeDependencies
or usingLayoutBuilder
constraints so it only runs when the size actually changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- This PR bundles dynamic canvas sizing, configurable EPD support, XBM export, and UI tweaks all in one—consider splitting into smaller focused PRs to make review and future maintenance easier.
- The image-flipping and export logic is duplicated between `_exportXbmFiles` and the transfer button handler—extract the flipping/apply calls into a single helper to avoid redundancy.
- You’re recalculating canvas dimensions on every build; consider moving `_calculateCanvasDimensions` into `didChangeDependencies` or using `LayoutBuilder` constraints so it only runs when the size actually changes.
## Individual Comments
### Comment 1
<location> `lib/view/widget/image_list.dart:207` </location>
<code_context>
? [
BoxShadow(
- color: colorPrimary.withValues(alpha: .2),
+ color: colorPrimary.withValues(alpha: .4),
blurRadius: 8,
offset: const Offset(0, 4),
</code_context>
<issue_to_address>
The method 'withValues' does not exist on Color; likely a typo.
Use 'withOpacity' or 'withAlpha' to set the alpha channel, as 'withValues' will cause a runtime error.
</issue_to_address>
### Comment 2
<location> `lib/util/xbm_encoder.dart:33` </location>
<code_context>
+ // Ensure we don't read past the image's width
+ if (x < width) {
+ final pixel = image.getPixel(x, y);
+ // In a monochrome image, a pixel's "on" state is typically white.
+ // We check the red channel, but luminance would also work.
+ if (pixel.r > 128) {
+ // Set the corresponding bit in the byte.
+ // XBM bits are typically ordered from right to left.
</code_context>
<issue_to_address>
XBM 'on' bit is typically black, not white.
The current logic sets bits for white pixels, which may invert the intended output. Please invert the condition so bits are set for black ('on') pixels, as per XBM convention.
</issue_to_address>
### Comment 3
<location> `lib/view/display_selection_screen.dart:33` </location>
<code_context>
int selectedIndex = -1;
+ void _showConfigurableDialog() async {
+ final configurable = displays.last as ConfigurableEpd;
+ final result = await showDialog<_CustomEpdConfig>(
+ context: context,
</code_context>
<issue_to_address>
Direct cast to ConfigurableEpd may throw if displays is modified.
Consider adding a type check before casting or using a method to reliably identify the ConfigurableEpd instance.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@kienvo I have it working now, can you please check the xbm images in this folder |
@@ -2,7 +2,9 @@ | |||
<application | |||
android:label="magic_epaper_app" | |||
android:name="${applicationName}" | |||
android:icon="@mipmap/ic_launcher"> | |||
android:icon="@mipmap/ic_launcher" | |||
android:enableOnBackInvokedCallback="true"> |
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.
This line is added for the File_saver module to work
@Dhruv1797 please review this |
xbm.final.mp4 |
@mariobehling I have added the presets like you have asked in the meet |
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.
I don't really want a full picture when developing a epaper application and I think others will do the same. Suppose I want to change a part of the screen so how do I generate bitmap code for that part of the screen? and why do I need presets for full screen?.
there is a custom option in the end of the presets which will allow you to select the resolution and the colors you want , please check from 13th second of the video. mario had wanted the presets so that people who are using this app to create the xbm images don't need to know their resolution exactly |
@kienvo please mention if there are any problems |
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.
Can you make the UI so that users can select the location to save the files? And create a new folder, then export the files to it would be nice if possible.
@kienvo i have added the path in InternalStorage/MagicEpaper/XBM xbm.ui.and.path.fixed.mp4 |
@Vishveshwara please resolve conflicts |
Fixes #67
Summary by Sourcery
Implement XBM export capabilities and custom e-paper display configuration
New Features:
Enhancements:
Chores: