import 'dart:convert'; import 'dart:io'; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart'; import 'package:image/image.dart' as img; import 'package:path_provider/path_provider.dart' as path_provider; import '../../constant/api_key.dart'; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../constant/info.dart'; import '../../main.dart'; import '../../print.dart'; import 'encrypt_decrypt.dart'; class ImageController extends GetxController { File? myImage; bool isloading = false; CroppedFile? croppedFile; final picker = ImagePicker(); var image; Future detectAndCropDocument(File imageFile) async { img.Image? image = img.decodeImage(await imageFile.readAsBytes()); if (image == null) throw Exception('Unable to decode image'); int left = image.width, top = image.height, right = 0, bottom = 0; // Threshold for considering a pixel as part of the document (adjust as needed) const int threshold = 240; for (int y = 0; y < image.height; y++) { for (int x = 0; x < image.width; x++) { final pixel = image.getPixel(x, y); final luminance = img.getLuminance(pixel); if (luminance < threshold) { left = x < left ? x : left; top = y < top ? y : top; right = x > right ? x : right; bottom = y > bottom ? y : bottom; } } } // Add a small padding left = (left - 5).clamp(0, image.width); top = (top - 5).clamp(0, image.height); right = (right + 5).clamp(0, image.width); bottom = (bottom + 5).clamp(0, image.height); return img.copyCrop(image, x: left, y: top, width: right - left, height: bottom - top); } Future rotateImageIfNeeded(File imageFile) async { img.Image croppedDoc = await detectAndCropDocument(imageFile); // Check if the document is in portrait orientation bool isPortrait = croppedDoc.height > croppedDoc.width; img.Image processedImage; if (isPortrait) { // Rotate the image by 90 degrees clockwise processedImage = img.copyRotate(croppedDoc, angle: 90); } else { processedImage = croppedDoc; } // Get temporary directory final tempDir = await path_provider.getTemporaryDirectory(); final tempPath = tempDir.path; // Create the processed image file File processedFile = File('$tempPath/processed_image.jpg'); await processedFile.writeAsBytes(img.encodeJpg(processedImage)); return processedFile; } Future rotateImage(File imageFile) async { // Read the image file img.Image? image = img.decodeImage(await imageFile.readAsBytes()); if (image == null) return imageFile; // Rotate the image by 90 degrees clockwise img.Image rotatedImage = img.copyRotate(image, angle: 90); // Get temporary directory final tempDir = await path_provider.getTemporaryDirectory(); final tempPath = tempDir.path; // Create the rotated image file File rotatedFile = File('$tempPath/rotated_image.jpg'); await rotatedFile.writeAsBytes(img.encodeJpg(rotatedImage)); return rotatedFile; } choosImage(String link, String imageType, String id) async { try { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.rear, ); if (pickedImage == null) return; image = File(pickedImage.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false, ), IOSUiSettings( title: 'Cropper'.tr, ), ], ); if (croppedFile == null) return; myImage = File(croppedFile!.path); isloading = true; update(); // Rotate the compressed image File processedImage = await rotateImageIfNeeded(File(croppedFile!.path)); File compressedImage = await compressImage(processedImage); print('link =$link'); Log.print('link: ${link}'); await uploadImage( compressedImage, { 'driverID': id, 'imageType': imageType, }, link, ); } catch (e) { print('Error in choosImage: $e'); Get.snackbar('Image Upload Failed'.tr, e.toString(), backgroundColor: AppColor.redColor); } finally { isloading = false; update(); } } // choosFaceFromDriverLicense(String link, String imageType) async { // final pickedImage = await picker.pickImage( // source: ImageSource.camera, // preferredCameraDevice: CameraDevice.rear, // ); // if (pickedImage == null) return; // image = File(pickedImage.path); // File? processedImage; // // For face images, use face detection and cropping // processedImage = await detectAndCropFace(image!); // if (processedImage == null) { // Get.snackbar('Face Detection Failed', 'No face detected in the image.'); // return; // } // isloading = true; // update(); // File compressedImage = await compressImage(processedImage); // try { // await uploadImage( // compressedImage, // { // 'driverID': box.read(BoxName.driverID).toString(), // 'imageType': imageType // }, // link, // ); // } catch (e) { // Get.snackbar('Image Upload Failed'.tr, e.toString(), // backgroundColor: AppColor.redColor); // } finally { // isloading = false; // update(); // } // } choosFace(String link, String imageType) async { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.front, ); if (pickedImage != null) { image = File(pickedImage.path); isloading = true; update(); // Compress the image File compressedImage = await compressImage(File(pickedImage.path)); // Save the picked image directly // File savedImage = File(pickedImage.path); print('link =$link'); try { await uploadImage( compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), 'imageType': imageType }, link, ); } catch (e) { Get.snackbar('Image Upload Failed'.tr, e.toString(), backgroundColor: AppColor.redColor); } finally { isloading = false; update(); } } } uploadImage(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', Uri.parse(link), ); Log.print('request: ${request}'); var length = await file.length(); var stream = http.ByteStream(file.openRead()); final headers = { 'Authorization': 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', // 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', }; Log.print('headers: ${headers}'); var multipartFile = http.MultipartFile( 'image', stream, length, filename: basename(file.path), ); request.headers.addAll(headers); // Set the file name to the driverID request.files.add( http.MultipartFile( 'image', stream, length, filename: '${box.read(BoxName.driverID)}.jpg', ), ); data.forEach((key, value) { request.fields[key] = value; }); var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}'); if (jsonDecode(res.body)['status'] == 'Image uploaded successfully!') { Get.snackbar('Success'.tr, 'Image uploaded successfully!'.tr, backgroundColor: AppColor.greenColor); } return jsonDecode(res.body); } else { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } } choosImagePicture(String link, String imageType) async { final pickedImage = await picker.pickImage( source: ImageSource.gallery, // preferredCameraDevice: CameraDevice.rear, // maxHeight: Get.height * .3, // maxWidth: Get.width * .9, // imageQuality: 100, ); image = File(pickedImage!.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, uiSettings: [ AndroidUiSettings( toolbarTitle: 'Cropper'.tr, toolbarColor: AppColor.blueColor, toolbarWidgetColor: AppColor.yellowColor, initAspectRatio: CropAspectRatioPreset.original, lockAspectRatio: false), IOSUiSettings( title: 'Cropper'.tr, ), ], ); myImage = File(pickedImage.path); isloading = true; update(); // Save the cropped image // File savedCroppedImage = File(croppedFile!.path); File compressedImage = await compressImage(File(croppedFile!.path)); print('link =$link'); try { await uploadImage( compressedImage, { 'driverID': box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), 'imageType': imageType }, link, ); } catch (e) { Get.snackbar('Image Upload Failed'.tr, e.toString(), backgroundColor: AppColor.redColor); } finally { isloading = false; update(); } } uploadImagePicture(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php' ); var length = await file.length(); var stream = http.ByteStream(file.openRead()); var multipartFile = http.MultipartFile( 'image', stream, length, filename: basename(file.path), ); request.headers.addAll({ 'Authorization': 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', }); // Set the file name to the driverID request.files.add( http.MultipartFile( 'image', stream, length, filename: '${box.read(BoxName.driverID)}.jpg', ), ); data.forEach((key, value) { request.fields[key] = value; }); var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { return jsonDecode(res.body); } else { throw Exception( 'Failed to upload image: ${res.statusCode} - ${res.body}'); } } } Future compressImage(File file) async { final dir = await path_provider.getTemporaryDirectory(); final targetPath = "${dir.absolute.path}/temp.jpg"; var result = await FlutterImageCompress.compressAndGetFile( file.absolute.path, targetPath, quality: 70, minWidth: 1024, minHeight: 1024, ); return File(result!.path); } // Future detectAndCropFace(File imageFile) async { // final inputImage = InputImage.fromFilePath(imageFile.path); // final options = FaceDetectorOptions( // enableClassification: false, // enableLandmarks: false, // enableTracking: false, // minFaceSize: 0.15, // performanceMode: FaceDetectorMode.accurate, // ); // final faceDetector = FaceDetector(options: options); // try { // final List faces = await faceDetector.processImage(inputImage); // final image = img.decodeImage(await imageFile.readAsBytes()); // if (image == null) throw Exception('Unable to decode image'); // int left, top, width, height; // if (faces.isNotEmpty) { // // Face detected, crop around the face // final face = faces[0]; // double padding = 0.2; // 20% padding // int paddingX = (face.boundingBox.width * padding).round(); // int paddingY = (face.boundingBox.height * padding).round(); // left = (face.boundingBox.left - paddingX).round(); // top = (face.boundingBox.top - paddingY).round(); // width = (face.boundingBox.width + 2 * paddingX).round(); // height = (face.boundingBox.height + 2 * paddingY).round(); // } else { // // No face detected, crop the center of the image // int size = min(image.width, image.height); // left = (image.width - size) ~/ 2; // top = (image.height - size) ~/ 2; // width = size; // height = size; // } // // Ensure dimensions are within image bounds // left = left.clamp(0, image.width - 1); // top = top.clamp(0, image.height - 1); // width = width.clamp(1, image.width - left); // height = height.clamp(1, image.height - top); // final croppedImage = // img.copyCrop(image, x: left, y: top, width: width, height: height); // // Save the cropped image // final tempDir = await path_provider.getTemporaryDirectory(); // final tempPath = tempDir.path; // final croppedFile = File('$tempPath/cropped_image.jpg'); // await croppedFile.writeAsBytes(img.encodeJpg(croppedImage, quality: 100)); // return croppedFile; // } finally { // faceDetector.close(); // } // }