David PHAM-VAN

Add more image loading functions

@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 - Improve image buffer management 14 - Improve image buffer management
15 - Optimize memory footprint 15 - Optimize memory footprint
16 - Add an exception if a jpeg image is not a supported format 16 - Add an exception if a jpeg image is not a supported format
  17 +- Add more image loading functions
17 18
18 ## 1.5.0 19 ## 1.5.0
19 20
@@ -49,15 +49,13 @@ pdf.addPage(pw.Page( @@ -49,15 +49,13 @@ pdf.addPage(pw.Page(
49 })); // Page 49 })); // Page
50 ``` 50 ```
51 51
52 -To load an image it is possible to use the dart library [image](https://pub.dev/packages/image): 52 +To load an image from a file:
53 53
54 ```dart 54 ```dart
55 -final img = decodeImage(File('test.webp').readAsBytesSync());  
56 -final image = PdfImage( 55 +final img = decodeImage();
  56 +final image = PdfImage.file(
57 pdf.document, 57 pdf.document,
58 - image: img.data.buffer.asUint8List(),  
59 - width: img.width,  
60 - height: img.height, 58 + bytes: File('test.webp').readAsBytesSync(),
61 ); 59 );
62 60
63 pdf.addPage(pw.Page( 61 pdf.addPage(pw.Page(
@@ -22,6 +22,7 @@ import 'dart:math' as math; @@ -22,6 +22,7 @@ import 'dart:math' as math;
22 import 'dart:typed_data'; 22 import 'dart:typed_data';
23 23
24 import 'package:crypto/crypto.dart'; 24 import 'package:crypto/crypto.dart';
  25 +import 'package:image/image.dart' as im;
25 import 'package:meta/meta.dart'; 26 import 'package:meta/meta.dart';
26 import 'package:utf/utf.dart'; 27 import 'package:utf/utf.dart';
27 import 'package:vector_math/vector_math_64.dart'; 28 import 'package:vector_math/vector_math_64.dart';
@@ -41,6 +41,8 @@ class PdfImage extends PdfXObject { @@ -41,6 +41,8 @@ class PdfImage extends PdfXObject {
41 bool alpha = true, 41 bool alpha = true,
42 PdfImageOrientation orientation = PdfImageOrientation.topLeft, 42 PdfImageOrientation orientation = PdfImageOrientation.topLeft,
43 }) { 43 }) {
  44 + assert(image != null);
  45 +
44 final PdfImage im = PdfImage._( 46 final PdfImage im = PdfImage._(
45 pdfDocument, 47 pdfDocument,
46 width, 48 width,
@@ -107,6 +109,42 @@ class PdfImage extends PdfXObject { @@ -107,6 +109,42 @@ class PdfImage extends PdfXObject {
107 return im; 109 return im;
108 } 110 }
109 111
  112 + factory PdfImage.fromImage(
  113 + PdfDocument pdfDocument, {
  114 + @required im.Image image,
  115 + PdfImageOrientation orientation = PdfImageOrientation.topLeft,
  116 + }) {
  117 + assert(image != null);
  118 +
  119 + return PdfImage(
  120 + pdfDocument,
  121 + image: image.getBytes(format: im.Format.rgba),
  122 + width: image.width,
  123 + height: image.height,
  124 + alpha: image.channels == im.Channels.rgba,
  125 + orientation: orientation,
  126 + );
  127 + }
  128 +
  129 + factory PdfImage.file(
  130 + PdfDocument pdfDocument, {
  131 + @required Uint8List bytes,
  132 + PdfImageOrientation orientation = PdfImageOrientation.topLeft,
  133 + }) {
  134 + assert(bytes != null);
  135 +
  136 + if (im.JpegDecoder().isValidFile(bytes)) {
  137 + return PdfImage.jpeg(pdfDocument, image: bytes);
  138 + }
  139 +
  140 + final im.Image image = im.decodeImage(bytes);
  141 + return PdfImage.fromImage(
  142 + pdfDocument,
  143 + image: image,
  144 + orientation: orientation,
  145 + );
  146 + }
  147 +
110 factory PdfImage._alpha( 148 factory PdfImage._alpha(
111 PdfDocument pdfDocument, 149 PdfDocument pdfDocument,
112 Uint8List image, 150 Uint8List image,
@@ -17,6 +17,7 @@ dependencies: @@ -17,6 +17,7 @@ dependencies:
17 archive: ^2.0.10 17 archive: ^2.0.10
18 qr: ^1.2.0 18 qr: ^1.2.0
19 barcode: ^1.5.0 19 barcode: ^1.5.0
  20 + image: ^2.1.4
20 21
21 dev_dependencies: 22 dev_dependencies:
22 test: 23 test:
@@ -84,6 +84,34 @@ void main() { @@ -84,6 +84,34 @@ void main() {
84 ); 84 );
85 }); 85 });
86 86
  87 + test('Pdf Image decode', () {
  88 + final Iterable<Widget> imageWidgets = imageFiles.map<Widget>(
  89 + (String image) => SizedBox(
  90 + child: Image(
  91 + PdfImage.file(
  92 + pdf.document,
  93 + bytes: gzip.decode(base64.decode(image)),
  94 + ),
  95 + ),
  96 + width: 200,
  97 + height: 200,
  98 + ),
  99 + );
  100 +
  101 + pdf.addPage(
  102 + Page(
  103 + build: (Context context) => Center(
  104 + child: Wrap(
  105 + spacing: 20,
  106 + runSpacing: 20,
  107 + alignment: WrapAlignment.spaceEvenly,
  108 + children: imageWidgets.toList(),
  109 + ),
  110 + ),
  111 + ),
  112 + );
  113 + });
  114 +
87 tearDownAll(() { 115 tearDownAll(() {
88 final File file = File('jpeg.pdf'); 116 final File file = File('jpeg.pdf');
89 file.writeAsBytesSync(pdf.save()); 117 file.writeAsBytesSync(pdf.save());
@@ -110,3 +138,9 @@ const List<String> images = <String>[ @@ -110,3 +138,9 @@ const List<String> images = <String>[
110 '/9j/4AAQSkZJRgABAQEA3ADcAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABwAAAAAAAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAwAFADASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAkI/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDVIAAAAAAAJVgAqoAAACVYAKqAAlWAAAAAAAAAAAD/2Q==', 138 '/9j/4AAQSkZJRgABAQEA3ADcAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABwAAAAAAAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAwAFADASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAkI/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDVIAAAAAAAJVgAqoAAACVYAKqAAlWAAAAAAAAAAAD/2Q==',
111 '/9j/4AAQSkZJRgABAQEA3ADcAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAACAAAAAAAAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAwAFADASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAkI/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDKgAAAAAAAAAKqAAAAlWACqgAJVgAqoAAAAAAACVYAP//Z', 139 '/9j/4AAQSkZJRgABAQEA3ADcAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAACAAAAAAAAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAwAFADASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAkI/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDKgAAAAAAAAAKqAAAAlWACqgAJVgAqoAAAAAAACVYAP//Z',
112 ]; 140 ];
  141 +
  142 +const List<String> imageFiles = <String>[
  143 + 'H4sIAKx0cl4AA/t/4/8DBgEvN083BkZGRgYPIGT4f5vBmeE/pQBoCCPFhhxgEORgUGQwYmZUYmASZGQWZPx/hEEM7FQUwMgEFBcVQBdmEAQJY6hmAJkiIoguyvD/FgMPMyPQImZBBnuGVU0LGLS1GpoaVqiyCi1lm8gY4iDK4MAYwMDA/v8mAIKohPQ4AQAA',
  144 + 'H4sIAAV2cl4AA+sM8HPn5ZLiYmBg4PX0cAkC0kZArMjBBCRF5PMvAylTTxfHkIjDb88ZMjIYcDAoxP5XM9vcsvrBS0bOEy+7quPmLFmKDrZ+Yjx0ienafeXk7UADGDxd/VzWOSU0AQCMWbgebgAAAA==',
  145 + 'H4sIAFZ2cl4AA3P3dLMwTzRiUGRoYGDIXCUJRDoMQAASYWBSb+lfefot/+I5W251b7635zd/2yOPac86l706te0d9/FPPte/9T7/de41K4M1ANAWLyFIAAAA'
  146 +];
No preview for this file type