Drawing a photo from the camera on a canvas? - flutter

I want to take a photo with the image_picker library that stores the file on the phone sd card.
I want to then load this image so that i can draw it with a CustomPaint widget by drawing the image on the canvas.
I have tried to load the image with both FileImage and Image.file
but this doesn't work because the 'Image' in the CustomPaint extends NativeFieldWrapperClass2 and isn't an Image widget
Is there anyone who knows how to load a photo and draw it on a canvas?

You need the ui package version of Image (as distinct from the widget called Image)
Import the ui package, and create a method to return the ui.Image:
import 'dart:ui' as ui;
Future<ui.Image> load(String filename) async {
var file = File(filename);
var bytes = await file.readAsBytes();
var codec = await ui.instantiateImageCodec(bytes);
var fi = await codec.getNextFrame();
return fi.image;
}
Use ui.Image to draw. You may need a transform to shrink it.

Related

Flutter: Async Await Function Not Waiting

I am doing some image processing and building in my app using the Image package. In this case, I am building a LinearProgressIndicator widget that is then converted into an image file, that is then merged into a larger image later on. However, the functions to build and take the image of the progress indicator widget isn't being waited on and the following error is observed
FileSystemException: Cannot open file, path = '/Users//Library/Developer/CoreSimulator/Devices//data/Containers/Data/Application//Library/Caches/bar.png' (OS Error: No such file or directory, errno = 2)
However, the progress indicator file is being created (I can see the cache), and then if I rerunning the image processing it works just fine (because now the file is there). However, I need it work on the first time. Here is what I have for image processing
import 'package:image/image.dart' as ui;
Future<File> instagramChalShare(BuildContext context, double progress) async {
//this is where it does not appear the progressBarPathFunct is being waited on
final testFile = await progressBarPathFunct(context, progress);
ui.Image tester = ui.decodeImage(testFile.readAsBytesSync());
//image is then resized
ui.Image progressResized = ui.Image(600, 90);
ui.drawImage(progressResized, tester);
//now progress bar is merged into larger image
final mergedImage = ui.Image(width, height);
ui.copyInto(mergedImage, progressResized, blend: true);
List<int> imageFile = ui.encodePng(mergedImage);
final imageFilePath = await File('${(await getTemporaryDirectory()).path}/temp.png').create();
print('picture finished $imageFilePath');
return imageFilePath.writeAsBytes(imageFile);
}
Here is the function to build the LinearProgressIndictor, convert it to an image, and create a file where the image is held.
Future<File> progressBarPathFunct(BuildContext context, double progress) async {
final progressFile = File('${(await getTemporaryDirectory()).path}/bar.png');
var indicator = LinearPercentIndicator(
percent: progress > 1.0 ? 1.0 : progress,
width: context.size.width,
lineHeight: 13,
),
barRadius: Radius.circular(20),
);
screenshotController.captureFromWidget(
InheritedTheme.captureAll(context, Material(child: indicator)),
).then((capturedProgress) async {
await progressFile.create(recursive: true);
await progressFile.writeAsBytes(capturedProgress);
});
print('progress bar path from functions ${progressFile.path}');
return progressFile;
}
This function is working, but it seems the top one creating the merged Image file is not waiting for this function to finish before attempting to complete.
Edit
I am following the example from the screenshot package to generate an image of a widget that is not on the screen.

Flutter: Image Package Crop to Circle

I am using the Image package to handle and process images in a flutter app. In this case, I am downloading the users profile pic and attempting to resize it and crop it to a circle. However, it does not appear to be cropping the image at all. Am I missing something here?
import 'package:image/image.dart' as ui;
final getProfile = await http.get(Uri.parse(profilePicPath));
final profileFile = File('${(await getTemporaryDirectory()).path}/image.png');
await profileFile.create(recursive: true);
await profileFile.writeAsBytes(getProfile.bodyBytes);
ui.Image profileImage = ui.decodeImage(profileFile.readAsBytesSync());
ui.copyCropCircle(profileImage, radius: 10);
Edit: I need to keep the image as a file and will not be shown in the UI (eventually used to overlay in another image file).
For anyone who runs into this issue, it was only a slight modification that got it to work. This pulls in the photo, stores it, resizes it, and then crops it to a cricle.
import 'package:image/image.dart' as ui;
final getProfile = await http.get(Uri.parse(profilePicPath));
final profileFile = File('${(await getTemporaryDirectory()).path}/image.png');
await profileFile.create(recursive: true);
await profileFile.writeAsBytes(getProfile.bodyBytes);
ui.Image profileImage = ui.decodeImage(profileFile.readAsBytesSync());
profileImage = ui.copyResize(profileImage, height: 100, width: 100);
profileImage = ui.copyCropCircle(profileImage, radius: 50);

Flutter: How to generate screenshots in arbitrary resolutions?

In Flutter, how do you get a screenshot for an arbitrary screen resolution? I.e. for a screen resolution that's different from the resolution the app is running in?
Is there a way to tell the Flutter engine to paint a single frame into a buffer with a specific resolution?
What I'm trying to accomplish is to generate the screenshots for the various app stores from within the app, but without scaling and cropping screenshots that were taken for different devices/resolutions.
How would you tackle that requirement?
Any advise is welcome,
Thank you!
if you are talking about taking a screenshot of a particular widget and saving it
the you have to use renderrepaint boundry with key .
dependencies - path provider
Image gallery saver ..
takeScreenshot(BuildContext context,GlobalKey _key,String slug) async {
RenderRepaintBoundary boundary = _key.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
final snackBar = SnackBar(content: Text("Image saved to gallery"));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final result = await ImageGallerySaver.saveImage(
byteData.buffer.asUint8List(),
name: "name.jpg");
}

how to embed widgets to images and save it to the device

I have an image with a container on it. I want to be able to edit the TextField inside the container and save the image as an image to the device.
My current setup is a stack where I have the image and a container on top of each other. How can I save that as an image?
Note that I don't want to save the whole screen, just the image and whatever on it.
Future<File> createWave(BuildContext context, GlobalKey screen) async {
RenderRepaintBoundary boundary = screen.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final directory = (await getApplicationDocumentsDirectory()).path;
File imgFile = File('$directory/screenshot.png');
await imgFile.writeAsBytes(pngBytes);
return imgFile;
}
Thankfully since flutter uses skia to render it's graphics, we are able to take screenshots of widgets and there is already a really good article that does somethings similar. Basically you wrap your widget in a RepaintBoundary and assign it a key then use the key to call the RenderObject.toImage method. Here is another simple example to do this. It's amazing how simple it is :D

How to convert image provider to image in flutter inorder use in canvas? [duplicate]

I basically want to show an image that I have in the assets folder onto the canvas.
import 'package:flutter/material.dart' as ui;
...
ui.Image img = ui.Image.asset("images/some_image.png");
ui.paintImage(canvas: canvas, image: img);
And have got the following error message when I tried to assign img to paintImage's image.
The argument type 'Image (C:\ABC\flutter\packages\flutter\lib\src\widgets\image.dart)' can't be assigned to the parameter type 'Image (C:\ABC\flutter\bin\cache\pkg\sky_engine\lib\ui\painting.dart)'.
I don't really know what could go wrong, I have seen other codes that had a similar approach with ui.Image.
Please advise.
There are two classes called Image in flutter, in different packages.
There's the Widget, which behaves like a widget and can be instantiated from an asset, from memory or from the network through its named constructors.
There's also the ui package Image which is used when painting at a lower level, for example in a CustomPainter. Since this version is in the ui package it's normally imported with the ui prefix like this:
import 'dart:ui' as ui;
Don't import material as ui! That will lead to a lot of confusion.
To make a widget, use the Image.asset constructor, passing the asset name.
To make a ui.Image from an asset use this snippet:
Future<ui.Image> load(String asset) async {
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return fi.image;
}