-
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
Open
Vishveshwara
wants to merge
27
commits into
fossasia:main
Choose a base branch
from
Vishveshwara:export
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
bc01993
Fixed sizing for multiple displays
Vishveshwara 1762360
fixed formatting
Vishveshwara 75b34cd
WIP: initial implementation of XBM export
Vishveshwara 491ac49
Merge branch 'main' into export
Vishveshwara cfd3491
FIxed Build issue
Vishveshwara 2596bcb
Merge branch 'main' into export
Vishveshwara cf6998b
Fixing Common Build
Vishveshwara 9c1a923
removed import in xbmencoder
Vishveshwara f27f8f2
Added Color_Util to avoid code duplication
Vishveshwara 4108413
Fixed XBM encoding logic issue
Vishveshwara 1848c82
Code refactoring and documentation added
Vishveshwara 2794d4b
Fixing info from flutter analyze
Vishveshwara d82bb27
fix common build
Vishveshwara e2ee492
dart format
Vishveshwara 75d89d0
fixing common build
Vishveshwara c93ec47
common build fixed
Vishveshwara be4ff7b
Merge branch 'main' into export
Vishveshwara bff950f
Merge branch 'main' into export
Vishveshwara a0f2ba7
dart formatting
Vishveshwara 38f6c55
fix error
Vishveshwara 0e6f7d9
Added some presets for the displays from good display and wave share …
Vishveshwara e91f503
formatted
Vishveshwara 576aa3f
Merge branch 'main' into export
Vishveshwara 1ccaa47
Fixed merging errors
Vishveshwara ee260f5
Fixed UI and added file path
Vishveshwara 95c4cc7
Merge branch 'main' into export
Vishveshwara 483203b
Removed refresh options for the export screen and fixed conflicts
Vishveshwara File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 0 additions & 12 deletions
12
lib/pro_image_editor/core/constants/example_constants.dart
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
/// A utility class for color-related operations and mappings. | ||
class ColorUtils { | ||
/// A mapping from [Color] objects to their display names. | ||
static final Map<Color, String> _colorMap = { | ||
Colors.black: 'Black', | ||
Colors.white: 'White', | ||
Colors.red: 'Red', | ||
Colors.yellow: 'Yellow', | ||
Colors.orange: 'Orange', | ||
Colors.green: 'Green', | ||
Colors.blue: 'Blue', | ||
}; | ||
|
||
/// Compares two [Color] objects for equality based on their ARGB values. | ||
/// | ||
/// Returns `true` if both colors have the same ARGB value, otherwise `false`. | ||
static bool colorsEqual(Color a, Color b) { | ||
return a.toARGB32() == b.toARGB32(); | ||
} | ||
|
||
/// Checks if a given [color] exists within the provided [colorList]. | ||
/// | ||
/// Returns `true` if the color is found in the list, otherwise `false`. | ||
static bool colorExistsInList(Color color, List<Color> colorList) { | ||
return colorList.any((c) => colorsEqual(c, color)); | ||
} | ||
|
||
/// Returns a user-friendly display name for the given [color]. | ||
/// | ||
/// If the color is not found in the predefined color map, returns 'Color'. | ||
static String getColorDisplayName(Color color) { | ||
for (final entry in _colorMap.entries) { | ||
if (colorsEqual(entry.key, color)) { | ||
return entry.value; | ||
} | ||
} | ||
return 'Color'; | ||
} | ||
|
||
/// Returns a file-friendly name for the given [color], used in exports. | ||
/// | ||
/// If the color is not a predefined one, returns its ARGB value as a hex string. | ||
static String getColorFileName(Color color) { | ||
if (colorsEqual(color, Colors.black)) return 'black'; | ||
if (colorsEqual(color, Colors.red)) return 'red'; | ||
if (colorsEqual(color, Colors.yellow)) return 'yellow'; | ||
if (colorsEqual(color, Colors.blue)) return 'blue'; | ||
if (colorsEqual(color, Colors.green)) return 'green'; | ||
if (colorsEqual(color, Colors.orange)) return 'orange'; | ||
return color.toARGB32().toRadixString(16); | ||
} | ||
|
||
/// Returns a label for the given [color], using available color choices as fallback. | ||
/// | ||
/// If the color is not a predefined one, checks [availableColorChoices] for a matching label. | ||
/// If no match is found, returns 'Color'. | ||
static String getColorLabel( | ||
Color color, List<dynamic> availableColorChoices) { | ||
final displayName = getColorDisplayName(color); | ||
if (displayName != 'Color') return displayName; | ||
|
||
for (final choice in availableColorChoices) { | ||
if (colorsEqual(choice.color, color)) { | ||
return choice.label; | ||
} | ||
} | ||
|
||
return 'Color'; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:magic_epaper_app/constants/asset_paths.dart'; | ||
import 'package:magic_epaper_app/util/epd/driver/driver.dart'; | ||
import 'package:magic_epaper_app/util/epd/driver/uc8253.dart'; | ||
import 'package:magic_epaper_app/util/image_processing/image_processing.dart'; | ||
import 'package:image/image.dart' as img; | ||
import 'epd.dart'; | ||
|
||
/// Represents a named image filter for use in e-paper image processing. | ||
/// | ||
/// Associates a filter function with a display name for UI and export purposes. | ||
class NamedImageFilter { | ||
/// The image filter function to apply. | ||
final img.Image Function(img.Image) filter; | ||
|
||
/// The display name of the filter. | ||
final String name; | ||
|
||
/// Creates a [NamedImageFilter] with the given [filter] and [name]. | ||
NamedImageFilter(this.filter, this.name); | ||
} | ||
|
||
/// A dynamically configurable e-paper display for custom export and processing. | ||
/// | ||
/// This class is used to export dithered images and supports: | ||
/// - Changing the color palette for dithering (custom colors) | ||
/// - Setting the height and width of the display | ||
/// - Generating XBM output for custom displays | ||
/// | ||
/// It allows users to experiment with different display configurations and image processing methods. | ||
class ConfigurableEpd extends Epd { | ||
/// The width of the display in pixels. | ||
@override | ||
final int width; | ||
|
||
/// The height of the display in pixels. | ||
@override | ||
final int height; | ||
|
||
/// The display name for UI and export. | ||
@override | ||
final String name; | ||
|
||
/// The list of supported colors for dithering and export. | ||
@override | ||
final List<Color> colors; | ||
|
||
/// The model identifier for this configurable export display. | ||
@override | ||
String get modelId => 'NA'; | ||
|
||
/// The asset path for the display image (custom export icon). | ||
@override | ||
String get imgPath => ImageAssets.customExport; | ||
|
||
/// Using a dummy driver as this is only for exporting images. | ||
@override | ||
Driver get controller => Uc8253() as Driver; | ||
|
||
/// The list of named image processing methods available for this display. | ||
final List<NamedImageFilter> namedProcessingMethods = []; | ||
|
||
@override | ||
List<img.Image Function(img.Image)> get processingMethods => | ||
namedProcessingMethods.map((f) => f.filter).toList(); | ||
|
||
List<String> get processingMethodNames => | ||
namedProcessingMethods.map((f) => f.name).toList(); | ||
|
||
/// Creates a [ConfigurableEpd] with the given [width], [height], [colors], and optional [name]. | ||
/// | ||
/// The color palette and display size can be customized, and dithering methods can be chosen. | ||
ConfigurableEpd({ | ||
required this.width, | ||
required this.height, | ||
required this.colors, | ||
this.name = 'Custom Export', | ||
}) { | ||
_addProcessingMethods(); | ||
} | ||
|
||
/// Creates a palette for the 'image' library from a list of Flutter [Color]s. | ||
/// | ||
/// Used for custom dithering with custom color palettes. | ||
img.PaletteUint8 _createDynamicPalette() { | ||
final palette = img.PaletteUint8(colors.length, 3); | ||
for (int i = 0; i < colors.length; i++) { | ||
final color = colors[i]; | ||
palette.setRgb(i, (color.r * 255.0).round(), (color.g * 255.0).round(), | ||
(color.b * 255.0).round()); | ||
} | ||
return palette; | ||
} | ||
|
||
/// Populates the list of processing methods based on the color palette. | ||
void _addProcessingMethods() { | ||
namedProcessingMethods.clear(); | ||
final isBlackAndWhite = colors.length == 2; | ||
if (isBlackAndWhite) { | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
ImageProcessing.bwFloydSteinbergDither, | ||
'Floyd-Steinberg', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
ImageProcessing.bwFalseFloydSteinbergDither, | ||
'False Floyd-Steinberg', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter(ImageProcessing.bwStuckiDither, 'Stucki'), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter(ImageProcessing.bwAtkinsonDither, 'Atkinson'), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter(ImageProcessing.bwHalftoneDither, 'Halftone'), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter(ImageProcessing.bwThreshold, 'Threshold'), | ||
); | ||
} else { | ||
final dynamicPalette = _createDynamicPalette(); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => ImageProcessing.customFloydSteinbergDither( | ||
orgImg, | ||
dynamicPalette, | ||
), | ||
'Floyd-Steinberg', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => ImageProcessing.customFalseFloydSteinbergDither( | ||
orgImg, | ||
dynamicPalette, | ||
), | ||
'False Floyd-Steinberg', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => | ||
ImageProcessing.customStuckiDither(orgImg, dynamicPalette), | ||
'Stucki', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => | ||
ImageProcessing.customAtkinsonDither(orgImg, dynamicPalette), | ||
'Atkinson', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => | ||
ImageProcessing.customHalftoneDither(orgImg, dynamicPalette), | ||
'Halftone', | ||
), | ||
); | ||
namedProcessingMethods.add( | ||
NamedImageFilter( | ||
(img.Image orgImg) => | ||
ImageProcessing.customThreshold(orgImg, dynamicPalette), | ||
'Threshold', | ||
), | ||
); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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