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