can someone please confirm this is a bug?
Loading a WMF file as WmfImage from a file (see code, method 1) works, but loading it from a byte array (method 2) fails.
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
// Method 1: WmfImageData from file (works).
WmfImageData imageData1 = new WmfImageData("test.wmf");
PdfFormXObject xObject1 = new PdfFormXObject(imageData1, pdf);
document.Add(new Image(xObject1));
// Method 2: WmfImageData from byte[] (fails).
byte[] wmfBytes = File.ReadAllBytes("test.wmf");
WmfImageData imageData2 = new WmfImageData(wmfBytes);
PdfFormXObject xObject2 = new PdfFormXObject(imageData2, pdf);
document.Add(new Image(xObject2));
document.Close();
In my case the second method is useful because I would be able to generate a Microsoft Chart and convert it to a WMF byte array, and place it in the PDF without having to save it to a file first.
Method 2 throws this error:
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=itext.io
StackTrace:
at iText.IO.Util.UrlUtil.OpenStream(Uri url) in itext7-dotnet\itext\itext.io\itext\io\util\UrlUtil.cs:line 73
at iText.Kernel.Pdf.Canvas.Wmf.WmfImageData.ReadImageType(Uri source) in itext7-dotnet\itext\itext.kernel\itext\kernel\pdf\canvas\wmf\WmfImageData.cs:line 94
at iText.Kernel.Pdf.Canvas.Wmf.WmfImageData..ctor(Byte[] bytes) in itext7-dotnet\itext\itext.kernel\itext\kernel\pdf\canvas\wmf\WmfImageData.cs:line 76
The cause seems to be the constructor accepting a byte array in the iText.Kernel.Pdf.Canvas.Wmf.WmfImageData
class. It tries to check whether the argument is a proper WMF image, but does so by trying to load bytes from an URI which does not exist.
My suggestion for a fix is the addition of the following function in the WmfImageData class, and changing one line in the constructor from ReadImageType(url)
to ReadImageType(bytes)
.
private static byte[] ReadImageType(byte[] bytes) {
if (bytes.Length > 1) {
return new byte[] { bytes[0], bytes[1] };
}
return null;
}
Assuming this source: https://github.com/itext/itext7/blob/develop/kernel/src/main/java/com/itextpdf/kernel/pdf/canvas/wmf/WmfImageData.java
Yes, I can confirm the constructor which takes a byte[]
errantly references the base class field url
without that field being initialized.
I will leave the how to fix up to the community of developers working on that project as they have more familiarity with the inner workings of WMF images. However, if I'm reading their ReadImageType(url)
function properly, then it uses the first 8 bytes as a type descriptor.
User contributions licensed under CC BY-SA 3.0