-
Notifications
You must be signed in to change notification settings - Fork 6k
[canvaskit] Decode images using <img> tag decoding #53201
Changes from 1 commit
49ed8d4
6b248d1
d780fe3
4e43312
9b1a448
e6d4d44
8ea4865
88d685d
23cb86b
7883559
8a1a7ce
389369d
d900ded
355891b
cfc1c4a
d317302
c579c8e
dd5c8d6
f3997c1
52b8330
b207ee7
4f5f863
7c6ab13
0b426fe
c06797c
e7aff46
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,14 +30,113 @@ Future<ui.Codec> skiaInstantiateImageCodec(Uint8List list, | |
| final DomBlob blob = createDomBlob(<ByteBuffer>[list.buffer]); | ||
| codec = await decodeBlobToCkImage(blob); | ||
| } | ||
| return ResizingCodec( | ||
| return CkResizingCodec( | ||
| codec, | ||
| targetWidth: targetWidth, | ||
| targetHeight: targetHeight, | ||
| allowUpscaling: allowUpscaling, | ||
| ); | ||
| } | ||
|
|
||
| /// A resizing codec which uses an HTML <canvas> element to scale the image if | ||
| /// it is backed by an HTML Image element. | ||
| class CkResizingCodec extends ResizingCodec { | ||
| CkResizingCodec( | ||
| super.delegate, { | ||
| super.targetWidth, | ||
| super.targetHeight, | ||
| super.allowUpscaling, | ||
| }); | ||
|
|
||
| @override | ||
| ui.Image scaleImage( | ||
| ui.Image image, { | ||
| int? targetWidth, | ||
| int? targetHeight, | ||
| bool allowUpscaling = true, | ||
| }) { | ||
| final CkImage ckImage = image as CkImage; | ||
| if (ckImage.imageElement == null) { | ||
| return scaleImageIfNeeded( | ||
| image, | ||
| targetWidth: targetWidth, | ||
| targetHeight: targetHeight, | ||
| allowUpscaling: allowUpscaling, | ||
| ); | ||
| } else { | ||
| return _scaleImageUsingDomCanvas( | ||
| ckImage, | ||
| targetWidth: targetWidth, | ||
| targetHeight: targetHeight, | ||
| allowUpscaling: allowUpscaling, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| CkImage _scaleImageUsingDomCanvas( | ||
| CkImage image, { | ||
| int? targetWidth, | ||
| int? targetHeight, | ||
| bool allowUpscaling = true, | ||
| }) { | ||
| assert(image.imageElement != null); | ||
| final int width = image.width; | ||
| final int height = image.height; | ||
| final ui.Size? scaledSize = | ||
| scaledImageSize(width, height, targetWidth, targetHeight); | ||
| if (scaledSize == null) { | ||
| return image; | ||
| } | ||
| if (!allowUpscaling && | ||
| (scaledSize.width > width || scaledSize.height > height)) { | ||
| return image; | ||
| } | ||
|
|
||
| final int scaledWidth = scaledSize.width.toInt(); | ||
| final int scaledHeight = scaledSize.height.toInt(); | ||
|
|
||
| final DomCanvasElement htmlCanvas = createDomCanvasElement( | ||
| width: scaledWidth, | ||
| height: scaledHeight, | ||
| ); | ||
| final DomCanvasRenderingContext2D ctx = | ||
| htmlCanvas.getContext('2d')! as DomCanvasRenderingContext2D; | ||
|
||
| ctx.drawImage( | ||
| image.imageElement!, | ||
| 0, | ||
| 0, | ||
| width, | ||
| height, | ||
| 0, | ||
| 0, | ||
| scaledWidth, | ||
| scaledHeight, | ||
| ); | ||
| final DomImageData imageData = | ||
| ctx.getImageData(0, 0, scaledWidth, scaledHeight); | ||
|
||
| final Uint8List pixels = imageData.data.buffer.asUint8List(); | ||
|
|
||
| final SkImage? skImage = canvasKit.MakeImage( | ||
| SkImageInfo( | ||
| width: scaledWidth.toDouble(), | ||
| height: scaledHeight.toDouble(), | ||
| colorType: canvasKit.ColorType.RGBA_8888, | ||
| alphaType: canvasKit.AlphaType.Premul, | ||
| colorSpace: SkColorSpaceSRGB, | ||
| ), | ||
| pixels, | ||
| (4 * scaledWidth).toDouble(), | ||
| ); | ||
|
|
||
| if (skImage == null) { | ||
| domWindow.console.warn('Failed to scale image.'); | ||
| return image; | ||
| } | ||
|
|
||
| return CkImage(skImage); | ||
| } | ||
| } | ||
|
|
||
| ui.Image createCkImageFromImageElement( | ||
| DomHTMLImageElement image, | ||
| int naturalWidth, | ||
|
|
@@ -212,9 +311,6 @@ CkImage scaleImage(SkImage image, int? targetWidth, int? targetHeight) { | |
| return ckImage; | ||
| } | ||
|
|
||
| CkImage scaleImageWithCanvas( | ||
| SkImage image, int? targetWidth, int? targetHeight) {} | ||
|
|
||
| /// Thrown when the web engine fails to decode an image, either due to a | ||
| /// network issue, corrupted image contents, or missing codec. | ||
| class ImageCodecException implements Exception { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
scaledImageSizeshould switch toBitmapSizeto avoid rounding? There's also the issue that we check forallowUpscalingbefore callingtoInt, which may end up upscaling anyway.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched to
BitmapSizeto avoid ugly.toInt()and.toDouble()calls where possible. Checking forallowUpscalingbefore callingtoInt()should be okay here since we're only working withints for the width and height.