@@ -20,6 +20,7 @@ import 'package:cloud_firestore/cloud_firestore.dart';
2020import 'package:firebase_storage/firebase_storage.dart' ;
2121import 'package:flutter/material.dart' ;
2222import 'package:path_provider/path_provider.dart' ;
23+ import 'package:multi_media_picker/multi_media_picker.dart' ;
2324
2425import 'countdown_timer.dart' ;
2526import 'models.dart' ;
@@ -38,14 +39,21 @@ class Camera extends StatefulWidget {
3839 final String label;
3940 final String labelKey;
4041 final UserModel userModel;
41-
42- Camera (this .dataset, this .label, this .labelKey, this .userModel);
42+ final bool isUploading;
43+ List <File > resultList;
44+ Camera (this .dataset, this .label, this .labelKey, this .userModel,
45+ this .isUploading);
4346
4447 Future init () async {
45- try {
46- cameras = await availableCameras ();
47- } on CameraException catch (e) {
48- logError (e.code, e.description);
48+ if (! isUploading) {
49+ try {
50+ cameras = await availableCameras ();
51+ } on CameraException catch (e) {
52+ logError (e.code, e.description);
53+ }
54+ } else {
55+ resultList =
56+ await MultiMediaPicker .pickImages (source: ImageSource .gallery);
4957 }
5058 }
5159
@@ -67,12 +75,14 @@ class _CameraState extends State<Camera> {
6775 @override
6876 void initState () {
6977 super .initState ();
70- WidgetsBinding .instance.addPostFrameCallback ((_) {
71- for (CameraDescription cameraDescription in cameras) {
72- if (cameraDescription.lensDirection == CameraLensDirection .back)
73- onNewCameraSelected (cameraDescription);
74- }
75- });
78+ if (! widget.isUploading) {
79+ WidgetsBinding .instance.addPostFrameCallback ((_) {
80+ for (CameraDescription cameraDescription in cameras) {
81+ if (cameraDescription.lensDirection == CameraLensDirection .back)
82+ onNewCameraSelected (cameraDescription);
83+ }
84+ });
85+ }
7686 }
7787
7888 @override
@@ -83,54 +93,74 @@ class _CameraState extends State<Camera> {
8393
8494 @override
8595 Widget build (BuildContext context) {
96+ if (widget.isUploading && widget.resultList != null ) {
97+ widget.resultList
98+ .forEach ((eachImage) => {uploadImageToStorage (eachImage.path)});
99+ }
86100 return Scaffold (
87101 key: _scaffoldKey,
88102 appBar: AppBar (
89103 backgroundColor: Theme .of (context).accentColor,
90104 title: Text ('Capture sample for ${widget .label }' ),
91105 ),
92- body: Container (
93- decoration: new BoxDecoration (color: Colors .black),
94- child: Column (
95- children: < Widget > [
96- Expanded (
97- child: Container (
98- child: Padding (
99- padding: const EdgeInsets .all (1.0 ),
100- child: Center (
101- child: _cameraPreviewWidget (),
102- ),
103- ),
104- decoration: BoxDecoration (
105- color: Colors .black,
106- border: Border .all (
107- color:
108- controller != null && controller.value.isRecordingVideo
109- ? Colors .redAccent
110- : Colors .black45,
111- width: 2.0 ,
112- ),
113- ),
106+ body: widget.isUploading
107+ ? Center (
108+ child: Column (
109+ mainAxisAlignment: MainAxisAlignment .center,
110+ crossAxisAlignment: CrossAxisAlignment .center,
111+ children: < Widget > [
112+ Text ('Uploading Images in the background' ),
113+ MaterialButton (
114+ onPressed: () {
115+ Navigator .pop (context);
116+ },
117+ child: Text ('OK' ),
118+ )
119+ ],
114120 ),
115- ),
116- new CameraControlWidget (
117- controller: controller,
118- onRecordingStart: onVideoRecordButtonPressed,
119- onRecordingStop: onStopButtonPressed,
120- onPictureTaken: onTakePictureButtonPressed,
121- ),
122- Padding (
123- padding: const EdgeInsets .all (5.0 ),
124- child: Row (
125- mainAxisAlignment: MainAxisAlignment .start,
121+ )
122+ : Container (
123+ decoration: new BoxDecoration (color: Colors .black),
124+ child: Column (
126125 children: < Widget > [
127- _thumbnailWidget (),
126+ Expanded (
127+ child: Container (
128+ child: Padding (
129+ padding: const EdgeInsets .all (1.0 ),
130+ child: Center (
131+ child: _cameraPreviewWidget (),
132+ ),
133+ ),
134+ decoration: BoxDecoration (
135+ color: Colors .black,
136+ border: Border .all (
137+ color: controller != null &&
138+ controller.value.isRecordingVideo
139+ ? Colors .redAccent
140+ : Colors .black45,
141+ width: 2.0 ,
142+ ),
143+ ),
144+ ),
145+ ),
146+ new CameraControlWidget (
147+ controller: controller,
148+ onRecordingStart: onVideoRecordButtonPressed,
149+ onRecordingStop: onStopButtonPressed,
150+ onPictureTaken: onTakePictureButtonPressed,
151+ ),
152+ Padding (
153+ padding: const EdgeInsets .all (5.0 ),
154+ child: Row (
155+ mainAxisAlignment: MainAxisAlignment .start,
156+ children: < Widget > [
157+ _thumbnailWidget (),
158+ ],
159+ ),
160+ ),
128161 ],
129162 ),
130163 ),
131- ],
132- ),
133- ),
134164 );
135165 }
136166
@@ -200,60 +230,7 @@ class _CameraState extends State<Camera> {
200230
201231 void onTakePictureButtonPressed () async {
202232 final filePath = await takePicture ();
203- final automlStorage = InheritedStorage .of (context).autoMlStorage;
204-
205- if (mounted) {
206- setState (() {
207- imagePath = filePath;
208- });
209-
210- final filename =
211- new DateTime .now ().millisecondsSinceEpoch.toString () + '.jpg' ;
212-
213- // upload to storage and firestore
214- final StorageReference ref = automlStorage
215- .ref ()
216- .child ('datasets' )
217- .child (widget.dataset.name)
218- .child (widget.label)
219- .child (filename);
220-
221- final File file = File (filePath).absolute;
222- // upload the file
223- StorageUploadTask uploadTask = ref.putFile (
224- file,
225- StorageMetadata (
226- contentType: 'image/jpeg' ,
227- customMetadata: < String , String > {'activity' : 'imgUpload' },
228- ),
229- );
230-
231- final snapshot = await uploadTask.onComplete;
232- final downloadUrl = await snapshot.ref.getDownloadURL ();
233-
234- Firestore .instance.collection ('images' ).add ({
235- 'parent_key' : widget.labelKey,
236- 'dataset_parent_key' : widget.dataset.id,
237- 'type' : toString (SampleType
238- .TRAIN ), // newly created images are categorized as training.
239- 'filename' : filename,
240- 'uploadPath' :
241- 'datasets/${widget .dataset .name }/${widget .label }/$filename ' ,
242- 'gcsURI' : downloadUrl,
243- 'uploader' : widget.userModel.user.email,
244- });
245-
246- final labelRef =
247- Firestore .instance.collection ('labels' ).document (widget.labelKey);
248-
249- // increment count for the label
250- await Firestore .instance.runTransaction ((Transaction tx) async {
251- DocumentSnapshot snapshot = await tx.get (labelRef);
252- await tx.update (labelRef, < String , dynamic > {
253- 'total_images' : snapshot.data['total_images' ] + 1
254- });
255- });
256- }
233+ uploadImageToStorage (filePath);
257234 }
258235
259236 void onVideoRecordButtonPressed () {
@@ -375,6 +352,63 @@ class _CameraState extends State<Camera> {
375352 logError (e.code, e.description);
376353 showInSnackBar ('Error: ${e .code }\n ${e .description }' );
377354 }
355+
356+ void uploadImageToStorage (String filePath) async {
357+ final automlStorage = InheritedStorage .of (context).autoMlStorage;
358+
359+ if (mounted) {
360+ setState (() {
361+ imagePath = filePath;
362+ });
363+
364+ final filename =
365+ new DateTime .now ().millisecondsSinceEpoch.toString () + '.jpg' ;
366+
367+ // upload to storage and firestore
368+ final StorageReference ref = automlStorage
369+ .ref ()
370+ .child ('datasets' )
371+ .child (widget.dataset.name)
372+ .child (widget.label)
373+ .child (filename);
374+
375+ final File file = File (filePath).absolute;
376+ // upload the file
377+ StorageUploadTask uploadTask = ref.putFile (
378+ file,
379+ StorageMetadata (
380+ contentType: 'image/jpeg' ,
381+ customMetadata: < String , String > {'activity' : 'imgUpload' },
382+ ),
383+ );
384+
385+ final snapshot = await uploadTask.onComplete;
386+ final downloadUrl = await snapshot.ref.getDownloadURL ();
387+
388+ Firestore .instance.collection ('images' ).add ({
389+ 'parent_key' : widget.labelKey,
390+ 'dataset_parent_key' : widget.dataset.id,
391+ 'type' : toString (SampleType
392+ .TRAIN ), // newly created images are categorized as training.
393+ 'filename' : filename,
394+ 'uploadPath' :
395+ 'datasets/${widget .dataset .name }/${widget .label }/$filename ' ,
396+ 'gcsURI' : downloadUrl,
397+ 'uploader' : widget.userModel.user.email,
398+ });
399+
400+ final labelRef =
401+ Firestore .instance.collection ('labels' ).document (widget.labelKey);
402+
403+ // increment count for the label
404+ await Firestore .instance.runTransaction ((Transaction tx) async {
405+ DocumentSnapshot snapshot = await tx.get (labelRef);
406+ await tx.update (labelRef, < String , dynamic > {
407+ 'total_images' : snapshot.data['total_images' ] + 1
408+ });
409+ });
410+ }
411+ }
378412}
379413
380414/// Widget to control start / stop of camera
0 commit comments