552 lines
16 KiB
Dart
552 lines
16 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'package:sefer_driver/constant/api_key.dart';
|
|
import 'package:sefer_driver/views/widgets/error_snakbar.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: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';
|
|
import '../../print.dart';
|
|
|
|
class ImageController extends GetxController {
|
|
File? myImage;
|
|
bool isloading = false;
|
|
CroppedFile? croppedFile;
|
|
final picker = ImagePicker();
|
|
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 {
|
|
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}');
|
|
//n8u22456
|
|
await uploadImage(
|
|
compressedImage,
|
|
{
|
|
'driverID':
|
|
box.read(BoxName.driverID) ?? box.read(BoxName.passengerID),
|
|
'imageType': imageType,
|
|
},
|
|
link,
|
|
);
|
|
} catch (e) {
|
|
print('Error in choosImage: $e');
|
|
mySnackeBarError('Image Upload Failed'.tr);
|
|
// Get.snackbar('Image Upload Failed'.tr, e.toString(),
|
|
// backgroundColor: AppColor.primaryColor);
|
|
} finally {
|
|
isloading = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
choosImageNewCAr(String link, String imageType) 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}');
|
|
//n8u22456
|
|
await uploadNewCar(
|
|
compressedImage,
|
|
{
|
|
'driverID': box.read(BoxName.driverID) +
|
|
'_' +
|
|
DateTime.now().toIso8601String(),
|
|
'imageType': imageType,
|
|
},
|
|
link,
|
|
);
|
|
} catch (e) {
|
|
print('Error in choosImage: $e');
|
|
// Get.snackbar('Image Upload Failed'.tr, e.toString(),
|
|
// backgroundColor: AppColor.primaryColor);
|
|
mySnackeBarError('Image Upload Failed'.tr);
|
|
} 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) {
|
|
mySnackeBarError('Image Upload Failed'.tr);
|
|
// 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),
|
|
);
|
|
|
|
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) {
|
|
Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
|
|
return jsonDecode(res.body);
|
|
} else {
|
|
throw Exception(
|
|
'Failed to upload image: ${res.statusCode} - ${res.body}');
|
|
}
|
|
}
|
|
|
|
uploadNewCar(File file, Map data, String link) async {
|
|
var request = http.MultipartRequest(
|
|
'POST',
|
|
Uri.parse(link),
|
|
);
|
|
|
|
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) {
|
|
Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}');
|
|
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) {
|
|
mySnackeBarError('Image Upload Failed'.tr);
|
|
// 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<File> 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<File> 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<Face> 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();
|
|
// }
|
|
// }
|