注意:此答案使用 iText7 for .NET,而不是已弃用的 iTextSharp
这是控制台应用程序中功能的一个工作示例。这会将 mschart 放置为具有完美质量的矢量图像,无论您放大多少。
static void Main(string[] args) {
// Create a chart.
Chart chart1 = new Chart();
chart1.ChartAreas.Add(new ChartArea());
Series series1 = new Series();
series1.Points.Add(new DataPoint(1, 2));
series1.Points.Add(new DataPoint(2, 4));
series1.Points.Add(new DataPoint(3, 1));
chart1.Series.Add(series1);
// Save the chart to an in-memory (emf) metafile.
Metafile metafile;
using (MemoryStream str1 = new MemoryStream()) {
chart1.SaveImage(str1, ChartImageFormat.Emf);
byte[] emfBytes = str1.ToArray();
IntPtr hemf = SetEnhMetaFileBits((uint) emfBytes.Length, emfBytes);
metafile = new Metafile(hemf, true);
}
// Convert the metafile to a WMF and write to a file.
byte[] wmfBytes = GetWmfByteArray(metafile);
File.WriteAllBytes(@"c:\temp\test.wmf", wmfBytes);
// Initialize the document.
PdfWriter writer = new PdfWriter(@"c:\temp\test.pdf");
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf);
// Add the image.
PdfFormXObject xObject1 = new PdfFormXObject(new WmfImageData(@"c:\temp\test.wmf"), pdf);
Image img1 = new Image(xObject1);
document.Add(img1);
document.Close();
}
[DllImport("gdiplus.dll", SetLastError = true)]
static extern int GdipEmfToWmfBits(int hEmf, int uBufferSize, byte[] bBuffer, int iMappingMode, EmfToWmfBitsFlags flags);
[DllImport("gdi32.dll")]
public static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] lpBuffer);
[Flags]
private enum EmfToWmfBitsFlags
{
EmfToWmfBitsFlagsDefault = 0x00000000,
EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
EmfToWmfBitsFlagsNoXORClip = 0x00000004
}
private static byte[] GetWmfByteArray(Metafile mf) {
const int MM_ANISOTROPIC = 8;
int handle = mf.GetHenhmetafile().ToInt32();
int bufferSize = GdipEmfToWmfBits(handle, 0, null, MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsIncludePlaceable);
byte[] buf = new byte[bufferSize];
GdipEmfToWmfBits(handle, bufferSize, buf, MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsIncludePlaceable);
return buf;
}
这是另一个适用于旧版 iTextSharp 的片段:
// Create a chart.
Chart chart1 = new Chart();
chart1.ChartAreas.Add(new ChartArea());
Series series1 = new Series();
series1.Points.Add(new DataPoint(1, 2));
series1.Points.Add(new DataPoint(2, 4));
series1.Points.Add(new DataPoint(3, 1));
chart1.Series.Add(series1);
// Save to metafile.
chart1.SaveImage(@"c:\temp\test.emf", ChartImageFormat.Emf);
// Convert to WMF.
Metafile mf = new Metafile(@"c:\temp\test.emf");
byte[] arr = GetWmfByteArray(mf);
ImgWMF wmf = new ImgWMF(arr);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(wmf);
// Create PDF.
Document document = new Document();
PdfWriter.GetInstance(document, new FileStream(@"c:\temp\test.pdf", FileMode.Create));
document.Open();
document.Add(img);
document.Close();
请注意,由于存在错误,目前没有办法(据我所知)将内存中的 WMF 放置在 iText PDF 中而不从文件中加载它。我提出了一个带有修复的拉取请求,所以希望他们很快就会合并它。
更新!拉取请求已合并,此问题已在iText 7.1.8中修复:您现在可以这样做new WmfImageData(wmfBytes)
,无需写入文件。
更新(2020 年 4 月):不幸的是,最近的 Windows 更新 (KB4549951) 似乎破坏了 GdipEmfToWmfBits 函数(用于从 EMF 转换为 WMF)。除了卸载更新之外,我还不知道永久的解决方案。