library camera_with_files; import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'package:camera/camera.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:image_picker/image_picker.dart'; import "package:intl/intl.dart"; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; class CustomCameraWidget extends StatefulWidget { final int? compressionQuality; const CustomCameraWidget({Key? key, this.compressionQuality = 100}) : super(key: key); @override CustomCameraWidgetState createState() => CustomCameraWidgetState(); } class CustomCameraWidgetState extends State { CameraController? controller; late List cameras; bool flashOn = false; bool showPerformance = false; @override void initState() { super.initState(); cameraLoad(); } cameraLoad() async { cameras = await availableCameras(); controller = CameraController(cameras[0], ResolutionPreset.max, imageFormatGroup: Platform.isIOS ? ImageFormatGroup.bgra8888 : null); controller!.initialize().then((_) { if (!mounted) { return; } _promptPermissionSetting().then((_) { if (_) {} setState(() {}); }); setState(() {}); }); } Future _promptPermissionSetting() async { if (kIsWeb) { return true; } else if (Platform.isIOS) { PermissionStatus status = await Permission.storage.request(); PermissionStatus status2 = await Permission.photos.request(); PermissionStatus status3 = await Permission.mediaLibrary.request(); return status.isGranted && status2.isGranted && status3.isGranted; } else if (Platform.isAndroid) { PermissionStatus status = await Permission.storage.request(); return status.isGranted; } return false; } @override void dispose() { controller!.dispose(); super.dispose(); } @override Widget build(BuildContext context) { if (controller == null) { return Container(); } var camera = controller!.value; final size = MediaQuery.of(context).size; var scale = 0.0; try { scale = size.aspectRatio * camera.aspectRatio; } catch (e) { debugPrint(e.toString()); } if (scale < 1) scale = 1 / scale; if (!controller!.value.isInitialized) { return Container(); } return WillPopScope( onWillPop: () { return Future.value(true); }, child: Scaffold( body: Stack( children: [ GestureDetector( onVerticalDragStart: (e) {}, child: Transform.scale( scale: scale, child: Center( child: CameraPreview(controller!), ), ), ), Align( alignment: Alignment.bottomCenter, child: Container( width: MediaQuery.of(context).size.width, height: 215, color: Colors.transparent, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _galleryButton(), _cameraButton(), SizedBox(width: 25,) ], ), ), ), SafeArea( child: Align( alignment: Alignment.topCenter, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( onPressed: () { setState(() { flashOn = !flashOn; if (flashOn) { controller!.setFlashMode(FlashMode.torch); } else { controller!.setFlashMode(FlashMode.off); } }); }, icon: const Icon(Icons.flash_off, size: 30, color: Colors.white)), IconButton( onPressed: () { compress(null); }, icon: const Icon( Icons.close_rounded, color: Colors.white, )) ], )), ), ], ), ), ); } Widget _galleryButton(){ return IconButton( onPressed: () async { final ImagePicker picker0 = ImagePicker(); final XFile? image = await picker0.pickImage( source: ImageSource.gallery); if (image == null) { return; } File file = File(image.path); compress(file); }, icon: const Icon(Icons.photo_library, size: 30, color: Colors.white), ); } Widget _cameraButton(){ return GestureDetector( onTap: () async { XFile file2 = await controller!.takePicture(); File file = File(file2.path); compress(file); }, child: Container( width: 75, height: 75, decoration: BoxDecoration( // color: Colors.white, borderRadius: const BorderRadius.all( Radius.circular( 50) ), border: Border.all( color: Colors.white, width: 3)), ), ); } void onSettingCallback() { setState(() { showPerformance = !showPerformance; }); } void compress(File? file) async { if (file == null) { Navigator.of(context).pop(null); } File? files2; Uint8List? blobBytes = await compressFile(file!); var dir = await getTemporaryDirectory(); String trimmed = dir.absolute.path; String dateTimeString = DateTime.now().millisecondsSinceEpoch.toString(); String pathString = "$trimmed/$dateTimeString.jpg"; File fileNew = File(pathString); fileNew.writeAsBytesSync(List.from(blobBytes!)); files2 = fileNew; if (context.mounted) { Navigator.of(context).pop(files2); } } String dateTimeToString(DateTime dateTime, String pattern) { final format = DateFormat(pattern); return format.format(dateTime); } Future compressFile(File file) async { var decodedImage = await decodeImageFromList(file.readAsBytesSync()); print("Image compress Before: " + getFileSizeString(bytes: file.lengthSync())); var result = await FlutterImageCompress.compressWithFile(file.absolute.path, minHeight: decodedImage.height, minWidth: decodedImage.width, quality: widget.compressionQuality!); print("Image compress After: " + getFileSizeString(bytes: result!.lengthInBytes)); return result; } String getFileSizeString({required int bytes, int decimals = 0}) { const suffixes = ["b", "kb", "mb", "gb", "tb"]; var i = (log(bytes) / log(1024)).floor(); return ((bytes / pow(1024, i)).toStringAsFixed(decimals)) + suffixes[i]; } }