2011-11-10 83 views
25

我正在使用OpenXML將圖像插入到我的文檔中。由微軟提供的代碼工作,但使圖像更小:使用OpenXML將圖像插入DocX並設置大小

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://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))); 
     } 

我需要使圖像的原始大小。我怎樣才能做到這一點? (我已經搜索瞭如何在這個過程之外做到這一點,但這不是我所期待的,我必須假設在給定的代碼中有某種尺寸屬性)。

編輯:更新的代碼(仍然沒有工作)

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), 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))); 
} 

回答

37

大小,在動車組(English Metric Unit -- read this for a good explanation),在該區段(的Cx和Cy)設置。 爲了得到一個PIC到DOCX我通常做它像這樣:

  1. 獲取圖像的尺寸和分辨率
  2. 計算在動車組圖像的寬度:wEmu = imgWidthPixels/imgHorizo​​ntalDpi * emuPerInch
  3. 計算禾木= imgHeightPixels/imgVerticalDpi * emuPerInch
  4. 計算在動車組中的最大頁面寬度(我發現,如果圖像太寬,它不會顯示)
  5. 如果圖像的寬度:在動車組圖像的高度在動車組中大於最大頁面寬度,我縮放圖像的寬度和高度,以便圖像的寬度等於頁面的寬度(當我說頁面時,我指的是「可用」頁面,即減去頁邊距):

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

  6. 然後我使用寬度爲Cx的值和高度賽揚的值,DW.ExtentA.Extents(的PIC.ShapePropertiesA.Transform2D) 。

注意,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以上你看到的。

UPDATE 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; 
... 
+0

對於寬度和高度圖像dpi是不變的?我如何計算這個? –

+0

我把它們視爲不恆定,但我還沒有找到一個他們不是。如果您使用[BitmapImage](http://msdn.microsoft.com/zh-cn/library/ms619218.aspx)類(System.Windows.Media.Imaging命名空間)打開圖像,它具有以下屬性,您可以使用:'PixelWidth','PixelHeight','DpiX','DpiY'。 – ssarabando

+0

我已將代碼示例添加到我的答案中。 – ssarabando

2

此代碼適用於我。

來源: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<ImagePart>("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; 
    } 
+1

小心添加源代碼找到它?因爲它不是你自己的「發現」。 – Styxxy

+0

http://msdn.microsoft.com/en-us/library/office/bb497430(v=office.15).aspx –

2

您可以對圖像給予其原始大小是這樣的:

首先,你得到的文件的寬度和高度:

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

然後轉換像素動車組這樣:

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

並打開您的文件時終於給的值,我的意思是在這行代碼的:

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

與計算值,以取代CX賽揚它看起來像這樣:

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

請注意,有兩行喲你必須給出計算值的代碼。

然後你有你的形象在它的原始大小,希望這可以幫助別人。