Repository navigation
DecorationImage with ColorFilter doesn't account for y-scale corrections in OpenGLES. #173162
Description
Steps to reproduce
Problem Description
When a ColorFilter is applied to a DecorationImage, it fails to respect the image's EXIF orientation metadata. This causes images, such as photos taken on mobile phones, to be rendered incorrectly (e.g., rotated sideways).
This behavior is inconsistent with the Image widget (and by extension, popular third-party widgets like CachedNetworkImage), which displays the exact same image with the correct orientation, even when wrapped in a ColorFiltered widget.
This inconsistency forces developers to use more complex widget structures (like stacking an Image widget behind content) instead of the more direct and performant DecorationImage, just to apply a simple color effect like an overlay.
The root cause seems to be that the rendering pipeline triggered when a ColorFilter is present on a DecorationImage does not include the logic to read and apply the EXIF orientation metadata before painting the image.
Steps to Reproduce
Here is a minimal, complete code sample that demonstrates the issue using the cached_network_image package and a real-world image URL known to contain EXIF rotation data.
1. Add dependency to pubspec.yaml:
dependencies:
flutter:
sdk: flutter
cached_network_image: ^3.3.1Expected results
Both images should be displayed in their correct, upright orientation. The DecorationImage should apply the color filter without altering the correct orientation of the image.
Actual results
The CachedNetworkImage widget displays the image correctly (upright).
The Container with DecorationImage and an applied ColorFilter displays the image incorrectly (rotated or upside down), ignoring the EXIF data.
Code sample
Code sample
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
const String exifRotatedImageUrl =
'https://firebasestorage.googleapis.com/v0/b/pacto-training-zone.appspot.com/o/gyms%2Fdefault%2Fimages%2Fimage13.jpg?alt=media&token=2cbe924a-6982-4c1d-9076-225c5c8d35df';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('EXIF Orientation Test'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Using DecorationImage with ColorFilter (Incorrect):',
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Container(
width: 250,
height: 250,
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 4),
image: DecorationImage(
fit: BoxFit.cover,
image: const CachedNetworkImageProvider(exifRotatedImageUrl),
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.3),
BlendMode.multiply,
),
),
),
),
const SizedBox(height: 32),
const Text(
'Using CachedNetworkImage Widget (Correct):',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
SizedBox(
width: 250,
height: 250,
child: CachedNetworkImage(
imageUrl: exifRotatedImageUrl,
fit: BoxFit.cover,
placeholder: (context, url) => const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
),
),
],
),
),
),
);
}
}Screenshots or Video
Logs
Logs
[Paste your logs here]Flutter Doctor output
[✓] Flutter (Channel stable, 3.32.8, on Ubuntu 24.04.2 LTS 6.14.0-27-generic, locale en_US.UTF-8) [194ms]
• Flutter version 3.32.8 on channel stable at /home/moovz-dell/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision edada7c56e (8 days ago), 2025-07-25 14:08:03 +0000
• Engine revision ef0cd00091
• Dart version 3.8.1
• DevTools version 2.45.1
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1) [4.1s]
• Android SDK at /home/moovz-dell/Android/Sdk
• Platform android-35, build-tools 35.0.1
• Java binary at: /snap/android-studio/197/jbr/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Chrome - develop for the web [30ms]
• Chrome at google-chrome
[✗] Linux toolchain - develop for Linux desktop [411ms]
• Ubuntu clang version 18.1.3 (1ubuntu1)
• cmake version 3.28.3
• ninja version 1.11.1
✗ pkg-config is required for Linux development.
It is likely available from your distribution (e.g.: apt install pkg-config), or can be downloaded from https://www.freedesktop.org/wiki/Software/pkg-config/
[✓] Android Studio (version 2025.1.1) [24ms]
• Android Studio at /snap/android-studio/197
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
[✓] Android Studio (version 2024.3) [20ms]
• Android Studio at /snap/android-studio/191
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13355223-b631.42)
[✓] VS Code (version unknown) [20ms]
• VS Code at /usr/share/code
• Flutter extension version 3.116.0
✗ Unable to determine VS Code version.
[✓] Connected device (3 available) [422ms]
• SM A125M (mobile) • RX8R70M9NEH • android-arm64 • Android 12 (API 31)
• Linux (desktop) • linux • linux-x64 • Ubuntu 24.04.2 LTS 6.14.0-27-generic
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.157
[✓] Network resources [552ms]
• All expected network resources are available.
! Doctor found issues in 2 categories.
[✓] Flutter (Channel stable, 3.32.8, on Ubuntu 24.04.2 LTS 6.14.0-27-generic, locale en_US.UTF-8) [194ms]
• Flutter version 3.32.8 on channel stable at /home/moovz-dell/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision edada7c56e (8 days ago), 2025-07-25 14:08:03 +0000
• Engine revision ef0cd00091
• Dart version 3.8.1
• DevTools version 2.45.1
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1) [4.1s]
• Android SDK at /home/moovz-dell/Android/Sdk
• Platform android-35, build-tools 35.0.1
• Java binary at: /snap/android-studio/197/jbr/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Chrome - develop for the web [30ms]
• Chrome at google-chrome
[✗] Linux toolchain - develop for Linux desktop [411ms]
• Ubuntu clang version 18.1.3 (1ubuntu1)
• cmake version 3.28.3
• ninja version 1.11.1
✗ pkg-config is required for Linux development.
It is likely available from your distribution (e.g.: apt install pkg-config), or can be downloaded from https://www.freedesktop.org/wiki/Software/pkg-config/
[✓] Android Studio (version 2025.1.1) [24ms]
• Android Studio at /snap/android-studio/197
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
[✓] Android Studio (version 2024.3) [20ms]
• Android Studio at /snap/android-studio/191
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13355223-b631.42)
[✓] VS Code (version unknown) [20ms]
• VS Code at /usr/share/code
• Flutter extension version 3.116.0
✗ Unable to determine VS Code version.
[✓] Connected device (3 available) [422ms]
• SM A125M (mobile) • RX8R70M9NEH • android-arm64 • Android 12 (API 31)
• Linux (desktop) • linux • linux-x64 • Ubuntu 24.04.2 LTS 6.14.0-27-generic
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.157
[✓] Network resources [552ms]
• All expected network resources are available.
! Doctor found issues in 2 categories.Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone

Activity
MachadoJorgeH commentedon Aug 2, 2025
Proposal
The developer experience would be more consistent if the rendering pipeline for DecorationImage correctly handled EXIF orientation even when a ColorFilter is applied. The current behavior forces developers to abandon DecorationImage for a more complex widget stack just to apply a simple filter.
The proposed solution is for the DecorationImage pipeline to apply the EXIF orientation transformation before applying the ColorFilter, thus preserving the correct orientation.
Alternatively, if this is not feasible due to performance or architectural constraints, the official documentation for both DecorationImage and ColorFilter should be updated to explicitly warn about this limitation.
chinmaygarde commentedon Aug 11, 2025
Triage: From the engine perspective, things don't quite add up. The images have to be decompressed and the EXIF orientation is accounted for during that decompression step, and not during rendering. We are wondering if this is happening only on the OpenGL backend and some paths not accounting for the Y-Flip. A way to reproduce this would be to verify if this is working correctly with the Vulkan backend on Android or just iOS.
chinmaygarde commentedon Aug 11, 2025
@justinmc I'm applying the engine tag for a bit while we investigate.
chinmaygarde commentedon Aug 11, 2025
cc @jason-simmons is going to take a stab at reproducing this on the other backends.
18 remaining items
[-][Proposal] DecorationImage with ColorFilter incorrectly handles EXIF orientation[/-][+]DecorationImage with ColorFilter doesn't account for y-scale corrections in OpenGLES.[/+][Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…
github-actions commentedon Aug 26, 2025
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.[Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…
[Impeller] Apply Y coordinate scaling when sampling from the destinat…