91 lines
2.4 KiB
Dart
91 lines
2.4 KiB
Dart
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<int> 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<int> 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 [];
|
||
} |