raw_image_provider.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // MIT License
  2. //
  3. // Copyright (c) 2021 Yrom Wang
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in all
  13. // copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. // SOFTWARE.
  22. import 'dart:typed_data';
  23. import 'dart:ui' as ui;
  24. import 'package:flutter/foundation.dart';
  25. import 'package:flutter/painting.dart';
  26. import 'package:crypto/crypto.dart';
  27. /// Decodes the given [image] (raw image pixel data) as an image ('dart:ui')
  28. class RawImageProvider extends ImageProvider<_RawImageKey> {
  29. final RawImageData image;
  30. final double? scale;
  31. final int? targetWidth;
  32. final int? targetHeight;
  33. RawImageProvider(
  34. this.image, {
  35. this.scale = 1.0,
  36. this.targetWidth,
  37. this.targetHeight,
  38. });
  39. @override
  40. ImageStreamCompleter loadImage(_RawImageKey key, ImageDecoderCallback decode) {
  41. return MultiFrameImageStreamCompleter(
  42. codec: _loadAsync(key),
  43. scale: scale ?? 1.0,
  44. debugLabel: 'RawImageProvider(${describeIdentity(key)})',
  45. );
  46. }
  47. @override
  48. Future<_RawImageKey> obtainKey(ImageConfiguration configuration) {
  49. return SynchronousFuture(image._obtainKey());
  50. }
  51. /// see [ui.decodeImageFromPixels]
  52. Future<ui.Codec> _loadAsync(_RawImageKey key) async {
  53. assert(key == image._obtainKey());
  54. // rgba8888 pixels
  55. var buffer = await ui.ImmutableBuffer.fromUint8List(image.pixels);
  56. final descriptor = ui.ImageDescriptor.raw(
  57. buffer,
  58. width: image.width,
  59. height: image.height,
  60. pixelFormat: image.pixelFormat,
  61. );
  62. assert(() {
  63. debugPrint('ImageDescriptor: ${descriptor.width}x${descriptor.height}');
  64. return true;
  65. }());
  66. return descriptor.instantiateCodec(
  67. targetWidth: targetWidth, targetHeight: targetHeight);
  68. }
  69. }
  70. class _RawImageKey {
  71. final int w;
  72. final int h;
  73. final int format;
  74. final Digest dataHash;
  75. _RawImageKey(this.w, this.h, this.format, this.dataHash);
  76. @override
  77. bool operator ==(Object other) {
  78. if (identical(this, other)) return true;
  79. return other is _RawImageKey &&
  80. other.w == w &&
  81. other.h == h &&
  82. other.format == format &&
  83. other.dataHash == dataHash;
  84. }
  85. @override
  86. int get hashCode {
  87. return Object.hash(w, h, format, dataHash.hashCode);
  88. }
  89. }
  90. /// Raw pixels data of an image
  91. class RawImageData {
  92. final Uint8List pixels;
  93. final int width;
  94. final int height;
  95. final ui.PixelFormat pixelFormat;
  96. RawImageData(
  97. this.pixels,
  98. this.width,
  99. this.height, {
  100. this.pixelFormat = ui.PixelFormat.rgba8888,
  101. });
  102. _RawImageKey? _key;
  103. _RawImageKey _obtainKey() {
  104. return _key ??=
  105. _RawImageKey(width, height, pixelFormat.index, md5.convert(pixels));
  106. }
  107. }