LCOV - code coverage report
Current view: top level - lib/src/assets - images.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 32 64 50.0 %
Date: 2021-08-10 15:50:53 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:convert' show base64;
       3             : import 'dart:typed_data';
       4             : import 'dart:ui';
       5             : import 'dart:ui' as ui show decodeImageFromPixels;
       6             : 
       7             : import 'package:flutter/foundation.dart';
       8             : 
       9             : import '../flame.dart';
      10             : 
      11             : class Images {
      12             :   final String prefix;
      13             :   final Map<String, _ImageAssetLoader> _loadedFiles = {};
      14             : 
      15          28 :   Images({this.prefix = 'assets/images/'});
      16             : 
      17           0 :   void clear(String fileName) {
      18           0 :     _loadedFiles.remove(fileName);
      19             :   }
      20             : 
      21           2 :   void clearCache() {
      22           4 :     _loadedFiles.clear();
      23             :   }
      24             : 
      25           0 :   Image fromCache(String fileName) {
      26           0 :     final image = _loadedFiles[fileName];
      27             :     assert(
      28           0 :       image?.loadedImage != null,
      29           0 :       'Tried to access an inexistent entry on cache "$fileName", make sure to use the load method before accessing a file on the cache',
      30             :     );
      31           0 :     return image!.loadedImage!;
      32             :   }
      33             : 
      34           0 :   Future<List<Image>> loadAll(List<String> fileNames) async {
      35           0 :     return Future.wait(fileNames.map(load));
      36             :   }
      37             : 
      38           0 :   Future<Image> load(String fileName) async {
      39           0 :     if (!_loadedFiles.containsKey(fileName)) {
      40           0 :       _loadedFiles[fileName] = _ImageAssetLoader(_fetchToMemory(fileName));
      41             :     }
      42           0 :     return _loadedFiles[fileName]!.retrieve();
      43             :   }
      44             : 
      45             :   /// Convert an array of pixel values into an [Image] object.
      46             :   ///
      47             :   /// The [pixels] parameter is the pixel data in the encoding described by
      48             :   /// [PixelFormat.rgba8888], the encoding can't be changed to allow for web support.
      49             :   ///
      50             :   /// If you want the image to be decoded as it would be on the web you can set
      51             :   /// [runAsWeb] to `true`. Keep in mind that it is slightly slower than the native
      52             :   /// [ui.decodeImageFromPixels]. By default it is set to [kIsWeb].
      53           5 :   Future<Image> decodeImageFromPixels(
      54             :     Uint8List pixels,
      55             :     int width,
      56             :     int height, {
      57             :     bool runAsWeb = kIsWeb,
      58             :   }) {
      59           5 :     final completer = Completer<Image>();
      60             :     if (runAsWeb) {
      61           2 :       completer.complete(_createBmp(pixels, width, height));
      62             :     } else {
      63           5 :       ui.decodeImageFromPixels(
      64             :         pixels,
      65             :         width,
      66             :         height,
      67             :         PixelFormat.rgba8888,
      68           5 :         completer.complete,
      69             :       );
      70             :     }
      71             : 
      72           5 :     return completer.future;
      73             :   }
      74             : 
      75           0 :   Future<Image> fromBase64(String fileName, String base64) async {
      76           0 :     if (!_loadedFiles.containsKey(fileName)) {
      77           0 :       _loadedFiles[fileName] = _ImageAssetLoader(_fetchFromBase64(base64));
      78             :     }
      79           0 :     return _loadedFiles[fileName]!.retrieve();
      80             :   }
      81             : 
      82           0 :   Future<Image> _fetchFromBase64(String base64Data) async {
      83           0 :     final data = base64Data.substring(base64Data.indexOf(',') + 1);
      84           0 :     final bytes = base64.decode(data);
      85           0 :     return _loadBytes(bytes);
      86             :   }
      87             : 
      88           0 :   Future<Image> _fetchToMemory(String name) async {
      89           0 :     final data = await Flame.bundle.load('$prefix$name');
      90           0 :     final bytes = Uint8List.view(data.buffer);
      91           0 :     return _loadBytes(bytes);
      92             :   }
      93             : 
      94           0 :   Future<Image> _loadBytes(Uint8List bytes) {
      95           0 :     final completer = Completer<Image>();
      96           0 :     decodeImageFromList(bytes, completer.complete);
      97           0 :     return completer.future;
      98             :   }
      99             : 
     100           1 :   Future<Image> _createBmp(Uint8List pixels, int width, int height) async {
     101           3 :     final size = (width * height * 4) + 122;
     102           1 :     final bmp = Uint8List(size);
     103           2 :     bmp.buffer.asByteData()
     104           1 :       ..setUint8(0x0, 0x42)
     105           1 :       ..setUint8(0x1, 0x4d)
     106           1 :       ..setInt32(0x2, size, Endian.little)
     107           1 :       ..setInt32(0xa, 122, Endian.little)
     108           1 :       ..setUint32(0xe, 108, Endian.little)
     109           1 :       ..setUint32(0x12, width, Endian.little)
     110           2 :       ..setUint32(0x16, -height, Endian.little)
     111           1 :       ..setUint16(0x1a, 1, Endian.little)
     112           1 :       ..setUint32(0x1c, 32, Endian.little)
     113           1 :       ..setUint32(0x1e, 3, Endian.little)
     114           3 :       ..setUint32(0x22, width * height * 4, Endian.little)
     115           1 :       ..setUint32(0x36, 0x000000ff, Endian.little)
     116           1 :       ..setUint32(0x3a, 0x0000ff00, Endian.little)
     117           1 :       ..setUint32(0x3e, 0x00ff0000, Endian.little)
     118           1 :       ..setUint32(0x42, 0xff000000, Endian.little);
     119             : 
     120           1 :     bmp.setRange(122, size, pixels);
     121             : 
     122           2 :     final codec = await instantiateImageCodec(bmp);
     123           2 :     final frame = await codec.getNextFrame();
     124             : 
     125           1 :     return frame.image;
     126             :   }
     127             : }
     128             : 
     129             : class _ImageAssetLoader {
     130           0 :   _ImageAssetLoader(this.future);
     131             : 
     132             :   Image? loadedImage;
     133             :   Future<Image> future;
     134             : 
     135           0 :   Future<Image> retrieve() async {
     136           0 :     return loadedImage ??= await future;
     137             :   }
     138             : }

Generated by: LCOV version 1.15