New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RenderRepaintBoundary.toImage bad quality #21269
Comments
Can you please try in a newer Flutter version like the newest |
Same issue here. The screenshot got pixelated.
|
@zoechi doctor
|
The original issue here is easily fixed when using pixelratio to capture a bigger image. As for the second issue. But this issue seems to have been fixed recently. I've tested this with the newest version of flutter with multiple devices and the capture has not failed. |
Picture.toImage() will generate bad quality too. Future<ui.Image> _clipImage(ui.Image originImage, Offset blockCenter,
Size canvasSize, Size blockSize) async {
DefaultCaptchaStrategy strategy = DefaultCaptchaStrategy();
Path blockShape = strategy.getBlockShape(blockCenter, blockSize);
ui.PictureRecorder recorder = ui.PictureRecorder();
Canvas canvas = Canvas(
recorder, Rect.fromLTWH(0, 0, canvasSize.width, canvasSize.height));
canvas.translate(
blockSize.width - blockCenter.dx, blockSize.height - blockCenter.dy);
canvas.clipPath(blockShape);
ImageUtil.paintImage(
originImage, Offset.zero & canvasSize, canvas, Paint(), BoxFit.fill);
Paint paint = Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 3;
canvas.drawPath(blockShape, paint);
ui.Picture picture = recorder.endRecording();
double imageWidth = blockSize.width * 2;
double imageHeight = blockSize.height * 2;
final pngBytes = await picture
.toImage(imageWidth.ceil(), imageHeight.ceil())
.toByteData(format: ui.ImageByteFormat.png);
var codec = await ui.instantiateImageCodec(pngBytes.buffer.asUint8List());
var frame = await codec.getNextFrame();
return frame.image;
} |
Increase pixelRatio should improve the image quality |
Thank You.. Works fine |
This is working as expected on the lastes master flutter doctor -v
Here is a sample to play around with Complete code sampleimport 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var globalKey = GlobalKey();
Uint8List bytes;
BuildContext localContext;
double ratio = 1.0;
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: globalKey,
child: MaterialApp(
title: 'Sample',
home: Builder(
builder: (ctx) {
localContext = ctx;
return Scaffold(
appBar: AppBar(
title: const Text("Logical pixels vs image size"),
),
body: Center(
child: GestureDetector(
onTap: () async {
await _capturePng();
Navigator.push(
localContext,
MaterialPageRoute(
builder: (BuildContext context) {
Image image = Image.memory(bytes);
image.image.resolve(new ImageConfiguration()).addListener(
new ImageStreamListener(
(ImageInfo imgInf, _) => print("Created screenshot with resolution ${imgInf.image.width}x${imgInf.image.height}"),
),
);
return Stack(
children: [
image,
Container(
padding: EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.green,
width: 3.0,
),
),
),
],
);
},
),
);
},
child: Container(
width: 300,
height: 300,
color: Colors.orange,
alignment: Alignment.center,
child: const Text("Tap to screenshot!"),
),
),
),
bottomNavigationBar: Container(
height: 100,
child: Card(
child: Column(
children: [
Row(
children: [
Flexible(
child: Slider(
value: ratio,
min: 1.0,
max: 8.0,
onChanged: (value) {
setState(() => ratio = value);
},
),
),
RaisedButton(
child: const Text("Use device\npixel ratio", textAlign: TextAlign.center),
onPressed: () => setState(() => ratio = ui.window.devicePixelRatio),
),
],
),
Text("pixelRatio: ${ratio.toStringAsFixed(2)}"),
Text("Screenshot resolution: ${getScreenshotRes()}")
],
),
),
),
);
},
),
),
);
}
String getScreenshotRes() {
var size = MediaQuery.of(localContext).size;
return "${(size.width * ratio).ceil()}x${(size.height * ratio).ceil()}";
}
Future<void> _capturePng() async {
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage(pixelRatio: ratio);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
setState(() => bytes = byteData.buffer.asUint8List());
}
} To understand the difference between logical and physical pixels see devicePixelRatio. |
this work for me, thanks |
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 |
The method of my screenshot is like this, but the screenshots I got are of poor quality. What went wrong?
The widget
The screenshot
flutter doctor
The text was updated successfully, but these errors were encountered: