使用OpenXML将图像插入DocX并设置大小

我正在使用OpenXML将图像插入到我的文档中。 Microsoft提供的代码可以工作,但会使图像更小:

public static void InsertAPicture(string document, string fileName) { using (WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(document, true)) { MainDocumentPart mainPart = wordprocessingDocument.MainDocumentPart; ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg); using (FileStream stream = new FileStream(fileName, FileMode.Open)) { imagePart.FeedData(stream); } AddImageToBody(wordprocessingDocument, mainPart.GetIdOfPart(imagePart)); } } private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId) { // Define the reference of the image. var element = new Drawing( new DW.Inline( new DW.Extent() { Cx = 990000L, Cy = 792000L }, new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new DW.DocProperties() { Id = (UInt32Value)1U, Name = "Picture 1" }, new DW.NonVisualGraphicFrameDrawingProperties( new A.GraphicFrameLocks() { NoChangeAspect = true }), new A.Graphic( new A.GraphicData( new PIC.Picture( new PIC.NonVisualPictureProperties( new PIC.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = "New Bitmap Image.jpg" }, new PIC.NonVisualPictureDrawingProperties()), new PIC.BlipFill( new A.Blip( new A.BlipExtensionList( new A.BlipExtension() { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" }) ) { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }, new A.Stretch( new A.FillRectangle())), new PIC.ShapeProperties( new A.Transform2D( new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = 990000L, Cy = 792000L }), new A.PresetGeometry( new A.AdjustValueList() ) { Preset = A.ShapeTypeValues.Rectangle })) ) { Uri = "http://sofzh.miximages.com/c%23/dprocessingDocument = WordprocessingDocument.Open(document, true)) { MainDocumentPart mainPart = wordprocessingDocument.MainDocumentPart; ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg); using (FileStream stream = new FileStream(fileName, FileMode.Open)) { imagePart.FeedData(stream); } AddImageToBody(wordprocessingDocument, mainPart.GetIdOfPart(imagePart), fileName); } } private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId, string fileName) { var img = new BitmapImage(new Uri(fileName, UriKind.RelativeOrAbsolute)); var widthPx = img.PixelWidth; var heightPx = img.PixelHeight; var horzRezDpi = img.DpiX; var vertRezDpi = img.DpiY; const int emusPerInch = 914400; const int emusPerCm = 360000; var maxWidthCm = 16.51; var widthEmus = (long)(widthPx / horzRezDpi * emusPerInch); var heightEmus = (long)(heightPx / vertRezDpi * emusPerInch); var maxWidthEmus = (long)(maxWidthCm * emusPerCm); if (widthEmus > maxWidthEmus) { var ratio = (heightEmus * 1.0m) / widthEmus; widthEmus = maxWidthEmus; heightEmus = (long)(widthEmus * ratio); } // Define the reference of the image. var element = new Drawing( new DW.Inline( new DW.Extent() { Cx = 990000L, Cy = 792000L }, new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new DW.DocProperties() { Id = (UInt32Value)1U, Name = "Picture 1" }, new DW.NonVisualGraphicFrameDrawingProperties( new A.GraphicFrameLocks() { NoChangeAspect = true }), new A.Graphic( new A.GraphicData( new PIC.Picture( new PIC.NonVisualPictureProperties( new PIC.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = "New Bitmap Image.jpg" }, new PIC.NonVisualPictureDrawingProperties()), new PIC.BlipFill( new A.Blip( new A.BlipExtensionList( new A.BlipExtension() { Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}" }) ) { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }, new A.Stretch( new A.FillRectangle())), new PIC.ShapeProperties( new A.Transform2D( new A.Offset() { X = 0L, Y = 0L }, new A.Extents() { Cx = widthEmus, Cy = heightEmus }), new A.PresetGeometry( new A.AdjustValueList() ) { Preset = A.ShapeTypeValues.Rectangle })) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) ) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U, EditId = "50D07946" }); // Append the reference to body, the element should be in a Run. wordDoc.MainDocumentPart.Document.Body.AppendChild(new Paragraph(new Run(element))); } 

EMU中的尺寸( 英制公制单位 – 阅读此内容以获得详细说明 ),在范围(Cx和Cy)中设置。 为了将图片放入DocX,我通常会这样做:

  1. 获取图像的尺寸和分辨率
  2. 在EMU中计算图像的宽度:wEmu = imgWidthPixels / imgHorizo​​ntalDpi * emuPerInch
  3. 在EMU中计算图像的高度:hEmu = imgHeightPixels / imgVerticalDpi * emuPerInch
  4. 计算EMU中的最大页面宽度(我发现如果图像太宽,则不会显示)
  5. 如果EMU中图像的宽度大于最大页面宽度,我会缩放图像的宽度和高度,使图像的宽度等于页面的宽度(当我说页面时,我指的是“可用”页面,这是减去边际):

    var ratio = hEmu / wEmu;
    wEmu = maxPageWidthEmu;
    hEmu = wEmu * ratio;

  6. 然后我使用宽度作为Cx的值,高度作为Cy的值,在DW.ExtentA.ExtentsA.Transform2DPIC.ShapeProperties )中。

请注意,emuPerInch值为914400。
我有这个运行(在服务中),但我现在没有代码。

UPDATE

