2011-11-10 36 views
25

Tôi đang sử dụng OpenXML để chèn hình ảnh vào tài liệu của mình. Mã do Microsoft cung cấp, nhưng làm cho hình ảnh nhỏ hơn nhiều:Chèn hình ảnh vào DocX bằng OpenXML và thiết lập kích thước

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

Tôi cần làm cho hình ảnh có kích thước ban đầu. Tôi có thể làm cái này như thế nào? (Tôi đã googled làm thế nào để làm điều này bên ngoài của quá trình này, nhưng đó không phải là những gì tôi đang tìm kiếm. Tôi phải giả định rằng có một số loại thuộc tính kích thước bên trong của mã nhất định).

Chỉnh sửa: Mã Cập nhật (vẫn không làm việc)

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

Trả lời

37

Các kích thước, trong EMUs (English Metric Unit -- read this for a good explanation), được thiết lập trong Extents (Cx và Cy). Để có được một pic vào một Docx Tôi thường làm điều đó như vậy:

  1. Nhận kích thước và độ phân giải
  2. Tính chiều rộng của hình ảnh trong EMUs của hình ảnh: wEmu = imgWidthPixels/imgHorizontalDpi * emuPerInch
  3. Tính chiều cao của hình ảnh trong EMUs: Hemu = imgHeightPixels/imgVerticalDpi * emuPerInch
  4. Tính chiều rộng trang tối đa trong EMUs (tôi đã phát hiện ra rằng nếu hình ảnh là quá rộng, nó sẽ không hiển thị)
  5. Nếu chiều rộng của hình ảnh trong EMUs lớn hơn chiều rộng của trang tối đa, tôi chia tỷ lệ chiều rộng và chiều cao của hình ảnh sao cho chiều rộng của hình ảnh bằng với trang (khi tôi nói trang, tôi đang đề cập đến trang "có thể sử dụng", trừ lề):

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

  6. sau đó tôi sử dụng độ rộng như giá trị của Cx và chiều cao như giá trị của Cy, cả trong DW.Extent và trong A.Extents (của A.Transform2D của PIC.ShapeProperties) .

Lưu ý rằng giá trị emuPerInch là 914400.
Tôi đã chạy này (trong một dịch vụ) nhưng tôi không có mã với tôi ngay bây giờ.

CẬP NHẬT

Đây là mã tôi sử dụng:

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

Trong trường hợp của tôi, các biện pháp trang của tôi là tính bằng cm, vì thế mà emusPerCm bạn nhìn thấy ở trên.

UPDATE 2 (để trả lời @andw)

Để có tập tin bị khóa trong thời gian tối thiểu có thể, mở nó bằng một FileStream và vượt qua dòng kết quả vào StreamSource tài sản của BitmapImage:

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

Hằng số dpi hình ảnh cho cả chiều rộng và chiều cao? làm thế nào để tính toán điều này? –

+0

Tôi đối xử với họ không phải là không đổi nhưng tôi vẫn chưa tìm được nơi họ không ở. Nếu bạn mở hình ảnh với lớp [BitmapImage] (http://msdn.microsoft.com/en-us/library/ms619218.aspx) (không gian tên System.Windows.Media.Imaging), nó có các thuộc tính sau đây bạn có thể sử dụng: 'PixelWidth',' PixelHeight', 'DpiX',' DpiY'. – ssarabando

+0

Tôi đã thêm mẫu mã vào câu trả lời của mình. – ssarabando

2

Mã này phù hợp với tôi.

Nguồn: 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

Chăm sóc để thêm nguồn nơi bạn tìm thấy điều này? Vì nó không phải là "phát hiện" của riêng bạn. – Styxxy

+0

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

2

Bạn có thể cho đến hình ảnh kích thước ban đầu của nó theo cách này:

Trước tiên, bạn có được chiều rộng và chiều cao của file:

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

Sau đó chuyển đổi các pixel đến EMUs theo cách này:

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

Và cuối cùng cung cấp cho các giá trị khi mở tập tin của bạn, tôi có nghĩa là trong dòng này của mã của bạn:

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

thay CxCy với các giá trị tính toán của bạn để có vẻ như sau:

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

Lưu ý có hai dòng trong yo mã ur nơi bạn phải cung cấp các giá trị được tính.

Sau đó, bạn có hình ảnh ở kích thước ban đầu, hy vọng điều này sẽ giúp ai đó.

Các vấn đề liên quan