import 'dart:io'; import 'dart:typed_data'; import 'dart:math'; class ReplaceContent { DocxImage? img; String? value; /// Only Text to replace; null if it's image! ReplaceContent({this.value, this.img}) { if (img != null && value != null) throw StateError('Can\'t have value and image define'); if (img == null && value == null) throw StateError('You need define value or image'); } } /// 16cm * 360 000 = 5 760 000 EMU const int maxWidth = 16 * 360000; /// 24cm * 360 000 = 8 640 000 EMU const int maxHeight = 24 * 360000; class DocxImage { int? id; int? sizeX; /// in EMU int? sizeY; /// in EMU late File file; /// [file] support JPG/JPEG and PNG /// [sizeX] and [sizeY] use EMU metrics BUT init a instance in PIXEL DocxImage({required File file, this.sizeX, this.sizeY}) { this.file = file; if (sizeX == null && sizeY == null) { Uint8List bytes = file.readAsBytesSync(); String extensions = file.path.substring(file.path.lastIndexOf('.') + 1); if (extensions == 'png') { sizeX = (bytes.buffer.asByteData().getUint32(16)) * 9525; sizeY = (bytes.buffer.asByteData().getUint32(20)) * 9525; } else if (extensions == 'jpg' || extensions == 'jpeg') { List sizes = getSizeJpg(bytes); if (sizes.isEmpty) throw StateError('Can\'t get the size of Jpg image'); sizeX = sizes[0]; sizeY = sizes[1]; } } else if (sizeX != null && sizeY != null) { sizeX = sizeX! * 9525; sizeY = sizeY! * 9525; } else throw StateError('Only sizeX or sizeY is defined!'); // Limit size of image double scale = min(maxWidth / sizeX!, maxHeight / sizeY!); scale = scale > 1 ? 1 : scale; sizeX = (sizeX! * scale).round(); sizeY = (sizeY! * scale).round(); } } /// Return size of Jpg => [width, height] List getSizeJpg(Uint8List bytes) { int i = 0; while (i < bytes.length) { while(bytes[i]==0xff) i++; int marker = bytes[i++]; if(marker==0xd8) // SOI continue; if(marker==0xd9) // EOI break; if(0xd0<=marker && marker<=0xd7) continue; if(marker==0x01) // TEM continue; int length = (bytes[i] << 8) | bytes[i + 1]; i += 2; if (marker == 0xc0) return [(bytes[i + 1] << 8) + bytes[i + 2], // Width (bytes[i + 3] << 8) + bytes[i + 4]]; // Height i += length - 2; } return []; }