From 53f3114ed13a7d18127121b3c23290a409dc4724 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 18 Jul 2024 15:29:25 +0300 Subject: [PATCH] 7/18/1 --- lib/controller/functions/upload_image.dart | 142 ++++++++++++++++++ .../auth/captin/cards/egypt_card_a_i.dart | 64 ++++---- .../widget/left_menu_map_captain.dart | 36 ++--- 3 files changed, 193 insertions(+), 49 deletions(-) diff --git a/lib/controller/functions/upload_image.dart b/lib/controller/functions/upload_image.dart index 2d8773a..bac2a10 100644 --- a/lib/controller/functions/upload_image.dart +++ b/lib/controller/functions/upload_image.dart @@ -8,6 +8,7 @@ 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; @@ -22,7 +23,148 @@ class ImageController extends GetxController { 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, diff --git a/lib/views/auth/captin/cards/egypt_card_a_i.dart b/lib/views/auth/captin/cards/egypt_card_a_i.dart index 004cf68..2fd1b06 100644 --- a/lib/views/auth/captin/cards/egypt_card_a_i.dart +++ b/lib/views/auth/captin/cards/egypt_card_a_i.dart @@ -455,26 +455,27 @@ Important notes: IconButton( onPressed: () async { await ai.allMethodForAI(""" - Given the following Arabic text values: + Given the following Arabic text values: + Please create a JSON object with the following fields: -- nationalID (use exactly 14 digits, no more and no less) -- issueDate (in format YYYY-MM-DD using Latin numerals) -- occupation -- gender -- country -- religion -- maritalStatus -- fullNameMarital (if maritalStatus is "أعزب", set this to "none") -- expirationDate (in format YYYY-MM-DD using Latin numerals) +nationalID: Use exactly 14 digits, converting from Arabic numerals to Latin numerals (0-9). +issueDate: Format as YYYY-MM-DD using Latin numerals, setting the date to the last day of the provided month. +occupation: Translate and format consistently (e.g., all lowercase). +gender: Translate and format consistently (e.g., all lowercase). +country: Set to "egypt". +religion: Translate and format consistently (e.g., all lowercase). +maritalStatus: Translate and format consistently (e.g., all lowercase). +fullNameMarital: If maritalStatus is "أعزب", set this to "none". Otherwise, leave it as "none". +expirationDate: Format as YYYY-MM-DD using Latin numerals. Important notes: -1. Ensure all date fields use Latin (Western) numerals (0-9) instead of Arabic numerals. -2. For the nationalID, use exactly 14 digits from the provided Arabic numeral string, converting to Latin numerals. -3. For issueDate, use the last day of the month since only year and month are provided. -4. Include the country field based on the provided information. -5. Format all string values consistently (e.g., all lowercase or proper case). +Ensure all date fields use Latin (Western) numerals (0-9) instead of Arabic numerals. +For the nationalID, use exactly 14 digits from the provided Arabic numeral string, converting to Latin numerals. +For issueDate, use the last day of the month since only year and month are provided. +Include the country field as "egypt". +Format all string values consistently (e.g., all lowercase or proper case). Please provide the resulting JSON object. """, AppLink.uploadEgypt, 'id_back'); //egypt }, @@ -545,27 +546,28 @@ Please provide the resulting JSON object. """, AppLink.uploadEgypt, child: InkWell( onTap: () async { await ai.allMethodForAI(''' - Given the following Arabic text values: + Given the following Arabic text values: + Please create a JSON object with the following fields: -- nationalID (use exactly 14 digits, no more and no less) -- issueDate (in format YYYY-MM-DD using Latin numerals) -- occupation -- gender -- country -- religion -- maritalStatus -- fullNameMarital (if maritalStatus is "أعزب", set this to "none") -- expirationDate (in format YYYY-MM-DD using Latin numerals) +nationalID: Use exactly 14 digits, converting from Arabic numerals to Latin numerals (0-9). +issueDate: Format as YYYY-MM-DD using Latin numerals, setting the date to the last day of the provided month. +occupation: Translate and format consistently (e.g., all lowercase). +gender: Translate and format consistently (e.g., all lowercase). +country: Set to "egypt". +religion: Translate and format consistently (e.g., all lowercase). +maritalStatus: Translate and format consistently (e.g., all lowercase). +fullNameMarital: If maritalStatus is "أعزب", set this to "none". Otherwise, leave it as "none". +expirationDate: Format as YYYY-MM-DD using Latin numerals. Important notes: -1. Ensure all date fields use Latin (Western) numerals (0-9) instead of Arabic numerals. -2. For the nationalID, use exactly 14 digits from the provided Arabic numeral string, converting to Latin numerals. -3. For issueDate, use the last day of the month since only year and month are provided. -4. Include the country field based on the provided information. -5. Format all string values consistently (e.g., all lowercase or proper case). -Please provide the resulting JSON object. ''', AppLink.uploadEgypt, +Ensure all date fields use Latin (Western) numerals (0-9) instead of Arabic numerals. +For the nationalID, use exactly 14 digits from the provided Arabic numeral string, converting to Latin numerals. +For issueDate, use the last day of the month since only year and month are provided. +Include the country field as "egypt". +Format all string values consistently (e.g., all lowercase or proper case). +Please provide the resulting JSON object.''', AppLink.uploadEgypt, 'id_back'); //egypt }, child: Column( diff --git a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart index 73d91c7..b42d07d 100644 --- a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart +++ b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart @@ -179,24 +179,24 @@ GetBuilder leftMainMenuCaptainIcons() { ), ), ), - // AnimatedContainer( - // duration: const Duration(microseconds: 200), - // width: controller.widthMapTypeAndTraffic, - // decoration: BoxDecoration( - // color: AppColor.secondaryColor, - // border: Border.all(color: AppColor.blueColor), - // borderRadius: BorderRadius.circular(15)), - // child: IconButton( - // onPressed: () async { - // Get.to(() => EgyptCardAI()); - // }, - // icon: const Icon( - // FontAwesome5.grin_tears, - // size: 29, - // color: AppColor.blueColor, - // ), - // ), - // ), + AnimatedContainer( + duration: const Duration(microseconds: 200), + width: controller.widthMapTypeAndTraffic, + decoration: BoxDecoration( + color: AppColor.secondaryColor, + border: Border.all(color: AppColor.blueColor), + borderRadius: BorderRadius.circular(15)), + child: IconButton( + onPressed: () async { + Get.to(() => EgyptCardAI()); + }, + icon: const Icon( + FontAwesome5.grin_tears, + size: 29, + color: AppColor.blueColor, + ), + ), + ), ], )), );