Closed Teutonic-Knight-0 closed 2 years ago
Package just returns a blacked out image.
Source code:
import 'dart:typed_data'; import 'package:crop/crop.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:flutter/material.dart'; import 'package:camera/camera.dart'; import 'package:extended_image/extended_image.dart'; import 'dart:io'; import 'dart:math'; import 'package:path_provider/path_provider.dart'; import 'dart:ui' as ui; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Camera Cropper', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { CameraController? _controller; late List<CameraDescription> _cameras; File? _capturedImage; final TransformationController _transformationController = TransformationController(); final CropController _cropController = CropController(); @override void initState() { super.initState(); _getCameras(); } _getCameras() async { _cameras = await availableCameras(); _controller = CameraController(_cameras[0], ResolutionPreset.max); await _controller?.initialize(); if (mounted) { setState(() {}); } } String _randomNonceString([int length = 32]) { final random = Random(); final charCodes = List<int>.generate(length, (_) { late int codeUnit; switch (random.nextInt(3)) { case 0: codeUnit = random.nextInt(10) + 48; break; case 1: codeUnit = random.nextInt(26) + 65; break; case 2: codeUnit = random.nextInt(26) + 97; break; } return codeUnit; }); return String.fromCharCodes(charCodes); } @override void dispose() { super.dispose(); _controller?.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: _controller == null ? const LoadingIndicator() : Stack( alignment: Alignment.bottomCenter, children: [ Column( children: [ Expanded( child: InteractiveViewer( constrained: false, transformationController: _transformationController, child: SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: _capturedImage != null ? ExtendedImage.file(_capturedImage!) : CameraPreview(_controller!), ), ), ), ], ), if (_capturedImage == null) ResizableWidget(cropController: _cropController), Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( child: const Icon( Icons.arrow_back_ios, color: Colors.white, size: 40, ), onPressed: () { setState(() { _capturedImage = null; }); }, ), GestureDetector( onTap: () async { // XFile image = await _controller!.takePicture(); // _capturedImage = File(image.path); final double pixelRatio = MediaQuery.of(context).devicePixelRatio; final ui.Image cropped = await _cropController.crop(pixelRatio: pixelRatio); final ByteData? byteData = await cropped.toByteData(format: ui.ImageByteFormat.png); final Uint8List buffer = byteData!.buffer.asUint8List(); final Directory dir = await getTemporaryDirectory(); final String path = '${dir.path}/${_randomNonceString()}.png'; if (!(await File(path).exists())) { File imageFile = await File(path).create(); _capturedImage = await imageFile.writeAsBytes(buffer); setState(() {}); } else { _capturedImage = await File(path).writeAsBytes(buffer); setState(() {}); } }, child: const CircleAvatar( radius: 30, backgroundColor: Colors.white, ), ), TextButton( child: Icon( _controller!.value.flashMode == FlashMode.auto ? Icons.flash_auto : _controller!.value.flashMode == FlashMode.off ? Icons.flash_off : Icons.flash_on, color: Colors.white, size: 40, ), onPressed: () async { await _controller!.setFlashMode(_controller!.value.flashMode == FlashMode.auto ? FlashMode.off : _controller!.value.flashMode == FlashMode.off ? FlashMode.always : FlashMode.auto); setState(() {}); }, ), ], ), ) ], ), ); } } class ResizableWidget extends StatefulWidget { const ResizableWidget({Key? key, required this.cropController}) : super(key: key); final CropController cropController; @override State<ResizableWidget> createState() => _ResizableWidgetState(); } const ballDiameter = 30.0; class _ResizableWidgetState extends State<ResizableWidget> { double height = 200; double width = 250; double top = 250; double left = 55; void onDrag(double dx, double dy) { var newHeight = height + dy; var newWidth = width + dx; setState(() { height = newHeight > 0 ? newHeight : 0; width = newWidth > 0 ? newWidth : 0; }); } @override Widget build(BuildContext context) { return Stack( children: <Widget>[ Positioned( top: top, left: left, child: DottedBorder( borderType: BorderType.RRect, radius: const Radius.circular(20), dashPattern: const [8, 8], color: Colors.white, strokeWidth: 2, child: SizedBox( height: height, width: width, child: Crop( controller: widget.cropController, shape: BoxShape.rectangle, backgroundColor: Colors.transparent, child: Container( decoration: const BoxDecoration( color: Colors.transparent, ), height: height, width: width, ), ), ), ), ), // top left Positioned( top: top - ballDiameter / 2, left: left - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var mid = (dx + dy) / 2; var newHeight = height - 2 * mid; var newWidth = width - 2 * mid; setState(() { height = newHeight > 0 ? newHeight : 0; width = newWidth > 0 ? newWidth : 0; top = top + mid; left = left + mid; }); }, ), ), // top middle Positioned( top: top - ballDiameter / 2, left: left + width / 2 - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var newHeight = height - dy; setState(() { height = newHeight > 0 ? newHeight : 0; top = top + dy; }); }, ), ), // top right Positioned( top: top - ballDiameter / 2, left: left + width - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var mid = (dx + (dy * -1)) / 2; var newHeight = height + 2 * mid; var newWidth = width + 2 * mid; setState(() { height = newHeight > 0 ? newHeight : 0; width = newWidth > 0 ? newWidth : 0; top = top - mid; left = left - mid; }); }, ), ), // center right Positioned( top: top + height / 2 - ballDiameter / 2, left: left + width - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var newWidth = width + dx; setState(() { width = newWidth > 0 ? newWidth : 0; }); }, ), ), // bottom right Positioned( top: top + height - ballDiameter / 2, left: left + width - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var mid = (dx + dy) / 2; var newHeight = height + 2 * mid; var newWidth = width + 2 * mid; setState(() { height = newHeight > 0 ? newHeight : 0; width = newWidth > 0 ? newWidth : 0; top = top - mid; left = left - mid; }); }, ), ), // bottom center Positioned( top: top + height - ballDiameter / 2, left: left + width / 2 - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var newHeight = height + dy; setState(() { height = newHeight > 0 ? newHeight : 0; }); }, ), ), // bottom left Positioned( top: top + height - ballDiameter / 2, left: left - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var mid = ((dx * -1) + dy) / 2; var newHeight = height + 2 * mid; var newWidth = width + 2 * mid; setState(() { height = newHeight > 0 ? newHeight : 0; width = newWidth > 0 ? newWidth : 0; top = top - mid; left = left - mid; }); }, ), ), //left center Positioned( top: top + height / 2 - ballDiameter / 2, left: left - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { var newWidth = width - dx; setState(() { width = newWidth > 0 ? newWidth : 0; left = left + dx; }); }, ), ), // center center Positioned( top: top + height / 2 - ballDiameter / 2, left: left + width / 2 - ballDiameter / 2, child: ManipulatingBall( onDrag: (dx, dy) { setState(() { top = top + dy; left = left + dx; }); }, ), ), ], ); } } class ManipulatingBall extends StatefulWidget { const ManipulatingBall({Key? key, required this.onDrag}) : super(key: key); final Function onDrag; @override State<ManipulatingBall> createState() => _ManipulatingBallState(); } class _ManipulatingBallState extends State<ManipulatingBall> { double _initX = 0; double _initY = 0; _handleDrag(details) { setState(() { _initX = details.globalPosition.dx; _initY = details.globalPosition.dy; }); } _handleUpdate(details) { var dx = details.globalPosition.dx - _initX; var dy = details.globalPosition.dy - _initY; _initX = details.globalPosition.dx; _initY = details.globalPosition.dy; widget.onDrag(dx, dy); } @override Widget build(BuildContext context) { return GestureDetector( onPanStart: _handleDrag, onPanUpdate: _handleUpdate, child: Container( width: ballDiameter, height: ballDiameter, decoration: BoxDecoration( color: Colors.pink.withOpacity(0.5), shape: BoxShape.circle, ), ), ); } } class LoadingIndicator extends StatelessWidget { const LoadingIndicator({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Center( child: CircularProgressIndicator(color: Colors.pink), ); } }
Pubspec:
name: camera_cropper description: A new Flutter project. publish_to: 'none' version: 1.0.0+1 environment: sdk: '>=2.18.0-130.0.dev <3.0.0' dependencies: flutter: sdk: flutter camera: ^0.9.6 image: ^3.2.0 extended_image: ^6.2.1 dotted_border: ^2.0.0+2 crop: ^0.5.2 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.1 flutter: uses-material-design: true
Flutter doctor:
Running flutter doctor... Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, 3.1.0-0.0.pre.821, on macOS 12.3.1 21E258 darwin-arm, locale en-ZA) [✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) [✓] Xcode - develop for iOS and macOS (Xcode 13.4) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.1) [✓] Android Studio (version 2021.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1) [✓] Connected device (3 available) [✓] HTTP Host Availability
• No issues found!
Are you using Flutter 3.0? There is an issue with it. Check:
https://github.com/flutter/flutter/issues/103803
This is fixed in the latest Flutter version on master channel. I am closing this issue but please open a new issue anytime.
Package just returns a blacked out image.
Source code:
Pubspec:
Flutter doctor:
Running flutter doctor... Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, 3.1.0-0.0.pre.821, on macOS 12.3.1 21E258 darwin-arm, locale en-ZA) [✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) [✓] Xcode - develop for iOS and macOS (Xcode 13.4) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.1) [✓] Android Studio (version 2021.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1.1) [✓] IntelliJ IDEA Ultimate Edition (version 2022.1) [✓] Connected device (3 available) [✓] HTTP Host Availability
• No issues found!