'How to load image from assets folder inside a pdf in Flutter web?

We want to show image on a pdf from assets folder in Flutter web application:

import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:flutter/material.dart';
.............

@override
Widget build(BuildContext context) {
return Scaffold(
    body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
      Expanded(
        child: Container(
            height: 400,
            width: 900,
            child: PdfPreview(
              build: (format) => _generatePdf(format, "SOME TITLE"),
            )),
      ),
    ]));
    }

Future<Uint8List> _generatePdf(PdfPageFormat format) async {
final pdf = pw.Document();    
pdf.addPage(
  pw.Page(
      pageFormat: format,
      build: (context) {
        return pw.Image(AssetImage('assets/imglogo.png')); //This line gives the error
      }));
       return pdf.save();
      }

This code gives error:

The argument type 'AssetImage' can't be assigned to the parameter type 'ImageProvider'

The documentation addresses only two cases To load an image from a file:(dart.io is not supported on the web), and To load an image from the network using the printing package:, which is not the case, so we tried the solutions provided here: 1,2, but each one gives a different exception.

Is there another approach to achieve this?



Solution 1:[1]

You can convert your ByteData directly to Uint8List as shown in the example code below. This can then be passed to the MemoryImage constructor:

  Future<void> addPage(pw.Document pdf, String filename) async {
    final imageByteData = await rootBundle.load('assets/$filename');
    // Convert ByteData to Uint8List
    final imageUint8List = imageByteData.buffer
        .asUint8List(imageByteData.offsetInBytes, imageByteData.lengthInBytes);

    final image = pw.MemoryImage(imageUint8List);
    pdf.addPage(
      pw.Page(
        build: (pw.Context context) {
          return pw.Center(
            child: pw.Image(image),
          ); // Center
        },
      ),
    );
  }

Solution 2:[2]

To achieve this you can get the asset image as a file, and then use this file in the PDF. If I take your code, we can add a function to get a File representation of your asset image :

  Future<File> getImageFileFromAssets(String path) async {
    final byteData = await rootBundle.load('assets/$path');

    final file = File('${(await getTemporaryDirectory()).path}/$path');
    await file.writeAsBytes(byteData.buffer
        .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));

    return file;
  }

To make it works, you need to add path_provider to your dependencies.

Then you can use this function in your pdf generation function :

    final pdf = pw.Document();

    final file = await getImageFileFromAssets(yourpath);

    final image = pw.MemoryImage(
      file.readAsBytesSync(),
    );

    pdf.addPage(pw.Page(
        pageFormat: format,
        build: (context) {
          return pw.Image(image);
        }));
    return pdf.save();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 hnnngwdlch
Solution 2 Pierre Monier