Showing
2 changed files
with
86 additions
and
118 deletions
@@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
11 | - Uniformize examples | 11 | - Uniformize examples |
12 | - Fix context painting empty Table | 12 | - Fix context painting empty Table |
13 | - Fix Text decoration placements | 13 | - Fix Text decoration placements |
14 | +- Improve image buffer management | ||
14 | 15 | ||
15 | ## 1.5.0 | 16 | ## 1.5.0 |
16 | 17 |
@@ -33,11 +33,6 @@ enum PdfImageOrientation { | @@ -33,11 +33,6 @@ enum PdfImageOrientation { | ||
33 | 33 | ||
34 | class PdfImage extends PdfXObject { | 34 | class PdfImage extends PdfXObject { |
35 | /// Creates a new [PdfImage] instance. | 35 | /// Creates a new [PdfImage] instance. |
36 | - /// | ||
37 | - /// @param image an [Uint8List] value | ||
38 | - /// @param width | ||
39 | - /// @param height | ||
40 | - /// @param alpha if the image is transparent | ||
41 | factory PdfImage( | 36 | factory PdfImage( |
42 | PdfDocument pdfDocument, { | 37 | PdfDocument pdfDocument, { |
43 | @required Uint8List image, | 38 | @required Uint8List image, |
@@ -45,68 +40,41 @@ class PdfImage extends PdfXObject { | @@ -45,68 +40,41 @@ class PdfImage extends PdfXObject { | ||
45 | @required int height, | 40 | @required int height, |
46 | bool alpha = true, | 41 | bool alpha = true, |
47 | PdfImageOrientation orientation = PdfImageOrientation.topLeft, | 42 | PdfImageOrientation orientation = PdfImageOrientation.topLeft, |
48 | - }) => | ||
49 | - PdfImage._( | 43 | + }) { |
44 | + final PdfImage im = PdfImage._( | ||
50 | pdfDocument, | 45 | pdfDocument, |
51 | - image: image, | ||
52 | - width: width, | ||
53 | - height: height, | ||
54 | - alpha: alpha, | ||
55 | - alphaChannel: false, | ||
56 | - isRGB: true, | ||
57 | - jpeg: false, | ||
58 | - orientation: orientation, | 46 | + width, |
47 | + height, | ||
48 | + orientation, | ||
59 | ); | 49 | ); |
60 | 50 | ||
61 | - PdfImage._( | ||
62 | - PdfDocument pdfDocument, { | ||
63 | - @required this.image, | ||
64 | - @required int width, | ||
65 | - @required int height, | ||
66 | - @required this.alpha, | ||
67 | - @required this.alphaChannel, | ||
68 | - @required this.isRGB, | ||
69 | - @required this.jpeg, | ||
70 | - @required this.orientation, | ||
71 | - }) : assert(alphaChannel == false || alpha == true), | ||
72 | - assert(width != null), | ||
73 | - assert(height != null), | ||
74 | - assert(jpeg != null), | ||
75 | - assert(isRGB != null), | ||
76 | - assert(orientation != null), | ||
77 | - _width = width, | ||
78 | - _height = height, | ||
79 | - super(pdfDocument, '/Image', isBinary: true) { | ||
80 | - _name = '/Image$objser'; | ||
81 | - params['/Width'] = PdfNum(width); | ||
82 | - params['/Height'] = PdfNum(height); | ||
83 | - params['/BitsPerComponent'] = const PdfNum(8); | ||
84 | - params['/Name'] = PdfName(_name); | ||
85 | - | ||
86 | - if (alphaChannel == false && alpha) { | ||
87 | - final PdfImage _sMask = PdfImage._( | 51 | + im.params['/BitsPerComponent'] = const PdfNum(8); |
52 | + im.params['/Name'] = PdfName(im.name); | ||
53 | + im.params['/ColorSpace'] = const PdfName('/DeviceRGB'); | ||
54 | + | ||
55 | + if (alpha) { | ||
56 | + final PdfImage _sMask = PdfImage._alpha( | ||
88 | pdfDocument, | 57 | pdfDocument, |
89 | - image: image, | ||
90 | - width: width, | ||
91 | - height: height, | ||
92 | - alpha: alpha, | ||
93 | - alphaChannel: true, | ||
94 | - isRGB: false, | ||
95 | - jpeg: jpeg, | ||
96 | - orientation: orientation, | 58 | + image, |
59 | + width, | ||
60 | + height, | ||
61 | + orientation, | ||
97 | ); | 62 | ); |
98 | - params['/SMask'] = PdfIndirect(_sMask.objser, 0); | 63 | + im.params['/SMask'] = PdfIndirect(_sMask.objser, 0); |
99 | } | 64 | } |
100 | 65 | ||
101 | - if (isRGB) { | ||
102 | - params['/ColorSpace'] = const PdfName('/DeviceRGB'); | ||
103 | - } else { | ||
104 | - params['/ColorSpace'] = const PdfName('/DeviceGray'); | 66 | + final int w = width; |
67 | + final int h = height; | ||
68 | + final int s = w * h; | ||
69 | + final Uint8List out = Uint8List(s * 3); | ||
70 | + for (int i = 0; i < s; i++) { | ||
71 | + out[i * 3] = image[i * 4]; | ||
72 | + out[i * 3 + 1] = image[i * 4 + 1]; | ||
73 | + out[i * 3 + 2] = image[i * 4 + 2]; | ||
105 | } | 74 | } |
106 | 75 | ||
107 | - if (jpeg) { | ||
108 | - params['/Intent'] = const PdfName('/RelativeColorimetric'); | ||
109 | - } | 76 | + im.buf.putBytes(out); |
77 | + return im; | ||
110 | } | 78 | } |
111 | 79 | ||
112 | factory PdfImage.jpeg( | 80 | factory PdfImage.jpeg( |
@@ -115,84 +83,83 @@ class PdfImage extends PdfXObject { | @@ -115,84 +83,83 @@ class PdfImage extends PdfXObject { | ||
115 | PdfImageOrientation orientation, | 83 | PdfImageOrientation orientation, |
116 | }) { | 84 | }) { |
117 | assert(image != null); | 85 | assert(image != null); |
118 | - final PdfJpegInfo info = PdfJpegInfo(image); | ||
119 | 86 | ||
120 | - return PdfImage._( | 87 | + final PdfJpegInfo info = PdfJpegInfo(image); |
88 | + final PdfImage im = PdfImage._( | ||
121 | pdfDocument, | 89 | pdfDocument, |
122 | - image: image, | ||
123 | - width: info.width, | ||
124 | - height: info.height, | ||
125 | - jpeg: true, | ||
126 | - alpha: false, | ||
127 | - isRGB: info.isRGB, | ||
128 | - alphaChannel: false, | ||
129 | - orientation: orientation ?? info.orientation, | 90 | + info.width, |
91 | + info.height, | ||
92 | + orientation ?? info.orientation, | ||
130 | ); | 93 | ); |
131 | - } | ||
132 | - | ||
133 | - /// RGBA Image Data | ||
134 | - final Uint8List image; | ||
135 | - | ||
136 | - /// Image width | ||
137 | - final int _width; | ||
138 | - int get width => orientation.index >= 4 ? _height : _width; | ||
139 | - | ||
140 | - /// Image height | ||
141 | - final int _height; | ||
142 | - int get height => orientation.index < 4 ? _height : _width; | ||
143 | - | ||
144 | - /// Image has alpha channel | ||
145 | - final bool alpha; | ||
146 | - | ||
147 | - String _name; | ||
148 | 94 | ||
149 | - /// Process alphaChannel only | ||
150 | - final bool alphaChannel; | 95 | + im.params['/BitsPerComponent'] = const PdfNum(8); |
96 | + im.params['/Name'] = PdfName(im.name); | ||
97 | + im.params['/Intent'] = const PdfName('/RelativeColorimetric'); | ||
98 | + im.params['/Filter'] = const PdfName('/DCTDecode'); | ||
151 | 99 | ||
152 | - /// The image data is a jpeg image | ||
153 | - final bool jpeg; | 100 | + if (info.isRGB) { |
101 | + im.params['/ColorSpace'] = const PdfName('/DeviceRGB'); | ||
102 | + } else { | ||
103 | + im.params['/ColorSpace'] = const PdfName('/DeviceGray'); | ||
104 | + } | ||
154 | 105 | ||
155 | - /// The image data is a color RGB image | ||
156 | - final bool isRGB; | 106 | + im.buf.putBytes(image); |
107 | + return im; | ||
108 | + } | ||
157 | 109 | ||
158 | - /// The internal orientation of the image | ||
159 | - final PdfImageOrientation orientation; | 110 | + factory PdfImage._alpha( |
111 | + PdfDocument pdfDocument, | ||
112 | + Uint8List image, | ||
113 | + int width, | ||
114 | + int height, | ||
115 | + PdfImageOrientation orientation, | ||
116 | + ) { | ||
117 | + final PdfImage im = PdfImage._( | ||
118 | + pdfDocument, | ||
119 | + width, | ||
120 | + height, | ||
121 | + orientation, | ||
122 | + ); | ||
160 | 123 | ||
161 | - /// write the pixels to the stream | ||
162 | - @override | ||
163 | - void _prepare() { | ||
164 | - if (jpeg) { | ||
165 | - buf.putBytes(image); | ||
166 | - params['/Filter'] = const PdfName('/DCTDecode'); | ||
167 | - super._prepare(); | ||
168 | - return; | ||
169 | - } | 124 | + im.params['/BitsPerComponent'] = const PdfNum(8); |
125 | + im.params['/Name'] = PdfName(im.name); | ||
126 | + im.params['/ColorSpace'] = const PdfName('/DeviceGray'); | ||
170 | 127 | ||
171 | - final int w = _width; | ||
172 | - final int h = _height; | 128 | + final int w = width; |
129 | + final int h = height; | ||
173 | final int s = w * h; | 130 | final int s = w * h; |
174 | 131 | ||
175 | - final Uint8List out = Uint8List(alphaChannel ? s : s * 3); | 132 | + final Uint8List out = Uint8List(s); |
176 | 133 | ||
177 | - if (alphaChannel) { | ||
178 | for (int i = 0; i < s; i++) { | 134 | for (int i = 0; i < s; i++) { |
179 | out[i] = image[i * 4 + 3]; | 135 | out[i] = image[i * 4 + 3]; |
180 | } | 136 | } |
181 | - } else { | ||
182 | - for (int i = 0; i < s; i++) { | ||
183 | - out[i * 3] = image[i * 4]; | ||
184 | - out[i * 3 + 1] = image[i * 4 + 1]; | ||
185 | - out[i * 3 + 2] = image[i * 4 + 2]; | 137 | + |
138 | + im.buf.putBytes(out); | ||
139 | + return im; | ||
186 | } | 140 | } |
141 | + | ||
142 | + PdfImage._( | ||
143 | + PdfDocument pdfDocument, | ||
144 | + this._width, | ||
145 | + this._height, | ||
146 | + this.orientation, | ||
147 | + ) : super(pdfDocument, '/Image', isBinary: true) { | ||
148 | + params['/Width'] = PdfNum(_width); | ||
149 | + params['/Height'] = PdfNum(_height); | ||
187 | } | 150 | } |
188 | 151 | ||
189 | - buf.putBytes(out); | 152 | + /// Image width |
153 | + final int _width; | ||
154 | + int get width => orientation.index >= 4 ? _height : _width; | ||
190 | 155 | ||
191 | - super._prepare(); | ||
192 | - } | 156 | + /// Image height |
157 | + final int _height; | ||
158 | + int get height => orientation.index < 4 ? _height : _width; | ||
159 | + | ||
160 | + /// The internal orientation of the image | ||
161 | + final PdfImageOrientation orientation; | ||
193 | 162 | ||
194 | - /// Get the name | ||
195 | - /// | ||
196 | - /// @return a String value | ||
197 | - String get name => _name; | 163 | + /// Name of the image |
164 | + String get name => '/Image$objser'; | ||
198 | } | 165 | } |
-
Please register or login to post a comment