Showing
5 changed files
with
154 additions
and
38 deletions
@@ -200,7 +200,13 @@ class PDFImage extends PdfImage { | @@ -200,7 +200,13 @@ class PDFImage extends PdfImage { | ||
200 | @required int height, | 200 | @required int height, |
201 | bool alpha = true, | 201 | bool alpha = true, |
202 | }) : super._(pdfDocument, | 202 | }) : super._(pdfDocument, |
203 | - image: image, width: width, height: height, alpha: alpha); | 203 | + image: image, |
204 | + width: width, | ||
205 | + height: height, | ||
206 | + alpha: alpha, | ||
207 | + alphaChannel: false, | ||
208 | + jpeg: false, | ||
209 | + orientation: PdfImageOrientation.topLeft); | ||
204 | } | 210 | } |
205 | 211 | ||
206 | @deprecated | 212 | @deprecated |
@@ -108,7 +108,33 @@ class PdfGraphics { | @@ -108,7 +108,33 @@ class PdfGraphics { | ||
108 | 108 | ||
109 | // q w 0 0 h x y cm % the coordinate matrix | 109 | // q w 0 0 h x y cm % the coordinate matrix |
110 | buf.putString('q '); | 110 | buf.putString('q '); |
111 | - buf.putNumList(<double>[w, 0, 0, h, x, y]); | 111 | + switch (img.orientation) { |
112 | + case PdfImageOrientation.topLeft: | ||
113 | + buf.putNumList(<double>[w, 0, 0, h, x, y]); | ||
114 | + break; | ||
115 | + case PdfImageOrientation.topRight: | ||
116 | + buf.putNumList(<double>[-w, 0, 0, h, w - x, y]); | ||
117 | + break; | ||
118 | + case PdfImageOrientation.bottomRight: | ||
119 | + buf.putNumList(<double>[-w, 0, 0, -h, w - x, h - y]); | ||
120 | + break; | ||
121 | + case PdfImageOrientation.bottomLeft: | ||
122 | + buf.putNumList(<double>[w, 0, 0, -h, x, h - y]); | ||
123 | + break; | ||
124 | + case PdfImageOrientation.leftTop: | ||
125 | + buf.putNumList(<double>[0, -h, -w, 0, w - x, h - y]); | ||
126 | + break; | ||
127 | + case PdfImageOrientation.rightTop: | ||
128 | + buf.putNumList(<double>[0, h, -w, 0, w - x, y]); | ||
129 | + break; | ||
130 | + case PdfImageOrientation.rightBottom: | ||
131 | + buf.putNumList(<double>[0, h, w, 0, x, y]); | ||
132 | + break; | ||
133 | + case PdfImageOrientation.leftBottom: | ||
134 | + buf.putNumList(<double>[0, -h, w, 0, x, h - y]); | ||
135 | + break; | ||
136 | + } | ||
137 | + | ||
112 | buf.putString(' cm ${img.name} Do Q\n'); | 138 | buf.putString(' cm ${img.name} Do Q\n'); |
113 | } | 139 | } |
114 | 140 |
@@ -16,6 +16,19 @@ | @@ -16,6 +16,19 @@ | ||
16 | 16 | ||
17 | part of pdf; | 17 | part of pdf; |
18 | 18 | ||
19 | +/// Represents the position of the first pixel in the data stream | ||
20 | +/// This corresponds to the exif orientations | ||
21 | +enum PdfImageOrientation { | ||
22 | + topLeft, | ||
23 | + topRight, | ||
24 | + bottomRight, | ||
25 | + bottomLeft, | ||
26 | + leftTop, | ||
27 | + rightTop, | ||
28 | + rightBottom, | ||
29 | + leftBottom, | ||
30 | +} | ||
31 | + | ||
19 | class PdfImage extends PdfXObject { | 32 | class PdfImage extends PdfXObject { |
20 | /// Creates a new [PdfImage] instance. | 33 | /// Creates a new [PdfImage] instance. |
21 | /// | 34 | /// |
@@ -29,6 +42,7 @@ class PdfImage extends PdfXObject { | @@ -29,6 +42,7 @@ class PdfImage extends PdfXObject { | ||
29 | @required int width, | 42 | @required int width, |
30 | @required int height, | 43 | @required int height, |
31 | bool alpha = true, | 44 | bool alpha = true, |
45 | + PdfImageOrientation orientation = PdfImageOrientation.topLeft, | ||
32 | }) => | 46 | }) => |
33 | PdfImage._( | 47 | PdfImage._( |
34 | pdfDocument, | 48 | pdfDocument, |
@@ -36,18 +50,27 @@ class PdfImage extends PdfXObject { | @@ -36,18 +50,27 @@ class PdfImage extends PdfXObject { | ||
36 | width: width, | 50 | width: width, |
37 | height: height, | 51 | height: height, |
38 | alpha: alpha, | 52 | alpha: alpha, |
53 | + alphaChannel: false, | ||
54 | + jpeg: false, | ||
55 | + orientation: orientation, | ||
39 | ); | 56 | ); |
40 | 57 | ||
41 | - PdfImage._(PdfDocument pdfDocument, | ||
42 | - {@required this.image, | ||
43 | - @required this.width, | ||
44 | - @required this.height, | ||
45 | - this.alpha = true, | ||
46 | - this.alphaChannel = false, | ||
47 | - this.jpeg = false}) | ||
48 | - : assert(alphaChannel == false || alpha == true), | 58 | + PdfImage._( |
59 | + PdfDocument pdfDocument, { | ||
60 | + @required this.image, | ||
61 | + @required int width, | ||
62 | + @required int height, | ||
63 | + @required this.alpha, | ||
64 | + @required this.alphaChannel, | ||
65 | + @required this.jpeg, | ||
66 | + @required this.orientation, | ||
67 | + }) : assert(alphaChannel == false || alpha == true), | ||
49 | assert(width != null), | 68 | assert(width != null), |
50 | assert(height != null), | 69 | assert(height != null), |
70 | + assert(jpeg != null), | ||
71 | + assert(orientation != null), | ||
72 | + _width = width, | ||
73 | + _height = height, | ||
51 | super(pdfDocument, '/Image', isBinary: true) { | 74 | super(pdfDocument, '/Image', isBinary: true) { |
52 | _name = '/Image$objser'; | 75 | _name = '/Image$objser'; |
53 | params['/Width'] = PdfStream.string(width.toString()); | 76 | params['/Width'] = PdfStream.string(width.toString()); |
@@ -56,12 +79,16 @@ class PdfImage extends PdfXObject { | @@ -56,12 +79,16 @@ class PdfImage extends PdfXObject { | ||
56 | params['/Name'] = PdfStream.string(_name); | 79 | params['/Name'] = PdfStream.string(_name); |
57 | 80 | ||
58 | if (alphaChannel == false && alpha) { | 81 | if (alphaChannel == false && alpha) { |
59 | - final PdfImage _sMask = PdfImage._(pdfDocument, | ||
60 | - image: image, | ||
61 | - width: width, | ||
62 | - height: height, | ||
63 | - alpha: alpha, | ||
64 | - alphaChannel: true); | 82 | + final PdfImage _sMask = PdfImage._( |
83 | + pdfDocument, | ||
84 | + image: image, | ||
85 | + width: width, | ||
86 | + height: height, | ||
87 | + alpha: alpha, | ||
88 | + alphaChannel: true, | ||
89 | + jpeg: jpeg, | ||
90 | + orientation: orientation, | ||
91 | + ); | ||
65 | params['/SMask'] = PdfStream.string('${_sMask.objser} 0 R'); | 92 | params['/SMask'] = PdfStream.string('${_sMask.objser} 0 R'); |
66 | } | 93 | } |
67 | 94 | ||
@@ -76,7 +103,11 @@ class PdfImage extends PdfXObject { | @@ -76,7 +103,11 @@ class PdfImage extends PdfXObject { | ||
76 | } | 103 | } |
77 | } | 104 | } |
78 | 105 | ||
79 | - factory PdfImage.jpeg(PdfDocument pdfDocument, {@required Uint8List image}) { | 106 | + factory PdfImage.jpeg( |
107 | + PdfDocument pdfDocument, { | ||
108 | + @required Uint8List image, | ||
109 | + PdfImageOrientation orientation, | ||
110 | + }) { | ||
80 | assert(image != null); | 111 | assert(image != null); |
81 | 112 | ||
82 | int width; | 113 | int width; |
@@ -117,18 +148,30 @@ class PdfImage extends PdfXObject { | @@ -117,18 +148,30 @@ class PdfImage extends PdfXObject { | ||
117 | offset += len - 2; | 148 | offset += len - 2; |
118 | } | 149 | } |
119 | 150 | ||
120 | - return PdfImage._(pdfDocument, | ||
121 | - image: image, width: width, height: height, jpeg: true, alpha: false); | 151 | + orientation ??= PdfImageOrientation.leftTop; |
152 | + | ||
153 | + return PdfImage._( | ||
154 | + pdfDocument, | ||
155 | + image: image, | ||
156 | + width: width, | ||
157 | + height: height, | ||
158 | + jpeg: true, | ||
159 | + alpha: false, | ||
160 | + alphaChannel: false, | ||
161 | + orientation: orientation, | ||
162 | + ); | ||
122 | } | 163 | } |
123 | 164 | ||
124 | /// RGBA Image Data | 165 | /// RGBA Image Data |
125 | final Uint8List image; | 166 | final Uint8List image; |
126 | 167 | ||
127 | /// Image width | 168 | /// Image width |
128 | - final int width; | 169 | + final int _width; |
170 | + int get width => orientation.index >= 4 ? _height : _width; | ||
129 | 171 | ||
130 | /// Image height | 172 | /// Image height |
131 | - final int height; | 173 | + final int _height; |
174 | + int get height => orientation.index < 4 ? _height : _width; | ||
132 | 175 | ||
133 | /// Image has alpha channel | 176 | /// Image has alpha channel |
134 | final bool alpha; | 177 | final bool alpha; |
@@ -141,6 +184,9 @@ class PdfImage extends PdfXObject { | @@ -141,6 +184,9 @@ class PdfImage extends PdfXObject { | ||
141 | /// The image data is a jpeg image | 184 | /// The image data is a jpeg image |
142 | final bool jpeg; | 185 | final bool jpeg; |
143 | 186 | ||
187 | + /// The internal orientation of the image | ||
188 | + final PdfImageOrientation orientation; | ||
189 | + | ||
144 | /// write the pixels to the stream | 190 | /// write the pixels to the stream |
145 | @override | 191 | @override |
146 | void _prepare() { | 192 | void _prepare() { |
@@ -151,8 +197,8 @@ class PdfImage extends PdfXObject { | @@ -151,8 +197,8 @@ class PdfImage extends PdfXObject { | ||
151 | return; | 197 | return; |
152 | } | 198 | } |
153 | 199 | ||
154 | - final int w = width; | ||
155 | - final int h = height; | 200 | + final int w = _width; |
201 | + final int h = _height; | ||
156 | final int s = w * h; | 202 | final int s = w * h; |
157 | 203 | ||
158 | final Uint8List out = Uint8List(alphaChannel ? s : s * 3); | 204 | final Uint8List out = Uint8List(alphaChannel ? s : s * 3); |
@@ -15,36 +15,73 @@ | @@ -15,36 +15,73 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import 'dart:async'; | 17 | import 'dart:async'; |
18 | +import 'dart:convert'; | ||
18 | import 'dart:io'; | 19 | import 'dart:io'; |
19 | import 'dart:typed_data'; | 20 | import 'dart:typed_data'; |
20 | 21 | ||
21 | import 'package:pdf/pdf.dart'; | 22 | import 'package:pdf/pdf.dart'; |
23 | +import 'package:pdf/widgets.dart'; | ||
22 | import 'package:test/test.dart'; | 24 | import 'package:test/test.dart'; |
23 | 25 | ||
24 | -Future<Uint8List> download(String url) async { | ||
25 | - final HttpClient client = HttpClient(); | ||
26 | - final HttpClientRequest request = await client.getUrl(Uri.parse(url)); | ||
27 | - final HttpClientResponse response = await request.close(); | ||
28 | - final BytesBuilder builder = await response.fold( | ||
29 | - BytesBuilder(), (BytesBuilder b, List<int> d) => b..add(d)); | ||
30 | - final List<int> data = builder.takeBytes(); | ||
31 | - return Uint8List.fromList(data); | ||
32 | -} | 26 | +Document pdf; |
33 | 27 | ||
34 | void main() { | 28 | void main() { |
35 | - test('Pdf Jpeg', () async { | ||
36 | - final PdfDocument pdf = PdfDocument(); | ||
37 | - final PdfPage page = PdfPage(pdf, pageFormat: PdfPageFormat.a4); | 29 | + setUpAll(() { |
30 | + Document.debug = true; | ||
31 | + pdf = Document(); | ||
32 | + }); | ||
38 | 33 | ||
34 | + test('Pdf Jpeg Download', () async { | ||
39 | final PdfImage image = PdfImage.jpeg( | 35 | final PdfImage image = PdfImage.jpeg( |
40 | - pdf, | 36 | + pdf.document, |
41 | image: await download('https://www.nfet.net/nfet.jpg'), | 37 | image: await download('https://www.nfet.net/nfet.jpg'), |
42 | ); | 38 | ); |
43 | 39 | ||
44 | - final PdfGraphics g = page.getGraphics(); | ||
45 | - g.drawImage(image, 30, page.pageFormat.height - 507.0); | 40 | + pdf.addPage(Page( |
41 | + build: (Context context) => Center(child: Image(image)), | ||
42 | + )); | ||
43 | + }); | ||
46 | 44 | ||
45 | + test('Pdf Jpeg Orientation', () { | ||
46 | + pdf.addPage( | ||
47 | + Page( | ||
48 | + build: (Context context) => Wrap( | ||
49 | + spacing: 20, | ||
50 | + runSpacing: 20, | ||
51 | + children: List<Widget>.generate( | ||
52 | + PdfImageOrientation.values.length, | ||
53 | + (int index) => SizedBox( | ||
54 | + width: 230, | ||
55 | + height: 230, | ||
56 | + child: Image( | ||
57 | + PdfImage.jpeg( | ||
58 | + pdf.document, | ||
59 | + image: base64.decode(jpegImage), | ||
60 | + orientation: PdfImageOrientation.values[index], | ||
61 | + ), | ||
62 | + ), | ||
63 | + ), | ||
64 | + ), | ||
65 | + ), | ||
66 | + ), | ||
67 | + ); | ||
68 | + }); | ||
69 | + | ||
70 | + tearDownAll(() { | ||
47 | final File file = File('jpeg.pdf'); | 71 | final File file = File('jpeg.pdf'); |
48 | file.writeAsBytesSync(pdf.save()); | 72 | file.writeAsBytesSync(pdf.save()); |
49 | }); | 73 | }); |
50 | } | 74 | } |
75 | + | ||
76 | +Future<Uint8List> download(String url) async { | ||
77 | + final HttpClient client = HttpClient(); | ||
78 | + final HttpClientRequest request = await client.getUrl(Uri.parse(url)); | ||
79 | + final HttpClientResponse response = await request.close(); | ||
80 | + final BytesBuilder builder = await response.fold( | ||
81 | + BytesBuilder(), (BytesBuilder b, List<int> d) => b..add(d)); | ||
82 | + final List<int> data = builder.takeBytes(); | ||
83 | + return Uint8List.fromList(data); | ||
84 | +} | ||
85 | + | ||
86 | +const String jpegImage = | ||
87 | + '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAEMuMjoyKkM6NjpLR0NPZKZsZFxcZMySmnmm8dT++u3U6eX//////////+Xp////////////////////////////2wBDAUdLS2RXZMRsbMT//+n/////////////////////////////////////////////////////////////////////wAARCAAUAAgDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAP/xAAbEAACAwEBAQAAAAAAAAAAAAABAgARIQMEQf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCvm5joGZi1hj9iPIgIZ7Nhzl5EC3FAikC9N7ERA//Z'; |
-
Please register or login to post a comment