import 'dart:convert'; import 'dart:io'; import 'package:SEFER/constant/api_key.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 image_package; import 'package:image/image.dart' as img; import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.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) async { 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, aspectRatioPresets: [ CropAspectRatioPreset.square, CropAspectRatioPreset.ratio3x2, CropAspectRatioPreset.original, CropAspectRatioPreset.ratio4x3, CropAspectRatioPreset.ratio16x9 ], 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 rotatedImage = await rotateImage(compressedImage); File processedImage = await rotateImageIfNeeded(File(croppedFile!.path)); File compressedImage = await compressImage(processedImage); 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(); } } choosImage1(String link, String imageType) async { final pickedImage = await picker.pickImage( source: ImageSource.camera, preferredCameraDevice: CameraDevice.rear, // maxHeight: Get.height * .3, // maxWidth: Get.width * .9, // imageQuality: 100, ); image = File(pickedImage!.path); croppedFile = await ImageCropper().cropImage( sourcePath: image!.path, aspectRatioPresets: [ CropAspectRatioPreset.square, CropAspectRatioPreset.ratio3x2, CropAspectRatioPreset.original, CropAspectRatioPreset.ratio4x3, CropAspectRatioPreset.ratio16x9 ], 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(); } } 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), //'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}'); } } 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, aspectRatioPresets: [ CropAspectRatioPreset.square, CropAspectRatioPreset.ratio3x2, CropAspectRatioPreset.original, CropAspectRatioPreset.ratio4x3, CropAspectRatioPreset.ratio16x9 ], 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); }