addImagePage method
Implementation
Future<int?> addImagePage(Uint8List encoded, {Size? size, double margin = 0}) async {
final UPdfRaster? raster = await UPdfEdit.rasterizeImage(encoded, maxSize: 4096);
if (raster == null || raster.isEmpty) return null;
final double pageWidth = size?.width ?? raster.width.toDouble();
final double pageHeight = size?.height ?? raster.height.toDouble();
final int pixels = raster.width * raster.height;
final Uint8List colour = Uint8List(pixels * 3);
final Uint8List alpha = Uint8List(pixels);
bool transparent = false;
for (int i = 0; i < pixels; i++) {
colour[i * 3] = raster.rgba[i * 4];
colour[i * 3 + 1] = raster.rgba[i * 4 + 1];
colour[i * 3 + 2] = raster.rgba[i * 4 + 2];
alpha[i] = raster.rgba[i * 4 + 3];
if (alpha[i] != 255) transparent = true;
}
int? maskNumber;
if (transparent) {
maskNumber = allocate();
_objects[maskNumber] = _stream(
alpha,
extra: <String, Object?>{
"Type": const UPdfName("XObject"),
"Subtype": const UPdfName("Image"),
"Width": raster.width,
"Height": raster.height,
"ColorSpace": const UPdfName("DeviceGray"),
"BitsPerComponent": 8,
},
);
}
final int imageNumber = allocate();
_objects[imageNumber] = _stream(
colour,
extra: <String, Object?>{
"Type": const UPdfName("XObject"),
"Subtype": const UPdfName("Image"),
"Width": raster.width,
"Height": raster.height,
"ColorSpace": const UPdfName("DeviceRGB"),
"BitsPerComponent": 8,
if (maskNumber != null) "SMask": UPdfRef(maskNumber, 0),
},
);
final double drawWidth = pageWidth - margin * 2;
final double drawHeight = pageHeight - margin * 2;
final double scale = min(drawWidth / raster.width, drawHeight / raster.height);
final double placedWidth = raster.width * scale;
final double placedHeight = raster.height * scale;
final double offsetX = (pageWidth - placedWidth) / 2;
final double offsetY = (pageHeight - placedHeight) / 2;
final int contents = allocate();
_objects[contents] = _stream(
Uint8List.fromList(
utf8.encode("q ${UPdfSerializer.number(placedWidth)} 0 0 ${UPdfSerializer.number(placedHeight)} ${UPdfSerializer.number(offsetX)} ${UPdfSerializer.number(offsetY)} cm /Im0 Do Q"),
),
);
final int number = allocate();
_objects[number] = UPdfDict(<String, Object?>{
"Type": const UPdfName("Page"),
"MediaBox": <Object?>[0, 0, pageWidth, pageHeight],
"Resources": UPdfDict(<String, Object?>{
"XObject": UPdfDict(<String, Object?>{"Im0": UPdfRef(imageNumber, 0)}),
}),
"Contents": UPdfRef(contents, 0),
});
_pages.add(number);
return number;
}