'How to: rotate a selected/set image (Flutter)
I've managed to rotate images to landscape/portrait after selecting them from Image picker (gallery/camera) ..
This works fine, and will continue set new images to my desired orientation ..
However, I'm trying to use the same method to rotate an already selected/set image and it doesn't work ..
Here is the logic I'm using:
import 'package:image/image.dart' as img;
void _rotateImage(File file) async {
print('>>> rotating image');
try {
List<int> imageBytes = await file.readAsBytes();
final originalImage = img.decodeImage(imageBytes);
print('>>> original width: ${originalImage.width}');
img.Image fixedImage;
fixedImage = img.copyRotate(originalImage, 90);
print('>>> fixed width: ${fixedImage.width}');
final fixedFile = await file.writeAsBytes(img.encodeJpg(fixedImage));
setState(() {
print('>>> setting state');
_image = fixedFile;
});
} catch (e) {
print(e);
}
}
I can even see that the image is getting rotated before setting state, but it still doesn't update on screen (this is showing two attempts, not multiple in one)
I/flutter (18314): >>> rotating image
I/flutter (18314): >>> original width: 450
I/flutter (18314): >>> fixed width: 360
I/flutter (18314): >>> setting state
I/flutter (18314): >>> rotating image
I/flutter (18314): >>> original width: 360
I/flutter (18314): >>> fixed width: 450
I/flutter (18314): >>> setting state
Does anyone has any idea why this method works when picking a new image from the camera/gallery but won't when using a file that's already in the state?
[EDIT] I thought it may be something to do with the same file path being used. So I added this code below and although it makes the image refresh, for a fraction of a second, it still doesn't show the rotated image [/EDIT]
import 'package:image/image.dart' as img;
void _rotateImage(File file) async {
try {
Random random = new Random();
int randomNumber = random.nextInt(1000000);
final newFile = await file.copy(
'/data/user/0/!PRIVATE!/cache/rotatedImage$randomNumber.jpg');
List<int> imageBytes = await newFile.readAsBytes();
final originalImage = img.decodeImage(imageBytes);
img.Image fixedImage;
fixedImage = img.copyRotate(originalImage, 90);
final fixedFile = await newFile.writeAsBytes(img.encodeJpg(fixedImage),
mode: FileMode.append, flush: true);
setState(() {
_image = fixedFile;
});
} catch (e) {
print(e);
}
}
Below is some code to show what's happening when selecting an image and choosing to rotate
import 'package:image/image.dart' as img;
void _pickImage() async {
Navigator.pop(context);
try {
final pickedFile =
await _imagePicker.getImage(source: ImageSource.gallery);
File file = File(pickedFile.path);
if (pickedFile != null && _rotateToLandscape) {
await _setImageToLandscape(file);
} else if (pickedFile != null) {
await _setImageToPortrait(file);
}
} catch (e) {
print(e);
}
}
Future<void> _setImageToLandscape(File file) async {
print('>>> setting image to landscape');
try {
setState(() {
_loading = true;
});
var decodedImage = await decodeImageFromList(file.readAsBytesSync());
int width = decodedImage.width;
int height = decodedImage.height;
if (width > height) {
print('>>> returing original image');
_setSelectedImage(file);
} else if (width < height) {
print('>>> rotating image');
List<int> imageBytes = await file.readAsBytes();
final originalImage = img.decodeImage(imageBytes);
img.Image fixedImage;
fixedImage = img.copyRotate(originalImage, -90);
final fixedFile = await file.writeAsBytes(img.encodeJpg(fixedImage));
_setSelectedImage(fixedFile);
}
} catch (e) {
print(e);
} finally {
setState(() {
_loading = false;
});
}
}
void _setSelectedImage(File file) {
switch (_selectedImage) {
case 1:
setState(() {
_image = file;
widget.setImage(image: file);
});
break;
case 2:
setState(() {
_image2 = file;
widget.setImage(image2: file);
});
break;
case 3:
setState(() {
_image3 = file;
widget.setImage(image3: file);
});
break;
}
}
Solution 1:[1]
Future<File?> _rotateImage(
String url, String fileExt, AttachmentModel item) async {
try {
File file;
if (item.file == null) {
file = await urlToFile(url, fileExt, true);
} else {
file = await urlToFile(url, fileExt, false);
List<int> temp = await item.file!.readAsBytes();
await file.writeAsBytes(temp);
}
List<int> imageBytes = await file.readAsBytes();
final originalImage = img.decodeImage(imageBytes);
print('previous width: ${originalImage?.width}');
img.Image newImage;
newImage = img.copyRotate(originalImage!, 90);
print('width: ${newImage.width}');
final fixedFile = await file.writeAsBytes(img.encodeJpg(newImage));
int index = attachments!.indexOf(item);
attachments![index] = AttachmentModel(
attachmentUrl: fixedFile.path,
fileExt: fileExt,
file: fixedFile,
);
setState(() {});
return fixedFile;
} catch (e) {
print(e);
return null;
}
}
Future<File> urlToFile(String imageUrl, String fileExt, bool isNet) async {
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
File file = File(tempPath + DateTime.now().toString() + '.$fileExt');
if (!isNet) return file;
Uri uri = Uri.parse(imageUrl);
http.Response response = await http.get(uri);
await file.writeAsBytes(response.bodyBytes);
return file;
}
Don't use original file, create new one over the original file, I put this code for an example. I know it's to late but maybe It can help someone
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Lala Naibova |
