Hello can anyone tell me why the background to this masking attempt is black. This must be close but I just can't kill the background. I've seen others reference that saveLayer(rect, paint)
is the key here as that shoves the whole canvas rect in to the masking operation. This question (no masking operation) and this one (no actual answer) are similar but were no use to me.
main.dart
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ui.Image mask;
ui.Image image;
@override
void initState() {
super.initState();
load('images/squircle.png').then((i) {
setState(() {
mask = i;
});
});
load('images/noodlejpg.jpg').then((i) {
setState(() {
image = i;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Colors.blue, title: Text('I am a title')),
body: SafeArea(
child: SizedBox(
width: 200.0,
height: 200.0,
child: CustomPaint(painter: OverlayPainter(mask, image)),
),
),
);
}
Future<ui.Image> load(String asset) async {
ByteData data = await rootBundle.load(asset);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
ui.FrameInfo fi = await codec.getNextFrame();
return fi.image;
}
}
class OverlayPainter extends CustomPainter {
ui.Image mask;
ui.Image image;
OverlayPainter(this.mask, this.image);
@override
void paint(Canvas canvas, Size size) {
var paint = new Paint();
paint.isAntiAlias = true;
if (image != null) {
var rect = Rect.fromLTRB(0, 0, 200, 200);
Size outputSize = rect.size;
Size inputSize = Size(image.width.toDouble(), image.height.toDouble());
final FittedSizes fittedSizes =
applyBoxFit(BoxFit.cover, inputSize, outputSize);
final Size sourceSize = fittedSizes.source;
canvas.save();
final Rect sourceRect = Alignment.center.inscribe(
sourceSize,
Offset.zero & inputSize,
);
canvas.drawImageRect(image, sourceRect, rect, paint);
canvas.restore();
}
if (mask != null) {
var rect = Rect.fromLTRB(0, 0, 200, 200);
Size outputSize = rect.size;
Size inputSize = Size(mask.width.toDouble(), mask.height.toDouble());
final FittedSizes fittedSizes =
applyBoxFit(BoxFit.cover, inputSize, outputSize);
final Size sourceSize = fittedSizes.source;
canvas.saveLayer(rect, Paint()..blendMode = BlendMode.dstIn);
final Rect sourceRect = Alignment.center.inscribe(
sourceSize,
Offset.zero & inputSize,
);
canvas.drawImageRect(mask, sourceRect, rect, paint);
canvas.restore();
}
}
@override
bool shouldRepaint(OverlayPainter oldDelegate) {
return mask != oldDelegate.mask || image != oldDelegate.image;
}
}
noodlejpg.jpg
squircle.jpg
result