7/18/1
This commit is contained in:
@@ -8,6 +8,7 @@ import 'package:image_cropper/image_cropper.dart';
|
|||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:image/image.dart' as image_package;
|
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:flutter_image_compress/flutter_image_compress.dart';
|
||||||
import 'package:path_provider/path_provider.dart' as path_provider;
|
import 'package:path_provider/path_provider.dart' as path_provider;
|
||||||
@@ -22,7 +23,148 @@ class ImageController extends GetxController {
|
|||||||
CroppedFile? croppedFile;
|
CroppedFile? croppedFile;
|
||||||
final picker = ImagePicker();
|
final picker = ImagePicker();
|
||||||
var image;
|
var image;
|
||||||
|
|
||||||
|
Future<img.Image> 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<File> 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<File> 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 {
|
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(
|
final pickedImage = await picker.pickImage(
|
||||||
source: ImageSource.camera,
|
source: ImageSource.camera,
|
||||||
preferredCameraDevice: CameraDevice.rear,
|
preferredCameraDevice: CameraDevice.rear,
|
||||||
|
|||||||
@@ -457,24 +457,25 @@ Important notes:
|
|||||||
await ai.allMethodForAI("""
|
await ai.allMethodForAI("""
|
||||||
Given the following Arabic text values:
|
Given the following Arabic text values:
|
||||||
|
|
||||||
|
|
||||||
Please create a JSON object with the following fields:
|
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:
|
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,
|
Please provide the resulting JSON object. """, AppLink.uploadEgypt,
|
||||||
'id_back'); //egypt
|
'id_back'); //egypt
|
||||||
},
|
},
|
||||||
@@ -547,25 +548,26 @@ Please provide the resulting JSON object. """, AppLink.uploadEgypt,
|
|||||||
await ai.allMethodForAI('''
|
await ai.allMethodForAI('''
|
||||||
Given the following Arabic text values:
|
Given the following Arabic text values:
|
||||||
|
|
||||||
|
|
||||||
Please create a JSON object with the following fields:
|
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:
|
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
|
'id_back'); //egypt
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@@ -179,24 +179,24 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// AnimatedContainer(
|
AnimatedContainer(
|
||||||
// duration: const Duration(microseconds: 200),
|
duration: const Duration(microseconds: 200),
|
||||||
// width: controller.widthMapTypeAndTraffic,
|
width: controller.widthMapTypeAndTraffic,
|
||||||
// decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
// color: AppColor.secondaryColor,
|
color: AppColor.secondaryColor,
|
||||||
// border: Border.all(color: AppColor.blueColor),
|
border: Border.all(color: AppColor.blueColor),
|
||||||
// borderRadius: BorderRadius.circular(15)),
|
borderRadius: BorderRadius.circular(15)),
|
||||||
// child: IconButton(
|
child: IconButton(
|
||||||
// onPressed: () async {
|
onPressed: () async {
|
||||||
// Get.to(() => EgyptCardAI());
|
Get.to(() => EgyptCardAI());
|
||||||
// },
|
},
|
||||||
// icon: const Icon(
|
icon: const Icon(
|
||||||
// FontAwesome5.grin_tears,
|
FontAwesome5.grin_tears,
|
||||||
// size: 29,
|
size: 29,
|
||||||
// color: AppColor.blueColor,
|
color: AppColor.blueColor,
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
// ),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user