0

I am making C# application that is supposed to extract images from doc file and show all extracted images in Pictureboxes. I have following codes:

WRONG SOLUTION

using Microsoft.Office.Interop.Word;
  public IDataObject ImageData { get; private set; }

    public List<Image> GetImages(Document doc)
    {
        List<Image> image = new List<Image>();
        foreach (InlineShape shape in doc.InlineShapes)
        {

            shape.Range.Select();
            if (shape.Type == WdInlineShapeType.wdInlineShapePicture)
            {
                doc.ActiveWindow.Selection.Range.CopyAsPicture();
                ImageData = Clipboard.GetDataObject();
                Image img = (Image)ImageData.GetData(DataFormats.Bitmap);


                image.Add(img);
                /*
                bmp.Save("C:\\Users\\Akshay\\Pictures\\bitmaps\\test" + i.ToString() + ".bmp");
                */
            }
        }

        return image;
    }

The problem is that if I insert images on page 2 in my doc file then img becomes null. While if i insert all images in page 1 then it works perfectly fine. I am curious to know what is the mistake in above codes. Any help will be highly appreciated.

Zanub Khan
  • 81
  • 1
  • 6

2 Answers2

0

Here is the CORRECT solution:

    using Microsoft.Office.Interop.Word;
    public List<Image> GetImages(Document doc,Microsoft.Office.Interop.Word.Application app)
    {
        List<Image> images = new List<Image>();
        for (var i = 1; i <= app.ActiveDocument.InlineShapes.Count; i++)
        {
             var inlineShapeId = i;



             images.Add(SaveInlineShapeToFile(inlineShapeId, app));

            // STA is needed in order to access the clipboard

        }

         return images;
    }

        private Image SaveInlineShapeToFile(int inlineShapeId, Microsoft.Office.Interop.Word.Application app)
    {
        var inlineShape = app.ActiveDocument.InlineShapes[inlineShapeId];
        inlineShape.Select();
       app.Selection.Copy();

        // Check data is in the clipboard
        if (Clipboard.GetDataObject() != null)
        {
            var data = Clipboard.GetDataObject();

            // Check if the data conforms to a bitmap format
            if (data != null && data.GetDataPresent(DataFormats.Bitmap))
            {
                // Fetch the image and convert it to a Bitmap
                Image image = (Image)data.GetData(DataFormats.Bitmap, true);
                return image;
            }
        }
        return null;
    }
Zanub Khan
  • 81
  • 1
  • 6
0

Since you're dealing with inline shapes, you could also consider using the property .EnhMetaFileBits of the associated range object. This would allow you to avoid using the clipboard, but the image quality might be a bit worse, so it depends on your requirements:

var document = app.ActiveDocument;
var imageShape = document.InlineShapes[1];

imageShape.SaveAsImage(Path.Combine(document.Path, "image.jpg"), ImageFormat.Jpeg);

public static class ImageSaving
{
    //Based on:http://stackoverflow.com/questions/6512392/how-to-save-word-shapes-to-image-using-vba
    public static void SaveAsImage(this Word.InlineShape inlineShape, string saveAsFileName, ImageFormat imageFormat)
    {
        Directory.CreateDirectory(Path.GetDirectoryName(saveAsFileName));
        var range = inlineShape.Range;
        var bytes = (byte[])range.EnhMetaFileBits;
        //This byte array could simply be saved to a .wmf-file with File.WriteAllBytes()

        using (var stream = new MemoryStream(bytes))
        //Code for resizing based on:  http://stackoverflow.com/questions/7951734/an-unclear-converted-image-wmf-to-png
        using (var metaFile = new Metafile(stream))
        {
            var header = metaFile.GetMetafileHeader();

            //Calculate the scale based on the shape width
            var scale = header.DpiX / inlineShape.Width;

            var width = scale * metaFile.Width / header.DpiX * 100;

            var height = scale * metaFile.Height / header.DpiY * 100;

            using (var bitmap = new Bitmap((int)width, (int)height))
            using (var graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(Color.White);
                graphics.ScaleTransform(scale, scale);
                graphics.DrawImage(metaFile, 0, 0);

                //At this point you could do something else with the bitmap than save it
                bitmap.Save(saveAsFileName, imageFormat);
            }
        }

    }
}
Jbjstam
  • 874
  • 6
  • 13