This tutorial shows you how to load image from a local file in Flutter using Image.File
and FileImage
.
Sometimes an application needs to be able to display images from files. In Flutter, displaying an image can be done by using Image
widget. Flutter provides a named constructor File.Image
which can be used if the image source is from a file. Alternatively, you can also use FileImage
. The usage examples can be found in this tutorial.
Handle Permission
To access a file in storage, the app needs to have the permission to read storage. Otherwise the user will get a permission error unless the file is located in the app's directory. The easiest way to handle permission is by using a 3rd party package such as permission_handler
. First, add the package in the dependencies
section of pubspec.yaml
permission_handler: ^5.1.0+2
After running flutter pub get
(or click on 'Packages get' in Android Studio), the package can be used by adding this import statement.
import 'package:permission_handler/permission_handler.dart';
Below is a code sample to handle storage permission.
initState() {
super.initState();
() async {
_permissionStatus = await Permission.storage.status;
if (_permissionStatus != PermissionStatus.granted) {
PermissionStatus permissionStatus= await Permission.storage.request();
setState(() {
_permissionStatus = permissionStatus;
});
}
} ();
}
Using Image.File
Below is the named constructeor Image.File
.
Image.file(
File file, {
Key? key,
double scale = 1.0,
this.frameBuilder,
this.errorBuilder,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.isAntiAlias = false,
this.filterQuality = FilterQuality.low,
int? cacheWidth,
int? cacheHeight,
})
The basic usage only requires you to pass an argument which is an instance of File
. In addition, you are not allowed to pass null
value for scale
and repeat
arguments (just keep the default value if you don't want to set it).
Below is a basic example that only passes the file
argument. No size constraints applied to the widget and the actual size of the used image (the width) is bigger than the available space.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
)
Output:
As you can see from the output, the default behavior is the image is scaled down so that it can fit in the available space. The next examples in this tutorial show you how to customize how the image should be rendered.
Set Width and Height
You can set the width and the height of the loaded image by passing width
and height
named arguments respectively.
The below example sets both width and height values to 100.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
)
Output:
Set Fit
If you set the image to be a specified size, sometimes the image may not fit in the available space. In that case, you may need to set how the image should be inscribed to the space. To do so, pass a BoxFit
enum value as fit
argument. We have a post about FittedBox
which shows the differences between the BoxFit
enum values.
The below example uses BoxFit.fill
, which fills the target box by distorting the source's aspect ratio.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
fit: BoxFit.fill,
)
Output:
Set Alignment
To set how the image should be aligned in the space, pass a named argument alignment
. You can use Alignment
value or create a custom alignment using the constructor of Alignment
.
The code below sets the alignment to topCenter
.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
alignment: Alignment.topCenter,
)
Output:
Set Repeat Mode
If the image doesn't fill all the available space, you can make it repeated by passing repeat
argument. The value is an enum of ImageRepeat
whose possible values are:
repeat
: Repeat the image in both the x and y directions until the box is filled.repeatX
: Repeat the image in the x direction until the box is filled horizontally.repeatY
: Repeat the image in the y direction until the box is filled vertically.noRepeat
: Leave uncovered portions of the box transparent.
If you don't pass the argument, the default value is ImageRepeat.noRepeat
. The code below uses ImageRepeat.repeat
. Since the box is already filled horizontally, it only repeats in the y direction.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
repeat: ImageRepeat.repeat,
)
Output:
Blend Image With Color
You can set a color to be blended with each pixel by passing color
argument. How to blend the color with the image can be set by passing colorBlendMode
argument. The BlendMode
mode enum has so many values you can choose.
The example below blends the image with red color using saturation mode.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
color: Colors.red,
colorBlendMode: BlendMode.saturation
)
Output:
Set Scale
The scale
argument is used to set how many image pixels for every one logical pixel. It applies to both width and height. For example, if the scale
is 2, there are 4 image pixels per one logical pixel. Thus, if you create an Image.File
with a scale
of 4, the rendered width and height will be half as big as having a scale
value of 2. That's because a logical pixel contains more image pixels.
Below is an example which sets the scale
argument to 4.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
scale: 4,
)
Output:
Using Error Builder
An error may occur while trying to load an image from a file, for example if the file doesn't exist or if the app doesn't have the storage permission. You can handle it by displaying another widget. It can be done by passing a function as errorBuilder
. The function returns a Widget
and has the following parameters:
BuildContext context
: The build context.Object error
: The error object.StackTrace stackTrace
: The stack trace.
The code below shows a Container
widget with 'Error load image' text inside if the image cannot be loaded successfully.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
return Container(
color: Colors.grey,
width: 100,
height: 100,
child: const Center(
child: const Text('Error load image', textAlign: TextAlign.center),
),
)
},
)
Output:
Using Frame Builder
You can pass a function as frameBuilder
to customize how the image should be rendered. The function which must return a Widget
has the following parameters:
BuildContext context
: The build context.Widget child
: The default image.int frame
: The current frame number. It will be null before the first image is ready. If the image only has one frame, the value can't be greater than 0. For multi-frame images (such as GIFs), the value will be increased by one for every frame.bool wasSynchronouslyLoaded
: whether the image was available synchronously and available to be painted immediately. For multi-frame images (such as images), the value for all frames will betrue
after the first image available.
Below is an example that adds a border around the image.
Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
frameBuilder: (
BuildContext context,
Widget child,
int frame,
bool wasSynchronouslyLoaded,
) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 5),
),
child: child,
);
},
)
Output:
Image.File
Parameters
File file
*: The file to be loaded as an image.Key key
: The widget's key, used to control how a widget is replaced with another widget.double scale
: A linear scale factor for drawing this image at its intended size, applies to both width and height. Defaults to 1.0.ImageFrameBuilder frameBuilder
: A builder function responsible for creating the widget that represents this image..ImageErrorWidgetBuilder errorBuilder
: A builder function that is called if an error occurs during image loading.String semanticLabel
: A Semantic description of the image.bool excludeFromSemantics
: Whether to exclude this image from semantics. Defaults tofalse
.double width
: If non-null, require the image to have this width.double height
: If non-null, require the image to have this height.Color color
: If non-null, this color is blended with each image pixel usingcolorBlendMode
.BlendMode colorBlendMode
: How to combinecolor
with the image.BoxFit fit
: How to inscribe the image into the space allocated during layout.AlignmentGeometry alignment
: How to align the image within its bounds. Defaults toAlignment.center
.ImageRepeat repeat
: How to paint any portions of the layout bounds not covered by the image. Defaults toImageRepeat.noRepeat
.Rect centerSlice
: The center slice for a nine-patch image.bool matchTextDirection
: Whether to paint the image in the direction of theTextDirection
. Defaults tofalse
.bool gaplessPlayback
: Whether to continue showing the old image (if true) or briefly show nothing (if alse) when the image provider changes. Defaults tofalse
.bool isAntiAlias
: Whether to paint the image with anti-aliasing. Defaults tofalse
.FilterQuality filterQuality
: Used to set theFilterQuality
of the image. Defaults toFilterQuality.low
.int cacheWidth
: The width size at which the image must be decoded.int cacheHeight
: The height size at which the image must be decoded.
*: required
Using FileImage
FileImage
is a class that extends ImageProvider
. It's not a widget, so you can't use it directly. You can pass it as the ImageProvider
of an Image
widget. Below is the constructor of FileImage
.
const FileImage(this.file, { this.scale = 1.0 })
It's required to pass the file
argument whose type is File
. There is an optional named argument scale
whose default value is 1.0. The scale
argument has the same usage as the one on Image.File
. Below is a usage example of FileImage
which also passes the optional scale
argument.
Image(
image: FileImage(
File('/storage/emulated/0/Download/test.jpg'),
scale: 4
),
)
Output:
FileImage
Parameters
File file
*: The file to be loaded as an image.double scale
: A linear scale factor for drawing this image at its intended size, applies to both width and height. Defaults to 1.0.
*: required
Full Code
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:permission_handler/permission_handler.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Woolha.com Flutter Tutorial',
home: Scaffold(
appBar: AppBar(
title: const Text('Woolha.com | ImageFile Example'),
backgroundColor: Colors.teal,
),
body: FileImageExample(),
),
);
}
}
class FileImageExample extends StatefulWidget {
@override
_FileImageExampleState createState() => _FileImageExampleState();
}
class _FileImageExampleState extends State<FileImageExample> {
PermissionStatus _permissionStatus;
initState() {
super.initState();
() async {
_permissionStatus = await Permission.storage.status;
if (_permissionStatus != PermissionStatus.granted) {
PermissionStatus permissionStatus= await Permission.storage.request();
setState(() {
_permissionStatus = permissionStatus;
});
}
} ();
}
@override
Widget build(BuildContext context) {
if (_permissionStatus != PermissionStatus.granted) {
return Text('Not granted');
}
return Image.file(
File('/storage/emulated/0/Download/test.jpg'),
width: 100,
height: 100,
fit: BoxFit.fill,
repeat: ImageRepeat.repeat,
alignment: Alignment.topCenter,
color: Colors.red,
colorBlendMode: BlendMode.saturation,
// scale: 4,
errorBuilder: (
BuildContext context,
Object error,
StackTrace stackTrace,
) {
print(error);
print(stackTrace);
return Container(
color: Colors.grey,
width: 100,
height: 100,
child: const Center(
child: const Text('Error load image', textAlign: TextAlign.center),
),
);
},
frameBuilder: (
BuildContext context,
Widget child,
int frame,
bool wasSynchronouslyLoaded,
) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 5),
),
child: child,
);
},
);
// return Image(
// image: FileImage(
// File('/storage/emulated/0/Download/test.jpg'),
// scale: 4
// ),
// );
}
}
Summary
That's how to load image from file in Flutter. You can use Image.File
or FileImage
. You can also read our tutorial about: