Add toImage to RenderRepaintBoundary#16758
Conversation
13717d2 to
28caa4d
Compare
573b758 to
6ef6eb7
Compare
There was a problem hiding this comment.
Don't say "multiplied by the [window.devicePixelRatio]" since it's covered below in the discussion of the [pixelRatio] named parameter?
There was a problem hiding this comment.
Yeah, sorry, I guess that's irrelevant now that I added pixelRatio.
There was a problem hiding this comment.
the render object must not need layout, painting, or compositing
How does the caller know whether this is the case?
Also, can we assert it below?
There was a problem hiding this comment.
Added asserts, and an explanation.
There was a problem hiding this comment.
Where is anti-aliasing usually done when the render object is drawn to the screen?
There was a problem hiding this comment.
I think it's antialiased at the device level (in the GPU), but since the engine downsamples it with nearest neighbor, anything smaller than the device resolution is not effectively antialiased. At least I think that's the case, and Jason says that it can actually take one of several paths in the engine, so it's not really clear to me when it happens. I decided to take out the advice: they can look at the result and decide for themselves to increase the size or not.
There was a problem hiding this comment.
I don't really understand how we're actually rendering this, but I would presume we're just uploading the whole scene to the GPU, having it render to a texture, then grabbing the texture? In which case I'd expect antialiasing to work fine?
cc @jason-simmons or @chinmaygarde
There was a problem hiding this comment.
Yeah, what @Hixie said. We have to render to texture on the GPU first because the scene may reference images that are only resident on the GPU. AA should work just fine.
There was a problem hiding this comment.
Does this have to be [ui.Scene.toImage]?
There was a problem hiding this comment.
Yes, but I wasn't sure if dartdoc would pick it up correctly or not if I did that.
There was a problem hiding this comment.
search for [ui. or [dart:ui. and compare to actual output, I forget which one is the right one.
There was a problem hiding this comment.
Is it worth optimizing out this matrix multiply for the case where pixelRatio is 1.0?
There was a problem hiding this comment.
No, not really. From what I can tell, calling Matrix4.identity() is slower than the diagonal3Values call.
There was a problem hiding this comment.
try/finally with a call to scene.dispose() in the finally?
There was a problem hiding this comment.
Good call. Added.
There was a problem hiding this comment.
Add a test that expects our assertion error if the render object isn't a repaint boundary?
There was a problem hiding this comment.
No, we don't usually test asserts as far as I can tell, and if my call doesn't assert, then the layer getter will.
There was a problem hiding this comment.
we do test asserts sometimes (check for takeException), but this point will be moot anyway if you move it to RenderRepaintBoundary.
15bce3f to
ebf0fb8
Compare
There was a problem hiding this comment.
To avoid people depending on particular widgets that happen to be repaint boundaries but might not always be, I recommend putting this on RenderRepaintBoundary.
There was a problem hiding this comment.
Yeah, I guess that makes sense. It means that they'll have to cast the result when they get the render object in order to call this function, but that's not horrible.
There was a problem hiding this comment.
paintBounds is a bit of a dubious choice because it's just advisory really.
If you move this to RenderRepaintBoundary, you can just use size, which is much more authoritative.
There was a problem hiding this comment.
We should replace "dimensions" with the actual property that we use to determine the dimensions (currently [paintBounds], though if you take my feedback below, [size]).
There was a problem hiding this comment.
OK, size it is.
There was a problem hiding this comment.
rather than "must not need painting" it might be more positive to say "must have gone through the paint phase" or some such (the parenthetical is fine though)
There was a problem hiding this comment.
rather than using multiplied() and allocating a new matrix, you can just use translate.
There was a problem hiding this comment.
Good idea. Done.
There was a problem hiding this comment.
I wonder if we should change toImage to just take a Size... cc @tvolkert
There was a problem hiding this comment.
For the use cases we've heard for this, I don't have a strong opinion either way.
There was a problem hiding this comment.
You should add a test that verifies that it works (gives the right pixels) with two layers, since that was a bug.
3675e9a to
d162ccc
Compare
09eeb2b to
681a657
Compare
|
I tried this out in a simple widget test: testWidgets('test', (WidgetTester tester) async {
await tester.pumpWidget(new MyApp());
RenderRepaintBoundary repaintRenderBoundary = tester
.allRenderObjects
.firstWhere((RenderObject object) => object is RenderRepaintBoundary);
ui.Image image = await repaintRenderBoundary.toImage();
ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png);
});If I run that test on an Android device/emulator, I get a correct PNG capture of the app. However, if I run that on the host in Am I holding it wrong? |
|
aha - indeed I was holding it wrong. I was calling: await new File('/path/fo/foo.png').writeAsBytes(bytes);Which doesn't play nicely with our fake async. When I call |
681a657 to
0699d76
Compare
…tter#16758) This adds a toImage function to RenderRepaintBoundary that returns an uncompressed raw image of the RenderRepaintBoundary and its children. A device pixel ratio different from the physical ratio may be specified for the captured image. A value of 1.0 will give an image in logical pixels.
This adds a toImage function to RenderRepaintBoundary that returns an uncompressed raw image of the RenderRepaintBoundary and its children. A device pixel ratio different from the physical ratio may be specified for the captured image. A value of 1.0 will give an image in logical pixels.