I'm trying to change image size from uint8list data.
There are lots of Image classes in Flutter as you know,
and The final type of image I want to get is ui.Image.
I get Uint8List Image(.jpg) data from socket communication.
Now, I want to set the size of the image and get the Image of ui.Image at the end.
I tried to do that through (dart:ui : ui, package:image/image.dart : IMG)
IMG.Image img = IMG.decodeImage(data);
IMG.Image resized = IMG.copyResize(img, width: 400, height: 200);
ui.Codec codec = await ui.instantiateImageCodec(IMG.encodeJpg(resized));
ui.Image image = (await codec.getNextFrame()).image;
,but It freezes the app.
How can I do that? Is there any way? Thank you.
Additionally,
In "flutter/lib/src/widgets/image.dart",
Image.memory(Uint8List, width, height) can make it be easy to set image size.
Is there any way to get Uint8List from that Image widget?
I resized the image data in Uint8List like below.
import package:image/image.dart as IMG
Uint8List resizeImage(Uint8List data) {
Uint8List resizedData = data;
IMG.Image img = IMG.decodeImage(data);
IMG.Image resized = IMG.copyResize(img, width: img.width*2, height: img.height*2);
resizedData = IMG.encodeJpg(resized);
return resizedData;
}
IMG : flutter image package
Have you tried using ui.decodeImageFromList instead of ui.instantiateImageCodec and getNextFrame() ?
import 'dart:ui' as ui;
ui.decodeImageFromList(IMG.encodeJpg(resized), (ui.Image img) {
// returned ui.Image
});
Related
Looking for a simple and fast example / tutorial to composite / overlay several images in Flutter, using (PNG) images from the assets directory:
Few options I've examined:
Manipulate Uint8List and use it in image.Memory
Use canvas.drawAtlas in my own Painter
use the image library (which seems a bit overkill in this case
Couldn't find any working example that suits my needs...
I'd appreciate any working example / tutorial that will help me, thanks!
4.Use combination of Stack and RepaintBoundary to generate new image:
Future<Uint8List> _takeScreenShot(context) async {
RenderRepaintBoundary boundary = _repaintKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: 2.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
return pngBytes;
}
Stack(
key: _repaintKey,
children: [
//your background image,
//your png image,
],
)
Good day ,I am generating certificates and for this I have a template where I must write user data, for the moment I am creating the certificates in pdf format, but the ideal would be to use images or convert those pdf to image since it is easier for the user to handle images, I have not found any library capable of writing in images that works correctly.
At the moment I am trying to use Image. https://pub.dev/packages/image.
I have the following code, but it fails to add a text fragment in the image.
imagecert = await ManagerDB().getcertificate(certificatetemplate); //imagecert is uint8list
if (imagecert != null) {
mg.Image ima = mg.Image.fromBytes(300, 200, List.from(imagecert)); Image works with list<int>
mg.Image imag = mg.drawString(ima, mg.arial_14, 0, 0, 'Hello World'); //here the code does not work
List<int> data = mg.encodePng(imag);
Uint8List bytes = Uint8List.fromList(data);
setState(() {});
return bytes;
} else {
print("Enlace no encontrado");
}
I don't know if there is a simpler solution to write text in an image. It is required to store those images.
Thank you
you can put image inside widget and add to that widget text
and converted to image using globalKey (don't forget to pass globalKey to key of that sepecific widget )
Future<Uint8List> _convertWidgetToImage(GlobalKey globalKey) async {
RenderRepaintBoundary boundary =
globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData byteData =
(await (image.toByteData(format: ui.ImageByteFormat.png)))!;
Uint8List pngBytes = byteData.buffer.asUint8List();
return pngBytes;
}
In my App, I need to create Images from the Widgets shown on Screen.
I used the below code to create the Image using RepaintBoundary.
But the image I get is of 72 PPI.
Is there any way I can get An Image of Higher Resolution?
Future<void> takePicture() async {
RenderRepaintBoundary boundary = genKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
File imgFile = new File('$directory/photo.png');
imgFile.writeAsBytes(pngBytes);
}
use this line will improve the "boundary.toImage(pixelRatio: 10.0)"
pixelRatio use as double to improve the quality as u want.
My goal is to increase the performance of my website by downscaling images.
When i show NetworkImages they always render the full source image resolution (e.g. 7000x4667 pixel). The widget itself mostly has a smaller size (e.g. 200x200 pixel). I have the image url and want to scale the 7000x4667 pixel image down to 200x200 before loading it in the NetworkImage widget.
What i already tried is the answer from this question:
Flutter - Resize network image
That does work in flutter for mobil but not in flutter web as the line ByteData originalByteData = await originalUiImage.toByteData(); returns null in flutter web.
Already thank you a lot in advance for your help.
I found a solution that propably suits you . Speed is fantastic and size of the image is reduced significantly.
late Uint8List targetlUinit8List;
late Uint8List originalUnit8List;
Future<Uint8List> _resizeImage() async {
var imageUrl = Uri.parse('https://picsum.photos/250?image=9');
http.Response response = await http.get(imageUrl);
originalUnit8List = response.bodyBytes;
ui.Image originalUiImage = await decodeImageFromList(originalUnit8List);
ByteData? originalByteData = await originalUiImage.toByteData();
print('original image ByteData size is ${originalByteData!.lengthInBytes}');
var codec = await ui.instantiateImageCodec(originalUnit8List,
targetHeight: 200, targetWidth: 200);
var frameInfo = await codec.getNextFrame();
ui.Image targetUiImage = frameInfo.image;
ByteData? targetByteData =
await targetUiImage.toByteData(format: ui.ImageByteFormat.png);
print('target image ByteData size is ${targetByteData!.lengthInBytes}');
targetlUinit8List = targetByteData.buffer.asUint8List();
//remove delay function
await Future.delayed(Duration(seconds: 2));
return targetlUinit8List;
}
Then I have a futureBuilder for my example , but you can use anything you want :
if (snapshot.hasData) {
children = <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Image.memory(snapshot.data!),
)
];
}
Only thing left to implement is to dispose the unused variables , and I have no idea how to do it (I am not the best at flutter). I want to know if anyone implements this with disposed variables
After reading an image with the ImageDescriptor API and resizing it by instantiating a codec I am trying to write the resized version in the application directory.
I saw that the when converting the frame into byte data I have a format which is rawUnmodified which I assumed would write the resized image in the same format as the original image. But when I tried to load the resized image I get an image format exception.
Example code:
//read the original image and obtain the image descriptor
var imageData = await file.readAsBytes();
final ImmutableBuffer buffer = await ImmutableBuffer.fromUint8List(imageData);
final imDescr = await ImageDescriptor.encoded(buffer);
//resize the image, get the first frame and convert it to bytes
Codec codec = await imDescr.instantiateCodec(targetWidth: 100, targetHeight: 100);
FrameInfo frameInfo = await codec.getNextFrame();
var bytes = await frameInfo.image.toByteData(
format: ImageByteFormat.rawUnmodified,
//note when using the png format it works, but I would like to have it in the original image format(in this case its jpg)
);
//write the resized image
Directory appDir = await getApplicationDocumentsDirectory();
var path = appDir.path;
var file = File('$path/test1.jpg');
await file.writeAsBytes(bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));
In the ImageByteFormat api it says: rawUnmodified -> Unencoded bytes, in the image's existing format. For example, a grayscale image may use a single 8-bit channel for each pixel.
But when I try to show this image the format is wrong. Anybody have an idea how to fix this?
Why use image ImageDescriptor, You can do it easily by image package
File resizeImage(File imageFile, String imageFormat, int targetWidth, int targetHeight) {
im.Image tempImage = im.decodeImage(imageFile.readAsBytesSync());
tempImage = im.bakeOrientation(tempImage);
tempImage = im.copyResize(tempImage, width: targetWidth, height: targetHeight);
File newImage;
if (imageFormat == 'jpg') {
newImage = File('newpath/test.jpg');
newImage.writeAsBytesSync(im.encodeJpg(tempImage));
return newImage;
} else if (imageFormat == 'png') {
newImage = File('newpath/test.png');
newImage.writeAsBytesSync(im.encodePng(tempImage));
return newImage;
} else {
throw ('Unknown Image Format');
}
}