这是我使用的代码:

 var img = new BitmapImage(new Uri(fileName, UriKind.RelativeOrAbsolute)); var widthPx = img.PixelWidth; var heightPx = img.PixelHeight; var horzRezDpi = img.DpiX; var vertRezDpi = img.DpiY; const int emusPerInch = 914400; const int emusPerCm = 360000; var widthEmus = (long)(widthPx / horzRezDpi * emusPerInch); var heightEmus = (long)(heightPx / vertRezDpi * emusPerInch); var maxWidthEmus = (long)(maxWidthCm * emusPerCm); if (widthEmus > maxWidthEmus) { var ratio = (heightEmus * 1.0m) / widthEmus; widthEmus = maxWidthEmus; heightEmus = (long)(widthEmus * ratio); } 

就我而言,我的页面的度量单位是厘米,因此您在上面看到的是emusPerCm。

更新2(回答@andw)

要在最短的时间内锁定文件,请使用FileStream打开它,并将结果流传递给BitmapImageStreamSource属性:

 var img = new BitmapImage(); using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { img.BeginInit(); img.StreamSource = fs; img.EndInit(); } // The file is now unlocked var widthPx = img.PixelWidth; ... 

您可以通过以下方式为图像提供原始大小:

首先,您获得文件的宽度和高度:

 int iWidth = 0; int iHeight = 0; using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap("yourFilePath")) { iWidth = bmp.Width; iHeight = bmp.Height; } 

然后以这种方式 像素 转换EMU

 iWidth = (int)Math.Round((decimal)iWidth * 9525); iHeight = (int)Math.Round((decimal)iHeight * 9525); 

最后在打开文件时给出值,我的意思是在你的代码的这一行:

 new DW.Extent() { Cx = 990000L, Cy = 792000L }, 

CxCy替换为您的计算值,使其如下所示:

 new DW.Extent() { Cx = iWidth, Cy = iHeight }, 

请注意,代码中有两行必须提供计算值。

然后你有你的原始大小的图像,希望这有助于某人。

这段代码适合我。

资料来源: http : //msdn.microsoft.com/en-us/library/office/bb497430(v = office.15).aspx

  public static void Do() { string filename = @"c:\temp\m.docx"; byte[] reportData = GetWordReport(); // File.WriteAllBytes(filename, reportData); //MessageBox.Show("File " + filename + " created"); } private static byte[] GetWordReport() { // using (MemoryStream stream = new MemoryStream()) // { //var template = GetTemplateData(); //stream.Write(template, 0, template.Length); using (WordprocessingDocument docx = WordprocessingDocument.Open(@"c:\temp\m.docx", true)) { // Some changes on docx docx.MainDocumentPart.Document = GenerateMainDocumentPart(6,4); var imagePart = docx.MainDocumentPart.AddNewPart("image/jpeg", "rIdImagePart1"); GenerateImagePart(imagePart); } // stream.Seek(0, SeekOrigin.Begin); // return stream.ToArray(); // } return null; } private static byte[] GetTemplateData() { using (MemoryStream targetStream = new MemoryStream()) using (BinaryReader sourceReader = new BinaryReader(File.Open(@"c:\temp\m_2.docx", FileMode.Open))) { byte[] buffer = new byte[4096]; int num = 0; do { num = sourceReader.Read(buffer, 0, 4096); if (num > 0) targetStream.Write(buffer, 0, num); } while (num > 0); targetStream.Seek(0, SeekOrigin.Begin); return targetStream.ToArray(); } } private static void GenerateImagePart(OpenXmlPart part) { using (Stream imageStream = File.Open(@"c:\temp\image002.jpg", FileMode.Open)) { part.FeedData(imageStream); } } private static Document GenerateMainDocumentPart(int cx,int cy) { long LCX = cx*261257L; long LCY = cy*261257L; var element = new Document( new Body( new Paragraph( new Run( new RunProperties( new NoProof()), new Drawing( new wp.Inline( new wp.Extent() { Cx = LCX, Cy = LCY }, new wp.EffectExtent() { LeftEdge = 0L, TopEdge = 19050L, RightEdge = 0L, BottomEdge = 0L }, new wp.DocProperties() { Id = (UInt32Value)1U, Name = "Picture 0", Description = "Forest Flowers.jpg" }, new wp.NonVisualGraphicFrameDrawingProperties( new a.GraphicFrameLocks() { NoChangeAspect = true }), new a.Graphic( new a.GraphicData( new pic.Picture( new pic.NonVisualPictureProperties( new pic.NonVisualDrawingProperties() { Id = (UInt32Value)0U, Name = "Forest Flowers.jpg" }, new pic.NonVisualPictureDrawingProperties()), new pic.BlipFill( new a.Blip() { Embed = "rIdImagePart1", CompressionState = a.BlipCompressionValues.Print }, new a.Stretch( new a.FillRectangle())), new pic.ShapeProperties( new a.Transform2D( new a.Offset() { X = 0L, Y = 0L }, new a.Extents() { Cx = LCX, Cy = LCY }), new a.PresetGeometry( new a.AdjustValueList() ) { Preset = a.ShapeTypeValues.Rectangle })) ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) ) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U })) ) { RsidParagraphAddition = "00A2180E", RsidRunAdditionDefault = "00EC4DA7" }, new SectionProperties( new PageSize() { Width = (UInt32Value)11906U, Height = (UInt32Value)16838U }, new PageMargin() { Top = 1440, Right = (UInt32Value)1800U, Bottom = 1440, Left = (UInt32Value)1800U, Header = (UInt32Value)851U, Footer = (UInt32Value)992U, Gutter = (UInt32Value)0U }, new Columns() { Space = ((UInt32Value)425U).ToString() }, new DocGrid() { Type = DocGridValues.Lines, LinePitch = 312 } ) { RsidR = "00A2180E", RsidSect = "00A2180E" })); return element; }