-
Notifications
You must be signed in to change notification settings - Fork 46
feat: add flip functionality on final processed image #46
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
Changes from all commits
eb4e438
823b679
5dba459
a9770a0
246937f
55d7cbe
663feed
b398360
88c869f
1210010
8b5122f
16a54fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| class ImageAssets { | ||
| static const String flipHorizontal = 'assets/images/h-flip.png'; | ||
| static const String whiteBoard = 'assets/canvas/white.png'; | ||
| static const String redBoard = 'assets/canvas/red.png'; | ||
| static const String blackBoard = 'assets/canvas/black.png'; | ||
| static const String epaper37Bwr = 'assets/images/displays/epaper_3.7_bwr.png'; | ||
| static const String epaper37Bw = 'assets/images/displays/epaper_3.7_bw.PNG'; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| class StringConstants { | ||
| static const String appName = 'Magic epaper'; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import 'package:image/image.dart' as img; | ||
| import 'package:magic_epaper_app/util/epd/epd.dart'; | ||
|
|
||
| List<img.Image> processImages({ | ||
| required img.Image originalImage, | ||
| required Epd epd, | ||
| }) { | ||
| final List<img.Image> processedImgs = []; | ||
|
|
||
| img.Image transformed = img.copyResize( | ||
| originalImage, | ||
| width: epd.width, | ||
| height: epd.height, | ||
| ); | ||
|
|
||
| for (final method in epd.processingMethods) { | ||
| processedImgs.add(method(transformed)); | ||
| } | ||
|
|
||
| return processedImgs; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,35 +2,57 @@ import 'dart:typed_data'; | |
|
|
||
| import 'package:flutter/material.dart'; | ||
| import 'package:magic_epaper_app/pro_image_editor/features/movable_background_image.dart'; | ||
| import 'package:magic_epaper_app/view/widget/flip_controls.dart'; | ||
| import 'package:magic_epaper_app/util/image_editor_utils.dart'; | ||
| import 'package:magic_epaper_app/view/widget/image_list.dart'; | ||
| import 'package:provider/provider.dart'; | ||
| import 'package:image/image.dart' as img; | ||
|
|
||
| import 'package:magic_epaper_app/provider/image_loader.dart'; | ||
| import 'package:magic_epaper_app/util/epd/epd.dart'; | ||
| import 'package:magic_epaper_app/constants.dart'; | ||
| import 'package:magic_epaper_app/constants/color_constants.dart'; | ||
|
|
||
| class ImageEditor extends StatelessWidget { | ||
| class ImageEditor extends StatefulWidget { | ||
| final Epd epd; | ||
| const ImageEditor({super.key, required this.epd}); | ||
|
|
||
| @override | ||
| State<ImageEditor> createState() => _ImageEditorState(); | ||
| } | ||
|
|
||
| class _ImageEditorState extends State<ImageEditor> { | ||
| bool flipHorizontal = false; | ||
| bool flipVertical = false; | ||
|
|
||
| void toggleFlipHorizontal() { | ||
| setState(() { | ||
| flipHorizontal = !flipHorizontal; | ||
| }); | ||
| } | ||
|
|
||
| void toggleFlipVertical() { | ||
| setState(() { | ||
| flipVertical = !flipVertical; | ||
| }); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| var imgLoader = context.watch<ImageLoader>(); | ||
| final List<img.Image> processedImgs = List.empty(growable: true); | ||
| final orgImg = imgLoader.image; | ||
|
|
||
| if (orgImg != null) { | ||
| final image = img.copyResize(imgLoader.image!, | ||
| width: epd.width, height: epd.height); | ||
| for (final method in epd.processingMethods) { | ||
| processedImgs.add(method(image)); | ||
| } | ||
| } | ||
| final List<img.Image> processedImgs = orgImg != null | ||
| ? processImages( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (performance): Reprocessing on every build might hurt performance Consider memoizing |
||
| originalImage: orgImg, | ||
| epd: widget.epd, | ||
| ) | ||
| : []; | ||
|
|
||
| final imgList = ImageList( | ||
| imgList: processedImgs, | ||
| epd: epd, | ||
| epd: widget.epd, | ||
| flipHorizontal: flipHorizontal, | ||
| flipVertical: flipVertical, | ||
| ); | ||
|
|
||
| return Scaffold( | ||
|
|
@@ -69,7 +91,8 @@ class ImageEditor extends StatelessWidget { | |
| ), | ||
| ), | ||
| onPressed: () { | ||
| imgLoader.pickImage(width: epd.width, height: epd.height); | ||
| imgLoader.pickImage( | ||
| width: widget.epd.width, height: widget.epd.height); | ||
| }, | ||
| child: const Text( | ||
| "Import Image", | ||
|
|
@@ -86,14 +109,20 @@ class ImageEditor extends StatelessWidget { | |
| ); | ||
| imgLoader.updateImage( | ||
| bytes: canvasBytes!, | ||
| width: epd.width, | ||
| height: epd.height, | ||
| width: widget.epd.width, | ||
| height: widget.epd.height, | ||
| ); | ||
| }, | ||
| child: const Text("Open Editor"), | ||
| ), | ||
| ], | ||
| ), | ||
| floatingActionButton: orgImg != null | ||
| ? FlipControls( | ||
| onFlipHorizontal: toggleFlipHorizontal, | ||
| onFlipVertical: toggleFlipVertical, | ||
| ) | ||
| : null, | ||
| body: SafeArea( | ||
| child: Padding( | ||
| padding: const EdgeInsets.symmetric(horizontal: 8.0), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import 'package:flutter/material.dart'; | ||
| import 'package:magic_epaper_app/constants/asset_paths.dart'; | ||
|
|
||
| class FlipControls extends StatelessWidget { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Add visual state feedback for flip controls Pass the flip state to Suggested implementation: You will also need to update the widget tree inside Additionally, update all usages of |
||
| final VoidCallback onFlipHorizontal; | ||
| final VoidCallback onFlipVertical; | ||
|
|
||
| const FlipControls({ | ||
| super.key, | ||
| required this.onFlipHorizontal, | ||
| required this.onFlipVertical, | ||
| }); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return Padding( | ||
| padding: const EdgeInsets.only(bottom: 80.0), | ||
| child: Column( | ||
| mainAxisAlignment: MainAxisAlignment.end, | ||
| children: [ | ||
| FloatingActionButton( | ||
| backgroundColor: Colors.white, | ||
| heroTag: 'flipH', | ||
| onPressed: onFlipHorizontal, | ||
| tooltip: 'Flip Horizontally', | ||
| child: Image.asset( | ||
| ImageAssets.flipHorizontal, | ||
| height: 24, | ||
| width: 24, | ||
| ), | ||
| ), | ||
| const SizedBox(height: 10), | ||
| FloatingActionButton( | ||
| backgroundColor: Colors.white, | ||
| heroTag: 'flipV', | ||
| onPressed: onFlipVertical, | ||
| tooltip: 'Flip Vertically', | ||
| child: Transform.rotate( | ||
| angle: -1.5708, | ||
| child: Image.asset( | ||
| ImageAssets.flipHorizontal, | ||
| height: 24, | ||
| width: 24, | ||
| ), | ||
| ), | ||
| ), | ||
| ], | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
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): Clone transformed image per method to avoid side effects
Passing the same transformed image to all methods may lead to unintended side effects if any method mutates its input. Pass a copy of
transformedto each method instead.