Flutter camera package, how can I rotate the image? - flutter

My code is simle;
final XFile image=await cameraController!.takePicture();
takenImage=await image.readAsBytes();
and when I am just using this two line, I can see the image with Image.memory(_vm.takenImage!, fit: BoxFit.fitWidth)
But i need to change picture rotation,
for this reason, I am using image package https://pub.dev/packages/image
so, why I am getting invalid image data after just these lines;
final XFile image=await cameraController!.takePicture();
takenImage=await image.readAsBytes();
img.Image? decodedImage=img.decodeImage(takenImage!);
takenImage=decodedImage!.getBytes();
If I delete the last two sentence it's working correctlye but if I add the last lines I am getting Exceltion: invalid image data, but why ? I mean .getBytes returning Uint8List, takenImage type is Uint8List? ...
if I can convert like my second code review, I can use the; img.copyRotate(originalImage!, 90).getBytes(); function, so please help me for understand.

For my problem related image type cause as you can see on question I wasn't encode my image with any type, so the solution and working code now can seen on below;
final XFile image=await cameraController!.takePicture();
img.Image? _capturedImage=img.decodeImage(await image.readAsBytes());
_capturedImage=img.copyRotate(_capturedImage!, 90);
takenImage=Uint8List.fromList(img.encodePng(_capturedImage));

Related

How to get `Uint8List` from `ImmutableBuffer`?

The new Flutter 3.3 deprecates the method load of class ImageProvider and now some my code became not working because load had a parameter bytes of type Uit8List but loadBuffer has a parameter buffer of ImmutableBuffer.
I used Uint8List to decode image using image package
final bytes = img.decodeImage(bytes); // bytes is instance of Uit8List
The complete code can be read from the article Remove a color from an image in Flutter starting from section 4. Decode.
And now I need to convert ImmutableBuffer to Uint8List. Does someone know how to do this?

Reduce size image from bytes Uint8List

I am using the file_picker package to import images before uploading them to Firebase Storage, because it allows me to choose the formats what is not possible with image_picker.
I would like to be able to reduce the size of these images to reduce their weight. The flutter_image_compress package allows to compress images but it is not available for Flutter Web.
How can I reduce the size of an image imported in Flutter Web knowing that the format is Uint8List?
You can use the archive package to compress any data. The following is an example function taking Uint8List and compressing it:
Uint8List compress(Uint8List input) {
final encoder = ZLibEncoder();
return encoder.encode(input) as Uint8List;
}
You'll want to do this in a separate isolate since this could noticeably block your UI, but this won't make any difference if your application is web-only.
if you know the image type you can convert it to jpeg and then compress it using the flutter image package.
import 'package:image/image.dart' as img;
Future<List<int>> _pngToJpg(Uint8List pngBytes) async {
final pngImage = img.decodePng(pngBytes);
final pngImageResized = img.copyResize(pngImage!, width: 800);
return img.encodeJpg(pngImageResized, quality: 90);
}
you can use any other decoder depending on your image type. Expect a freeze in UI. You can use compute to minimize it.

How to convert file back to Asset

I am using the multiple file picker package on pub.dev, the link is below https://pub.dev/packages/multi_image_picker in conjunction with the image cropper package by Yalantis
https://pub.dev/packages/image_cropper
to let my user pick multiple images and then crop them at will.
I am using this code to convert my asset into a file and feed it into the cropper. And it works.
final temp = await Directory.systemTemp.createTemp();
final data = await finalList[index].getByteData();
File failo = await File('${temp.path}/img').writeAsBytes(
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
print("The path is ${temp.path}");
File croppedFailo = await ImageCropper.cropImage(
sourcePath: failo.path,
androidUiSettings: AndroidUiSettings(toolbarTitle: "My App"),
);
The tricky bit is to convert it back to an asset so that i can replace the old uncropped asset with this new cropped one..I read through the Asset documentation of the package and I tried this but it made my app crash
Asset croppedPic = new Asset(
croppedFailo.path,
DateTime.now().millisecondsSinceEpoch.toString(),
300,
300,
);
finalList.replaceRange(index, index + 1, [croppedPic]);
EDIT: When i say "asset", i am not referring to images i manually added to the assets/images folder in the app. The multi image picker plugin has a file- type called asset in which it returns images. That is the type to which i want to convert my file back into.
Never mind. I figured it's too unnecessarily complicated to do that. So, i instead just reformatted my entire code to handle images as files instead of assets. And, it actually made my life a lot simpler coz files give you more versatility and less problems than assets.

How to add markers on the map

I'm using the Flutter SDK Version 4.3.1.0.
I would like to display markers on the map and I found that this would be possible via:
final String positionMarkerPath = 'assets/markers/marker.png';
mapScene.addMapMarker(
MapMarker(
geoCoordinates,
MapImage.withFilePathAndWidthAndHeight(positionMarkerPath, 32, 32)));
When using this method I constantly get errors
E/CL_geoviz( 9632): [ERROR] CL_geoviz - Can't find image 'file:///assets/markers/marker.png' in asset repository.
E/CL_geoviz( 9632): [ERROR] CL_geoviz - Can't load image file 'file:///assets/markers/marker.png' to memory stream.
Now, the method MapImage.withFilePathAndWidthAndHeight is documented as follows in the SDK:
Creates a new map image from the provided path to the SVG Tiny image which is weird because I thought that Flutter doesn't even support SVG out of the box. Could that be an issue? Or what am I doing wrong here?
I tried using an SVG, Vector Drawable and a png, tried fully qualifying the path, nothing works
The documentation for MapImage.withFilePathAndWidthAndHeight says that it is only for SVG Tiny format. But it currently does not seem to work as the HERE SDK for Flutter is still in Beta state.
You can instead load and add PNG files as marker like this:
ByteData data = await rootBundle.load('assets/some_image.png');
MapImage image = MapImage.withPixelDataAndImageFormat(Uint8List.view(data.buffer), ImageFormat.png);
MapMarker marker = MapMarker(geoCoordinates, image);
hereMapController.mapScene.addMapMarker(marker);
The assets directory needs to be specified in the pubspec.yaml.

How to retrieve the exif orientation value in flutter

I am developing an app using Flutter and I want to retrieve the exif orientation value of an image that I selected using the image_picker plugin.
When I run the code below and select an image that I have rotated beforehand, I get null for the orientation value and an empty Map for the exif data.
File file = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
img.Image decodedImage = img.decodeImage(file.readAsBytesSync());
print("decodedImage.exif.orientation ${decodedImage.exif.orientation}"); // null
print("decodedImage.exif.data ${decodedImage.exif.data}"); // {}
I send the image that I used with this code to my mac book through google drive to see the orientation value and this is what I got:
I am using the newest available version of the image_picker plugin. How can I retrieve the exif orientation value of an image in Flutter?
I used this function:
needRotation(String path) async {
Map<String, IfdTag> data =
await readExifFromBytes(await new File(path).readAsBytes());
return data['EXIF ExifImageWidth'].values[0] >
data['EXIF ExifImageLength'].values[0];
}
using import 'package:exif/exif.dart';
Explain: given the path of an image it will return if need rotation (i.e. is in landscape mode)
I also hadthe null orientation problem that u mentioned and uses the width/height to figure it out my self...
It seems weired I know... hope someone comes with a better solution.