@@ -44,6 +44,8 @@ class _ImageEditorState extends State<ImageEditor> {
44
44
List <img.Image > _rawImages = [];
45
45
List <Uint8List > _processedPngs = [];
46
46
ImageSaveHandler ? _imageSaveHandler;
47
+ bool _isProcessingImages = false ;
48
+ bool _isInitializing = true ;
47
49
48
50
@override
49
51
void initState () {
@@ -52,33 +54,44 @@ class _ImageEditorState extends State<ImageEditor> {
52
54
_selectedWaveform = null ;
53
55
_selectedWaveformName = null ;
54
56
55
- Future .microtask (() {
57
+ WidgetsBinding .instance.addPostFrameCallback ((_) {
58
+ setState (() {
59
+ _isInitializing = false ;
60
+ });
56
61
loadInitialImage ();
57
62
});
58
63
}
59
64
60
65
Future <void > loadInitialImage () async {
61
- final imgLoader = context.read <ImageLoader >();
62
- if (imgLoader.image == null ) {
63
- await imgLoader.loadFinalizedImage (
64
- width: widget.device.width,
65
- height: widget.device.height,
66
- );
67
- }
68
- if (imgLoader.image == null ) {
69
- loadDefaultImage (imgLoader);
66
+ try {
67
+ final imgLoader = context.read <ImageLoader >();
68
+ if (imgLoader.image == null ) {
69
+ await imgLoader.loadFinalizedImage (
70
+ width: widget.device.width,
71
+ height: widget.device.height,
72
+ );
73
+ }
74
+ if (imgLoader.image == null ) {
75
+ await loadDefaultImage (imgLoader);
76
+ }
77
+ } catch (e) {
78
+ debugPrint ('Error loading initial image: $e ' );
70
79
}
71
80
}
72
81
73
82
Future <void > loadDefaultImage (ImageLoader imgLoader) async {
74
- const assetPath = 'assets/images/FOSSASIA.png' ;
75
- final byteData = await rootBundle.load (assetPath);
76
- final pngBytes = byteData.buffer.asUint8List ();
77
- await imgLoader.updateImage (
78
- bytes: pngBytes,
79
- width: widget.device.width,
80
- height: widget.device.height,
81
- );
83
+ try {
84
+ const assetPath = 'assets/images/FOSSASIA.png' ;
85
+ final byteData = await rootBundle.load (assetPath);
86
+ final pngBytes = byteData.buffer.asUint8List ();
87
+ await imgLoader.updateImage (
88
+ bytes: pngBytes,
89
+ width: widget.device.width,
90
+ height: widget.device.height,
91
+ );
92
+ } catch (e) {
93
+ debugPrint ('Error loading default image: $e ' );
94
+ }
82
95
}
83
96
84
97
@override
@@ -132,6 +145,7 @@ class _ImageEditorState extends State<ImageEditor> {
132
145
_processedSourceImage = null ;
133
146
_rawImages = [];
134
147
_processedPngs = [];
148
+ _isProcessingImages = false ;
135
149
});
136
150
}
137
151
return ;
@@ -141,17 +155,43 @@ class _ImageEditorState extends State<ImageEditor> {
141
155
return ;
142
156
}
143
157
144
- _rawImages = processImages (originalImage: sourceImage, epd: widget.device);
145
-
146
- _processedPngs =
147
- _rawImages.map ((rawImage) => img.encodePng (rawImage)).toList ();
158
+ _processImagesAsync (sourceImage);
159
+ }
148
160
161
+ Future <void > _processImagesAsync (img.Image sourceImage) async {
162
+ if (_isProcessingImages) return ;
149
163
setState (() {
150
- _processedSourceImage = sourceImage;
151
- _selectedFilterIndex = 0 ;
152
- flipHorizontal = false ;
153
- flipVertical = false ;
164
+ _isProcessingImages = true ;
154
165
});
166
+ try {
167
+ await Future .delayed (const Duration (milliseconds: 50 ));
168
+ final rawImages =
169
+ processImages (originalImage: sourceImage, epd: widget.device);
170
+ final processedPngs = < Uint8List > [];
171
+ for (int i = 0 ; i < rawImages.length; i++ ) {
172
+ processedPngs.add (img.encodePng (rawImages[i]));
173
+ if (i % 2 == 0 ) {
174
+ await Future .delayed (const Duration (milliseconds: 1 ));
175
+ }
176
+ }
177
+ if (mounted) {
178
+ setState (() {
179
+ _rawImages = rawImages;
180
+ _processedPngs = processedPngs;
181
+ _processedSourceImage = sourceImage;
182
+ _selectedFilterIndex = 0 ;
183
+ flipHorizontal = false ;
184
+ flipVertical = false ;
185
+ _isProcessingImages = false ;
186
+ });
187
+ }
188
+ } catch (e) {
189
+ if (mounted) {
190
+ setState (() {
191
+ _isProcessingImages = false ;
192
+ });
193
+ }
194
+ }
155
195
}
156
196
157
197
Future <void > _exportXbmFiles () async {
@@ -218,7 +258,11 @@ class _ImageEditorState extends State<ImageEditor> {
218
258
@override
219
259
Widget build (BuildContext context) {
220
260
var imgLoader = context.watch <ImageLoader >();
221
- _updateProcessedImages (imgLoader.image);
261
+ if (! _isInitializing && imgLoader.image != null && ! _isProcessingImages) {
262
+ WidgetsBinding .instance.addPostFrameCallback ((_) {
263
+ _updateProcessedImages (imgLoader.image);
264
+ });
265
+ }
222
266
223
267
return Scaffold (
224
268
backgroundColor: Colors .white,
@@ -344,11 +388,22 @@ class _ImageEditorState extends State<ImageEditor> {
344
388
body: SafeArea (
345
389
top: false ,
346
390
bottom: true ,
347
- child: imgLoader.isLoading
391
+ child: _isInitializing || imgLoader.isLoading || _isProcessingImages
348
392
? Center (
349
- child: Text (
350
- appLocalizations.loading,
351
- style: const TextStyle (color: colorBlack, fontSize: 14 ),
393
+ child: Column (
394
+ mainAxisAlignment: MainAxisAlignment .center,
395
+ children: [
396
+ const CircularProgressIndicator (
397
+ valueColor: AlwaysStoppedAnimation <Color >(colorAccent),
398
+ ),
399
+ const SizedBox (height: 16 ),
400
+ Text (
401
+ _isProcessingImages
402
+ ? appLocalizations.processingImages
403
+ : appLocalizations.loading,
404
+ style: const TextStyle (color: colorBlack, fontSize: 14 ),
405
+ ),
406
+ ],
352
407
),
353
408
)
354
409
: Padding (
0 commit comments