Repository navigation
Description
@iskakaushik asked me to post this as a separate issue from #48885.
When using the cacheWidth and cacheHeight parameters, the resulting image has less details than without using the parameters, although they are set to the same values as the image's width and height.
I was under the assumption that if I supply the same values to the cacheWidth / cacheHeight parameters as I do to the width / height parameters, then the quality should be exactly the same, but the cache uses the given dimensions instead of a possibly much larger native size. I thought the cache parameters are basically just a way to tell the engine that I will never draw the image in a higher resolution, so it is ok to cache it at the specified resolution in order to reduce memory footprint.
However, as the pictures below show, when using the cache parameters, the image gets drawn in less quality, which is especially visible on the edges (e.g. compare the e or the a).
Comparison pictures:
I stumbled upon this with a real picture in my app (that I can't share) and was wondering why it renders with these artifacts and found by chance that the artifacts are gone when I don't use the cache parameters. I originally noticed this on a Pixel 2, but the screenshots were taken from Android Emulator, where it is also clearly visible.
Sample code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(appBar: AppBar(title: Text('Test')),
backgroundColor: Colors.black,
body: Image.asset(
'assets/test.png',
width: 200,
height: 200,
cacheWidth: 200,
cacheHeight: 200,
),
),
);
}
}
Source Image:
Logs
[ +40 ms] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git -c
log.showSignature=false log -n 1 --pretty=format:%H
[ +58 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%H
[ ] 0b8abb4724aa590dd0f429683339b1e045a1594d
[ ] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git describe --match
v*.*.* --first-parent --long --tags
[ +8 ms] Exit code 0 from: git describe --match v*.*.* --first-parent --long --tags
[ ] v1.12.13+hotfix.8-0-g0b8abb472
[ +5 ms] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git rev-parse
--abbrev-ref HEAD
[ +7 ms] Exit code 0 from: git rev-parse --abbrev-ref HEAD
[ ] stable
[ +36 ms] Artifact Instance of 'AndroidMavenArtifacts' is not required, skipping update.
[ +3 ms] Artifact Instance of 'AndroidInternalBuildArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'IOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterWebSdk' is not required, skipping update.
[ +2 ms] Artifact Instance of 'WindowsEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxEngineArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'LinuxFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'MacOSFuchsiaSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerSDKArtifacts' is not required, skipping update.
[ ] Artifact Instance of 'FlutterRunnerDebugSymbols' is not required, skipping update.
[ +26 ms] executing: /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped/jre/bin/java -version
[ +110 ms] Exit code 0 from: /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped/jre/bin/java
-version
[ +2 ms] openjdk version "1.8.0_212-release"
OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
OpenJDK 64-Bit Server VM (build 25.212-b4-5784211, mixed mode)
[ +11 ms] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git rev-parse
--abbrev-ref --symbolic @{u}
[ +7 ms] Exit code 0 from: git rev-parse --abbrev-ref --symbolic @{u}
[ ] origin/stable
[ ] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git ls-remote
--get-url origin
[ +7 ms] Exit code 0 from: git ls-remote --get-url origin
[ ] https://github.com/flutter/flutter.git
[ +19 ms] executing: [/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped/] git -c
log.showSignature=false log -n 1 --pretty=format:%ar
[ +8 ms] Exit code 0 from: git -c log.showSignature=false log -n 1 --pretty=format:%ar
[ ] 3 months ago
[ +14 ms] executing: /home/nion/.cache/flutter/artifacts/engine/android-arm-profile/linux-x64/gen_snapshot
[ +16 ms] Exit code 255 from: /home/nion/.cache/flutter/artifacts/engine/android-arm-profile/linux-x64/gen_snapshot
[ ] At least one input is required
Usage: gen_snapshot [<vm-flags>] [<options>] <dart-kernel-file>
Common options:
--help
Display this message (add --verbose for information about all VM options).
--version
Print the VM version.
To create a core snapshot:
--snapshot_kind=core
--vm_snapshot_data=<output-file>
--isolate_snapshot_data=<output-file>
<dart-kernel-file>
To create an AOT application snapshot as assembly suitable for compilation
as a static or dynamic library:
--snapshot_kind=app-aot-assembly
--assembly=<output-file>
[--obfuscate]
[--save-obfuscation-map=<map-filename>]
<dart-kernel-file>
To create an AOT application snapshot as an ELF shared library:
--snapshot_kind=app-aot-elf
--elf=<output-file>
[--strip]
[--obfuscate]
[--save-obfuscation-map=<map-filename>]
<dart-kernel-file>
AOT snapshots can be obfuscated: that is all identifiers will be renamed
during compilation. This mode is enabled with --obfuscate flag. Mapping
between original and obfuscated names can be serialized as a JSON array
using --save-obfuscation-map=<filename> option. See dartbug.com/30524
for implementation details and limitations of the obfuscation pass.
[ +11 ms] executing: /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped/jre/bin/java -version
[ +45 ms] Exit code 0 from: /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped/jre/bin/java
-version
[ ] openjdk version "1.8.0_212-release"
OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
OpenJDK 64-Bit Server VM (build 25.212-b4-5784211, mixed mode)
[ +2 ms] java -version
⣽[ +124 ms] executing: /home/nion/opt/android-sdk/platform-tools/adb devices -l
[ +7 ms] Exit code 0 from: /home/nion/opt/android-sdk/platform-tools/adb devices -l
[ ] List of devices attached
192.168.1.31:5555 device product:walleye model:Pixel_2 device:walleye transport_id:17
emulator-5554 device product:sdk_phone_x86 model:Android_SDK_built_for_x86 device:generic_x86 transport_id:20 [ +6 ms] [✓] Flutter (Channel stable, v1.12.13+hotfix.8, on Linux, locale en_US.UTF-8)
[ +1 ms] • Flutter version 1.12.13+hotfix.8 at
/nix/store/bxyz9r12vvlg2n37kmpk2rqjxi4s70gj-flutter-stable-1.12.13+hotfix.8-unwrapped
[ +1 ms] • Framework revision 0b8abb4724 (3 months ago), 2020-02-11 11:44:36 -0800
[ ] • Engine revision e1e6ced81d
[ ] • Dart version 2.7.0
⣽[ +11 ms] /home/nion/opt/android-sdk/platform-tools/adb -s 192.168.1.31:5555 shell getprop
[ +65 ms] executing: /home/nion/opt/android-sdk/tools/bin/sdkmanager --licenses ⢿[ +211 ms] ro.hardware = walleye
[ ] ro.build.characteristics = nosdcard
[ +1 ms] /home/nion/opt/android-sdk/platform-tools/adb -s emulator-5554 shell getprop ⡿[ +83 ms] ro.hardware = ranchu ⣯
[+3572 ms] [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[ ] • Android SDK at /home/nion/opt/android-sdk
[ ] • Android NDK location not configured (optional; useful for native profiling support)
[ ] • Platform android-29, build-tools 29.0.3
[ ] • ANDROID_HOME = /home/nion/opt/android-sdk
[ ] • Java binary at: /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped/jre/bin/java
[ ] • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
[ ] • All Android licenses accepted.
[ ] [✓] Android Studio (version 3.6)
[ ] • Android Studio at /nix/store/mgb6pwg4r24l2y7qxfz9l4bfmn4p335i-android-studio-stable-3.6.3.0-unwrapped
[ ] • Flutter plugin version 45.0.1
[ ] • Dart plugin version 192.7761
[ ] • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
[ ] [✓] Connected device (2 available)
[ ] • Pixel 2 • 192.168.1.31:5555 • android-arm64 • Android 10 (API 29)
[ ] • Android SDK built for x86 • emulator-5554 • android-x86 • Android 10 (API 29) (emulator)
[ ] • No issues found!
[ +7 ms] "flutter doctor" took 4,508ms.



Activity
[-]`cacheWidth` / `cacheHeight` degrading image quality[/-][+]cacheWidth / cacheHeight degrade image quality[/+][-]cacheWidth / cacheHeight degrade image quality[/-][+]Specifying cacheWidth / cacheHeight can degrade the image quality[/+]davidmartos96 commentedon May 8, 2020
I'd like to share a sample with a more detailed image as I think is much more noticeable than the provided one.
Source image from Unsplash
I have also tried multiplying the cache dimension by the devicePixelRatio and it looks much better, but I don't know if that is really the issue.
Here is the comparison (Flutter 1.17.0)
Without devicePixelRatio
With devicePixelRatio
pedromassangocode commentedon Dec 8, 2020
Reproducible on latest
stablechannel.Code
flutter doctor -v
off cacheHeight of Image.asset. See: flutter/flutter#56239
Board UI, first (#21)
Оптимизировал виджет аватара. Теперь можно использовать его без объек…
lucascardo12 commentedon May 13, 2022
I have the same problem on some phones the quality is perfect but on some phones it is pixelated
maRci002 commentedon Feb 9, 2023
Flutter's (
3.7.2) current documentation for Image:Flutter documentation should be updated since
Image.width/Image.heightuses logical pixels whileImage.cacheWidth/Image.cacheHeightuses physical pixels.See @davidmartos96 #56239 (comment) example.
8 remaining items
maRci002 commentedon Jun 28, 2023
This solution can be dangerous because if the widget changes its size, for instance, if the user resizes the window, you would ask the image provider to decode the image every frame and cache it.
I think the best solution is generate multiple resolutions of the image, then you choose the best image:
Then call it
ranulfo commentedon Jun 28, 2023
this time it was not very clear to me. how can i set the initial values for
landscapeImages?, i did it like this:and it didn't work
maRci002 commentedon Jun 28, 2023
Example code
YouTube API is very similar
Output:
ranulfo commentedon Jun 28, 2023
thank you for everything. this solution will be more work because I will have to resize and record new images on the server side. while the distortion generated that i mentioned in the previous comment, do you have any suggestion how to solve it?
maRci002 commentedon Jun 29, 2023
Maybe by finding the closest image and not resizing it (for example, not passing
memCacheWidth), you can solve your issue. Perhaps passingimageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGettoCachedNetworkImagewill also solve the problem.distortion maybe caused by #122541
Xim-ya commentedon Nov 14, 2023
I have referenced this issue and organized related content for a blog post titled "Save Your Memory Usage By Optimizing Network Image in Flutter."
The post includes concepts of resizing images and methods for dynamically setting cache values based on the image layout.
For anyone who is interested, please take a look.
ebwood commentedon Jan 8, 2024
@Xim-ya Does any solution to solve the problem like issue #52802?
Says the original image size is 1000*1500, image widget size is 100 * 100,
the resize image size will be 100 * 150,
debugInvertOversizedImageswill complain about oversize.add `cacheWidth: 100 * MediaQuery.of(context).devicePixelRatio.round()' will distort image.
Is there any solution to crop image from 100*150 to 100 * 100 in memory to avoid the oversize complain?
AndreiMisiukevich commentedon May 13, 2025
devicePixelRatio works incorrectly on mac retina
it returns 2, and image looks degraded
gaganyadav80 commentedon Aug 20, 2025
If anyone facing issue where providing both
cacheHeightandcacheWidthdoes not respectboxFit, then you can fix it using the below code:Add useLogicalPixels to ResizeImage for logical pixel cache sizing (f…
github-actions commentedon Sep 2, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.