Reputation: 30909
In Flutter/Dart, how can I perform the following 3 steps:
Note: I must be able to display the final result with a regular Flutter Image widget.
CLARIFICATION: I don't want to save the image, but I do want to actually resize it in memory.
Upvotes: 66
Views: 116063
Reputation: 17412
I would say use the dart image
package.
import 'package:image/image.dart' as image show
decodedImage, copyResize //, encodePng
;
import 'dart:convert' as convert show
base64encode
;
void resizeImage() async {
List<int> fileBytes = await file.readAsBytes();
image.Image decodedImage = image.decodeImage(fileBytes) as image.Image;
image.Image thumbnail = image.copyResize(decodedImage, width: 60);
List<int> resizedIntList = thumbnail.getBytes();
// Or compress as a PNG image
// List<int> resizedIntList = image.encodePng(thumbnail, level: 6);
String resizedBase64Image = convert.base64Encode(resizedIntList);
}
You could also reference the following code, if you don't want the overhead of the package.
import 'dart:ui' as ui show
Codec, instantiateImageCodec, FrameInfo;
import 'dart:typed_data' as typedData show
ByteData, Uint8List
;
import 'dart:convert' as convert show
base64Encode
;
void resizeImage() async {
typedData.Uint8List fileBytes = await file.readAsBytes();
// Resize image
// ----------
ui.Codec codec = await ui.instantiateImageCodec(
fileBytes,
targetWidth: 60
);
ui.FrameInfo frameInfo = await codec.getNextFrame();
ui.Image resizedImage = frameInfo.image;
// ----------
// Convert to List<int>
// ----------
typedData.ByteData resizedByteData = await resizedImage.toByteData() as typedData.ByteData;
typedData.Uint8List resizedUint8List = resizedByteData.buffer
.asUint8List(resizedByteData.offsetInBytes, resizedByteData.lengthInBytes);
List<int> resizedIntList = resizedUint8List.cast<int>();
// ----------
String resizedBase64Image = convert.base64Encode(resizedIntList);
}
Upvotes: 4
Reputation: 7289
There are many solutions :
ResizeImage class instructs Flutter to decode the image at the specified dimensions instead of at its native size.
Usage : Just wrap your ImageProvider with ResizeImage class
Example :
Image(image: ResizeImage(AssetImage('eg.png'), width: 70, height: 80)),
ImageProvider includes
AssetImage
,NetworkImage
,FileImage
andMemoryImage
.
cacheHeight
and cacheWidth
property in your Image widgetThese properties create a widget that displays an [ImageStream] obtained from an asset , network , memory or file .
Example :
Image.asset('assets/image.png', cacheHeight:120 , cacheWidth: 150),
There are these properties in
Image.asset
,Image.network
,Image.file
andImage.memory
Upvotes: 7
Reputation: 51
final pickedFile = await picker.getImage(
source: ImageSource.gallery,
imageQuality: 25,
maxHeight: 1024,
maxWidth: 1024);
Upvotes: 4
Reputation: 10264
Use the ResizeImage
image provider.
Using a separate package is nice if you want to use many of the functionality, or if you can't do otherwise. But just to depend on something instead of what the framework itself (and its underlying graphics engine) can do easily... :-)
If you have an ImageProvider
now, say, to display an image from the bytes in memory:
Image(image: MemoryImage(bytes))
Just wrap it inside a ResizeImage
:
Image(image: ResizeImage(MemoryImage(bytes), width: 50, height: 100))
And if you want even more control, just create your own image provider based on the source code of this one.
Upvotes: 14
Reputation: 31386
You can read image from the disk using the image.file constructor.
For more features you can use the Image library
A Dart library providing the ability to load, save and manipulate images in a variety of different file formats.
Sample from the documentation examples
Load a jpeg, resize it and save it as a png
import 'dart:io' as Io;
import 'package:image/image.dart';
void main() {
// Read a jpeg image from file.
Image image = decodeImage(new Io.File('test.jpg').readAsBytesSync());
// Resize the image to a 120x? thumbnail (maintaining the aspect ratio).
Image thumbnail = copyResize(image, width: 120);
// Save the thumbnail as a PNG.
new Io.File('out/thumbnail-test.png')
..writeAsBytesSync(encodePng(thumbnail));
}
Upvotes: 76
Reputation: 51
you can use the image class from dart ui library, get the image object with your desired width and height using the frameInfo from intantiateImageCodec and then save it in your desired path
import 'dart:ui' as ui;
Uint8List m = File(path).readAsBytesSync();
ui.Image x = await decodeImageFromList(m);
ByteData bytes = await x.toByteData();
print('height is ${x.height}'); //height of original image
print('width is ${x.width}'); //width of oroginal image
print('array is $m');
print('original image size is ${bytes.lengthInBytes}');
ui.instantiateImageCodec(m, targetHeight: 800, targetWidth: 600)
.then((codec) {
codec.getNextFrame().then((frameInfo) async {
ui.Image i = frameInfo.image;
print('image width is ${i.width}');//height of resized image
print('image height is ${i.height}');//width of resized image
ByteData bytes = await i.toByteData();
File(path).writeAsBytes(bytes.buffer.asUint32List());
print('resized image size is ${bytes.lengthInBytes}');
});
});
Upvotes: 5
Reputation: 3327
You can use the Image widget in the Scaffold widget,
First of all you need to create assets folder in the root and add an images folder, after that add,
flutter:
assets:
- assets/images/
to the pubspec.yaml file, after that
new Image(
image: AssetImage('assets/images/pizzaFont.png'),
height: 12,
width:12, ......
)
You can use width and height to change the size of the image.
For more information follow,
https://medium.com/@suragch/how-to-include-images-in-your-flutter-app-863889fc0b29
Upvotes: -1
Reputation: 1088
Here's an example Thumbnail
widget which does this on the flight
It uses Isolate
to offload CPU-intensive work to background thread and have UI thread jank-free
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as IMG;
import 'package:path/path.dart';
class Thumbnail extends StatefulWidget {
final Size size;
final File image;
const Thumbnail({Key key, this.size, this.image}) : super(key: key);
@override
_ThumbnailState createState() => _ThumbnailState();
}
class _ThumbnailState extends State<Thumbnail> {
List<int> imgBytes;
Isolate isolate;
@override
void initState() {
_asyncInit();
super.initState();
}
static _isolateEntry(dynamic d) async {
final ReceivePort receivePort = ReceivePort();
d.send(receivePort.sendPort);
final config = await receivePort.first;
print(config);
final file = File(config['path']);
final bytes = await file.readAsBytes();
IMG.Image image = IMG.decodeImage(bytes);
IMG.Image thumbnail = IMG.copyResize(
image,
width: config['size'].width.toInt(),
);
d.send(IMG.encodeNamedImage(thumbnail, basename(config['path'])));
}
_asyncInit() async {
final ReceivePort receivePort = ReceivePort();
isolate = await Isolate.spawn(_isolateEntry, receivePort.sendPort);
receivePort.listen((dynamic data) {
if (data is SendPort) {
if (mounted) {
data.send({
'path': widget.image.path,
'size': widget.size,
});
}
} else {
if (mounted) {
setState(() {
imgBytes = data;
});
}
}
});
}
@override
void dispose() {
if (isolate != null) {
isolate.kill();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: widget.size.height,
width: widget.size.width,
child: imgBytes != null
? Image.memory(
imgBytes,
fit: BoxFit.cover,
)
: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.grey[100], Colors.grey[300]],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
),
),
);
}
}
Upvotes: 12
Reputation: 359
It's not a very good way to resize picture via Image library, since it blocks ui thread, and it brings very bad UX.
There is a a maxWidth
argument in image_picker
lib, you can set it, so these writing files manipulation will be unnecessary in some cases.
Upvotes: 15
Reputation: 4884
You can use the dart image
package: https://pub.dartlang.org/packages/image.
The package provide various services such as resize, crop and rotate.
While this package does work, unfortunately it is very slow.
See discussion: https://github.com/brendan-duncan/image/issues/55
Upvotes: 2
Reputation: 342
To resize an image that is defined in pubspec.yaml use "BoxFit":
@override
Widget build(BuildContext context) {
return (new Container(
width: 250.0,
height: 250.0,
alignment: Alignment.center,
decoration: new BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/Launcher_Icon.png'),
fit: BoxFit.fill
),
),
));
}
also reference how to access images: https://flutter.io/assets-and-images/
Upvotes: 14