feat: image rotation (suite)
parent
d063256dce
commit
1ce0d03198
|
|
@ -81,8 +81,6 @@ class _CustomCameraPreviewState extends State<CustomCameraPreview> {
|
|||
shape: BoxShape.circle),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
/// TODO FBE delete image on local storage
|
||||
fileDelete((widget.photoFiles[index]));
|
||||
setState(() {
|
||||
widget.photoFiles.removeAt(index);
|
||||
});
|
||||
|
|
@ -103,16 +101,6 @@ class _CustomCameraPreviewState extends State<CustomCameraPreview> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> fileDelete(File file) async {
|
||||
try {
|
||||
if (await file.exists()) {
|
||||
await file.delete();
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Positioned _rejectButton() {
|
||||
return Positioned(
|
||||
bottom: 5,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// ignore_for_file: prefer_const_constructors
|
||||
|
||||
import 'dart:ui';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:mobdr/config/constant.dart';
|
||||
|
||||
|
|
@ -16,6 +17,7 @@ import 'package:flutter/services.dart';
|
|||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'objectbox.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
|
|
@ -59,6 +61,8 @@ class MyApp extends StatelessWidget {
|
|||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
initDirectories();
|
||||
|
||||
// Initialize all bloc provider used on this entire application here
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
|
|
@ -117,4 +121,23 @@ class MyApp extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
void initDirectories() async {
|
||||
// Get the application's document directory
|
||||
final Directory documentsDir = await getApplicationDocumentsDirectory();
|
||||
|
||||
// Create a Directory object for the "photos" directory in the documents directory
|
||||
final Directory photosDir = Directory('${documentsDir.path}/photos');
|
||||
|
||||
// Check if the "photos" directory exists
|
||||
if (await photosDir.exists()) {
|
||||
print(
|
||||
'The "photos" directory already exists in the documents directory.');
|
||||
} else {
|
||||
// Create the "photos" directory if it does not exist
|
||||
await photosDir.create();
|
||||
print(
|
||||
'The "photos" directory has been created in the documents directory.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class ObjectBox {
|
|||
concurrentBox.removeAll();
|
||||
visiteBox.removeAll();
|
||||
visiteTagBox.removeAll();
|
||||
photoBox.removeAll();
|
||||
//photoBox.removeAll();
|
||||
//photoTypologyBox.removeAll();
|
||||
|
||||
// Add some demo data if the box is empty.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import 'package:flutter/services.dart';
|
|||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:flutter/painting.dart' show ImageProvider;
|
||||
|
||||
import 'package:mobdr/config/constant.dart';
|
||||
import 'package:mobdr/main.dart';
|
||||
|
|
@ -16,6 +18,8 @@ import 'package:mobdr/ui/home/photo_camera.dart';
|
|||
import 'package:mobdr/model/photo_model.dart';
|
||||
import 'package:mobdr/db/box_photo.dart';
|
||||
|
||||
// TODO Il faut supprimer les possibles photos du répertoire cache !
|
||||
|
||||
extension FileNameExtension on File {
|
||||
String getFileName() {
|
||||
String fileName = path.split('/').last;
|
||||
|
|
@ -138,12 +142,8 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
children: <Widget>[
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
child: Image.file(
|
||||
File(photoData.image),
|
||||
fit: BoxFit.cover,
|
||||
height: 100,
|
||||
width: 150,
|
||||
),
|
||||
child: Image.file(File(photoData.image),
|
||||
fit: BoxFit.cover, height: 100, width: 150),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
|
|
@ -289,8 +289,10 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () async {
|
||||
await rotateAndReplaceImage(
|
||||
File(_photoData[index].image));
|
||||
setState(() => _listKey = GlobalKey());
|
||||
File(_photoData[index].image), 90);
|
||||
setState(() {
|
||||
_listKey = GlobalKey();
|
||||
});
|
||||
Fluttertoast.showToast(
|
||||
msg: 'The image has been rotated');
|
||||
},
|
||||
|
|
@ -310,8 +312,14 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
),
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
showPopupDeletePhoto(index, boxImageSize);
|
||||
onTap: () async {
|
||||
await rotateAndReplaceImage(
|
||||
File(_photoData[index].image), -90);
|
||||
setState(() {
|
||||
_listKey = GlobalKey();
|
||||
});
|
||||
Fluttertoast.showToast(
|
||||
msg: 'The image has been rotated');
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
|
||||
|
|
@ -345,8 +353,6 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
/// if the user has validated photos
|
||||
if (val == true) {
|
||||
savePhotos();
|
||||
} else {
|
||||
resetPhotos();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -384,12 +390,20 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
);
|
||||
}
|
||||
|
||||
void savePhotos() {
|
||||
Future<bool> evictImage(String imageURL) async {
|
||||
final NetworkImage provider = NetworkImage(imageURL);
|
||||
return await provider.evict();
|
||||
}
|
||||
|
||||
void savePhotos() async {
|
||||
if (photoFiles.length > 0) {
|
||||
final List<Photo> _listPhotos = [];
|
||||
final List<PhotoModel> _listPhotosModel = [];
|
||||
|
||||
for (var myPhoto in photoFiles) {
|
||||
for (var myTmpPhoto in photoFiles) {
|
||||
/// move jpg file to photo directory
|
||||
final myPhoto = await moveFileFromTempToPhotosDir(myTmpPhoto);
|
||||
|
||||
/// database
|
||||
_listPhotos.add(Photo(
|
||||
id_visite: 0,
|
||||
|
|
@ -412,15 +426,9 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
_photoData.insertAll(0, _listPhotosModel);
|
||||
|
||||
/// refresh widget
|
||||
setState(() => _listKey = GlobalKey());
|
||||
}
|
||||
}
|
||||
|
||||
void resetPhotos() {
|
||||
/// for all photos taken
|
||||
for (var photo in photoFiles) {
|
||||
/// delete image on local storage
|
||||
deleteFile(photo);
|
||||
setState(() {
|
||||
_listKey = GlobalKey();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -447,10 +455,13 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
onPressed: () {
|
||||
int removeIndex = index;
|
||||
var removedItem = _photoData.removeAt(removeIndex);
|
||||
|
||||
// delete file on database
|
||||
objectbox.delPhoto(removedItem.image_name);
|
||||
// delete file on locale storages
|
||||
|
||||
// delete file on local storage
|
||||
deleteFile(new File(removedItem.image));
|
||||
|
||||
// This builder is just so that the animation has something
|
||||
// to work with before it disappears from view since the original
|
||||
// has already been deleted.
|
||||
|
|
@ -494,7 +505,22 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> rotateAndReplaceImage(File imageFile) async {
|
||||
Future<File> moveFileFromTempToPhotosDir(File tempFile) async {
|
||||
// Get the application's document directory
|
||||
final Directory documentsDir = await getApplicationDocumentsDirectory();
|
||||
|
||||
// Set the new file path with the original file name
|
||||
final String newPath =
|
||||
'${documentsDir.path}/photos/${tempFile.path.split('/').last}';
|
||||
|
||||
// Rename the file to move it to the documents directory
|
||||
await tempFile.rename(newPath);
|
||||
|
||||
// Create and return a new File object for the new file
|
||||
return File(newPath);
|
||||
}
|
||||
|
||||
Future<void> rotateAndReplaceImage(File imageFile, int angle) async {
|
||||
// Read the image file into a Uint8List
|
||||
Uint8List bytes = await imageFile.readAsBytes();
|
||||
|
||||
|
|
@ -502,13 +528,15 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
img.Image? image = img.decodeImage(bytes);
|
||||
|
||||
// Rotate the image clockwise by 90 degrees
|
||||
img.Image? rotatedImage = img.copyRotate(image!, angle: 10);
|
||||
img.Image? rotatedImage = img.copyRotate(image!, angle: angle);
|
||||
|
||||
// Encode the rotated image back into a Uint8List
|
||||
Uint8List rotatedBytes = img.encodePng(rotatedImage);
|
||||
|
||||
// Overwrite the original file with the rotated image
|
||||
deleteFile(imageFile);
|
||||
await imageFile.writeAsBytes(rotatedBytes, flush: true);
|
||||
await imageFile.writeAsBytes(rotatedBytes);
|
||||
|
||||
// remove the flutter cache image
|
||||
FileImage(imageFile).evict();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue