David PHAM-VAN

Improve image buffer management

... ... @@ -11,6 +11,7 @@
- Uniformize examples
- Fix context painting empty Table
- Fix Text decoration placements
- Improve image buffer management
## 1.5.0
... ...
... ... @@ -33,11 +33,6 @@ enum PdfImageOrientation {
class PdfImage extends PdfXObject {
/// Creates a new [PdfImage] instance.
///
/// @param image an [Uint8List] value
/// @param width
/// @param height
/// @param alpha if the image is transparent
factory PdfImage(
PdfDocument pdfDocument, {
@required Uint8List image,
... ... @@ -45,68 +40,41 @@ class PdfImage extends PdfXObject {
@required int height,
bool alpha = true,
PdfImageOrientation orientation = PdfImageOrientation.topLeft,
}) =>
PdfImage._(
pdfDocument,
image: image,
width: width,
height: height,
alpha: alpha,
alphaChannel: false,
isRGB: true,
jpeg: false,
orientation: orientation,
);
}) {
final PdfImage im = PdfImage._(
pdfDocument,
width,
height,
orientation,
);
PdfImage._(
PdfDocument pdfDocument, {
@required this.image,
@required int width,
@required int height,
@required this.alpha,
@required this.alphaChannel,
@required this.isRGB,
@required this.jpeg,
@required this.orientation,
}) : assert(alphaChannel == false || alpha == true),
assert(width != null),
assert(height != null),
assert(jpeg != null),
assert(isRGB != null),
assert(orientation != null),
_width = width,
_height = height,
super(pdfDocument, '/Image', isBinary: true) {
_name = '/Image$objser';
params['/Width'] = PdfNum(width);
params['/Height'] = PdfNum(height);
params['/BitsPerComponent'] = const PdfNum(8);
params['/Name'] = PdfName(_name);
if (alphaChannel == false && alpha) {
final PdfImage _sMask = PdfImage._(
im.params['/BitsPerComponent'] = const PdfNum(8);
im.params['/Name'] = PdfName(im.name);
im.params['/ColorSpace'] = const PdfName('/DeviceRGB');
if (alpha) {
final PdfImage _sMask = PdfImage._alpha(
pdfDocument,
image: image,
width: width,
height: height,
alpha: alpha,
alphaChannel: true,
isRGB: false,
jpeg: jpeg,
orientation: orientation,
image,
width,
height,
orientation,
);
params['/SMask'] = PdfIndirect(_sMask.objser, 0);
im.params['/SMask'] = PdfIndirect(_sMask.objser, 0);
}
if (isRGB) {
params['/ColorSpace'] = const PdfName('/DeviceRGB');
} else {
params['/ColorSpace'] = const PdfName('/DeviceGray');
final int w = width;
final int h = height;
final int s = w * h;
final Uint8List out = Uint8List(s * 3);
for (int i = 0; i < s; i++) {
out[i * 3] = image[i * 4];
out[i * 3 + 1] = image[i * 4 + 1];
out[i * 3 + 2] = image[i * 4 + 2];
}
if (jpeg) {
params['/Intent'] = const PdfName('/RelativeColorimetric');
}
im.buf.putBytes(out);
return im;
}
factory PdfImage.jpeg(
... ... @@ -115,84 +83,83 @@ class PdfImage extends PdfXObject {
PdfImageOrientation orientation,
}) {
assert(image != null);
final PdfJpegInfo info = PdfJpegInfo(image);
return PdfImage._(
final PdfJpegInfo info = PdfJpegInfo(image);
final PdfImage im = PdfImage._(
pdfDocument,
image: image,
width: info.width,
height: info.height,
jpeg: true,
alpha: false,
isRGB: info.isRGB,
alphaChannel: false,
orientation: orientation ?? info.orientation,
info.width,
info.height,
orientation ?? info.orientation,
);
}
/// RGBA Image Data
final Uint8List image;
/// Image width
final int _width;
int get width => orientation.index >= 4 ? _height : _width;
/// Image height
final int _height;
int get height => orientation.index < 4 ? _height : _width;
im.params['/BitsPerComponent'] = const PdfNum(8);
im.params['/Name'] = PdfName(im.name);
im.params['/Intent'] = const PdfName('/RelativeColorimetric');
im.params['/Filter'] = const PdfName('/DCTDecode');
/// Image has alpha channel
final bool alpha;
if (info.isRGB) {
im.params['/ColorSpace'] = const PdfName('/DeviceRGB');
} else {
im.params['/ColorSpace'] = const PdfName('/DeviceGray');
}
String _name;
im.buf.putBytes(image);
return im;
}
/// Process alphaChannel only
final bool alphaChannel;
factory PdfImage._alpha(
PdfDocument pdfDocument,
Uint8List image,
int width,
int height,
PdfImageOrientation orientation,
) {
final PdfImage im = PdfImage._(
pdfDocument,
width,
height,
orientation,
);
/// The image data is a jpeg image
final bool jpeg;
im.params['/BitsPerComponent'] = const PdfNum(8);
im.params['/Name'] = PdfName(im.name);
im.params['/ColorSpace'] = const PdfName('/DeviceGray');
/// The image data is a color RGB image
final bool isRGB;
final int w = width;
final int h = height;
final int s = w * h;
/// The internal orientation of the image
final PdfImageOrientation orientation;
final Uint8List out = Uint8List(s);
/// write the pixels to the stream
@override
void _prepare() {
if (jpeg) {
buf.putBytes(image);
params['/Filter'] = const PdfName('/DCTDecode');
super._prepare();
return;
for (int i = 0; i < s; i++) {
out[i] = image[i * 4 + 3];
}
final int w = _width;
final int h = _height;
final int s = w * h;
im.buf.putBytes(out);
return im;
}
final Uint8List out = Uint8List(alphaChannel ? s : s * 3);
PdfImage._(
PdfDocument pdfDocument,
this._width,
this._height,
this.orientation,
) : super(pdfDocument, '/Image', isBinary: true) {
params['/Width'] = PdfNum(_width);
params['/Height'] = PdfNum(_height);
}
if (alphaChannel) {
for (int i = 0; i < s; i++) {
out[i] = image[i * 4 + 3];
}
} else {
for (int i = 0; i < s; i++) {
out[i * 3] = image[i * 4];
out[i * 3 + 1] = image[i * 4 + 1];
out[i * 3 + 2] = image[i * 4 + 2];
}
}
/// Image width
final int _width;
int get width => orientation.index >= 4 ? _height : _width;
buf.putBytes(out);
/// Image height
final int _height;
int get height => orientation.index < 4 ? _height : _width;
super._prepare();
}
/// The internal orientation of the image
final PdfImageOrientation orientation;
/// Get the name
///
/// @return a String value
String get name => _name;
/// Name of the image
String get name => '/Image$objser';
}
... ...