Optimize Flutter Performance: Handle Heavy Image with Ease
SR
Sabin Ranabhat
Published February 22, 2024•4 min read


Recently, I came across a property in Flutter: debugInvertOversizedImages.
You might think, "What does it do?" Okay, let me answer you.
This property takes a boolean value, i.e., true or false; by default, it is false. If we make it true, then it will invert color and flip the images that are larger than their display size. With the help of this property, developers can easily stop oversized images on their app.
How do I enable the debugInvertOversizedImages property?
Go to your main.dart file. Inside the main method, add this line:
debugInvertOversizedImages = true;
I have added a high-resolution image to my assets, and below is my demo implementation.
Image.asset('assets/demo.jpg')
Now run your app. You can see all the oversized images being color-inverted and flipped by Flutter.
And if you check your logs, then you might see something like this:
EXCEPTION CAUGHT BY PAINTING LIBRARY
The following message was thrown while painting an image:
Image assets/demo. jpg has a display size of 1080×1439 but a decode size of 3688*4917, which uses an additional 86347KB (assuming a device pixel ratio of 2.625).
Consider resizing the asset ahead of time, supplying a cacheWidth parameter of 1080, a cacheHeight parameter of 1439, or using a ResizeImage.
Here, we are trying to load an image of 3688×4917, but actually, the display size is 1080×1493. And on the second line, we can see the solutions too.
Let’s try the first solution by adding the cacheHeight and cacheWidth parameters to the Image widget with the recommended dimensions provided by Flutter on the console.
Image.asset(
'assets/demo.jpg',
cacheHeight: 1439,
cacheWidth: 1080,
)
Voilà, now your image will be displayed perfectly fine.
Now, let’s try with ResizeImage
Before that, let's learn what ResizeImage is.
Flutter’s ResizeImage class allows you to specify the desired dimensions at which images are decoded and cached instead of their full dimensions without altering the original image file. By resizing images to appropriate dimensions, we can significantly reduce memory usage and improve image loading time.
Now replace Image.asset with AssetImage, as ResizeImage takes image providers only. And set width and height to the same values we have added previously. We cannot display ResizeImage directly, so let’s wrap it in the Image widget.
Image(
image: ResizeImage(
AssetImage('assets/demo.jpg'),
height: 1439,
width: 1080,
),
)
If both do the same thing, then what’s the difference? You might be wondering.
The cacheWidth and cacheHeight parameters of Image.asset are used for static resizing images before loading into the UI and remain the same for the whole lifetime of the app. The ResizeImage class is used for dynamic resizing of images at runtime and is generated every time the ImageProvider is used.
If you ask for my recommendation, I recommend you use the former one. Yes, cacheWidth and cacheHeight parameters of the Image widget. This can be used on Image.asset, Image.network, Image.file, and Image.memory.
What if you are using the cache_networked_image package instead of Image.network?
You can pass your desired dimension value to the memCacheHeight and memCacheWidth properties of the CachedNetworkImage class. If you are using the CachedNetworkImageProvider class, then you don’t have access to these properties. Instead, you should wrap it under ResizeImage.
Bonus: Dynamically determining image cache size by Extensions and MediaQuery class
The usage of ImageExtension is pretty simple.
extension ImageExtension on num {
int cacheSize(BuildContext context) {
return (this * MediaQuery.of(context).devicePixelRatio).round();
}
}
// Usage
Image.asset(
'assets/demo.jpg',
cacheHeight: 550.cacheSize(context),
cacheWidth: 410.cacheSize(context),
)
Conclusion
In this article, we explored how to load heavy images efficiently and optimize performance when displaying heavy images from assets and networks.
Links
Share this article:
Related Posts

Blog
December 31, 2025
The Art of Flutter Code Review: A Guide for Reviewers & Authors
Master the art of code review in Flutter. Learn how to balance human factors with technical rigor, ensuring code quality without sacrificing team morale.

Blog
December 31, 2025
Mastering Flutter Pull Requests: Best Practices & Standards
Learn best practices for submitting high-quality Flutter pull requests, including writing clear titles, crafting strong descriptions, and adhering to community standards.

Blog
December 16, 2025
Conventional Commits: A Guide to Meaningful Git History
Instead of writing vague messages like 'fixed bug' or 'updates', this convention provides a rigorous rule set for creating an explicit commit history. This makes it easier to understand *what* happened in a project and *why*, and it enables potent automation tools (like automatic changelogs and version bumping).

Blog
February 4, 2024
Exploring Parallelism on Flutter: Main Thread, Isolate and Compute
Understanding the nuances of main thread, isolates, and compute empowers you to make informed decisions about concurrency in your Flutter projects.
© 2026 Sabin Ranabhat