Skip to content

Instantly share code, notes, and snippets.

@flar
Last active January 23, 2021 00:12
Show Gist options
  • Save flar/d30027c001a812ae7f3f4d2ca1aa8fd3 to your computer and use it in GitHub Desktop.
Save flar/d30027c001a812ae7f3f4d2ca1aa8fd3 to your computer and use it in GitHub Desktop.
Workaround for Image widget not applying the filter quality unless you force it to change size via the "fit" operation
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(ImageTestApp());
}
class ImageTestApp extends StatefulWidget {
@override
State createState() => ImageTestAppState();
}
class ImageTestAppState extends State<ImageTestApp> {
final isCanvasKit = const bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false);
bool padTweak = false;
bool boxTweak = false;
Map<String, ui.Image> uiImages = {};
@override
void initState() {
super.initState();
_loadImages();
}
Future<void> _loadImages() async {
await _loadImage('images/sample.png');
await _loadImage('images/sample2.png');
await _loadImage('images/sample3.png');
setState(() async {
});
}
Future<void> _loadImage(String imageFile) async {
ByteData bd = await rootBundle.load(imageFile);
final Uint8List bytes = Uint8List.view(bd.buffer);
final ui.Codec codec = await ui.instantiateImageCodec(bytes);
final ui.Image image = (await codec.getNextFrame()).image;
uiImages[imageFile] = image;
}
Widget tweakedImage(ImageProvider provider, FilterQuality quality, Size size) {
Image image = Image(
image: provider,
filterQuality: quality,
fit: BoxFit.fill,
width: padTweak ? size.width + 0.001 : null,
height: padTweak ? size.height + 0.001 : null,
);
if (!boxTweak) return image;
return SizedBox(
width: size.width + 0.001,
height: size.height + 0.001,
child: image,
);
}
Widget wrap(String imageFile, Size size) {
ImageProvider provider = AssetImage(imageFile);
return Row(
children: <Widget>[
tweakedImage(provider, FilterQuality.none, size),
tweakedImage(provider, FilterQuality.low, size),
tweakedImage(provider, FilterQuality.high, size),
if (uiImages[imageFile] != null)
CustomPaint(
painter: _ImagePainter(uiImages[imageFile], FilterQuality.none),
child: SizedBox(width: size.width, height: size.height,),
),
if (uiImages[imageFile] != null)
CustomPaint(
painter: _ImagePainter(uiImages[imageFile], FilterQuality.low),
child: SizedBox(width: size.width, height: size.height,),
),
if (uiImages[imageFile] != null)
CustomPaint(
painter: _ImagePainter(uiImages[imageFile], FilterQuality.high),
child: SizedBox(width: size.width, height: size.height,),
),
],
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Container(
child: Container(
padding: const EdgeInsets.all(8.0),
width: double.infinity,
child: Column(
crossAxisAlignment: isCanvasKit ? CrossAxisAlignment.start : CrossAxisAlignment.end,
children: <Widget>[
Text(isCanvasKit ? 'CanvasKit' : 'HTML'),
Row(
children: [
Text('Pad Image size tweak: '),
Checkbox(value: padTweak, onChanged: (value) => setState(() { padTweak = value; }),),
SizedBox(width: 20),
Text('SizedBox tweak: '),
Checkbox(value: boxTweak, onChanged: (value) => setState(() { boxTweak = value; }),),
],
),
SizedBox(height: 20),
wrap('images/sample2.png', Size(200, 200)),
wrap('images/sample.png', Size(100, 100)),
wrap('images/sample3.png', Size(60, 60)),
],
),
),
),
),
);
}
}
class _ImagePainter extends CustomPainter {
_ImagePainter(this.image, this.filterQuality);
final ui.Image image;
final FilterQuality filterQuality;
@override
void paint(Canvas canvas, Size size) {
canvas.drawImage(image, Offset.zero, Paint()..filterQuality = filterQuality);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment