Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resize and image in a PowerPoint presentation using c# and OpenXML

Apologies if this has already been answered but I've seen plenty of posts along similar lines and nothing has so far helped me.

Basically I'm building an app that takes a PowerPoint 'template' and replaces text and images sourced from a database. Most of it is complete but I'm struggling to solve a problem when I replace images. The template has lots of blank images inserted, ready to replace and they are all square as they are just placeholders. I can replace them no problem but the new images are stretched either vertically or horizontally depending on the image I pull from the database. It's basically filling the placeholders shape.

I must admit I am finding it hard to get my head around the document model so maybe I'm trying to change the wrong thing, I had tried to change the "extents" properties of the blip.parent.shape but I was guessing and got no joy.

Below is the code that works as far as swapping the image out (credit to original author amos http://atakala.com/browser/Item.aspx?user_id=amos&dict_id=2291). I'm not sure where even to attempt the resize, once the image is in place or before... any help would be much appreciated. I'm not worried about the actual size for now, I can calculate that myself, it's just being able to change the image size that is the problem.

As well as the sample code (which might not be that useful) I've linked to my sample project. The sample and files should all be placed in c:\test to work. It's just a few images, the c# project and program.cs file, plus a sample PPTX file.

DOWNLOAD Sample zip file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using d = DocumentFormat.OpenXml.Drawing;
using System.IO;

namespace PPTX_Image_Replace_test
{
class Program
{
    static void Main(string[] args)
    {
        TestImageReplace(@"C:\test\TestImageReplaceAndResize.pptx");
    }

    public static void TestImageReplace(string fileName)
    {
        // make a copy of the original and edit that
        string outputFileName = Path.Combine(Path.GetDirectoryName(fileName), "New_" + Path.GetFileName(fileName));
        File.Copy(fileName, outputFileName,true);


        using (PresentationDocument document = PresentationDocument.Open(outputFileName, true))
        {
            ReplaceFirstImageMatchingAltText(document, @"C:\test\Arrow_UP.png", "changeme");
        }
    }

    public static void ReplaceFirstImageMatchingAltText(PresentationDocument presentationDocument, string newImagePath, string alternateTextToFind)
    {
        OpenXmlElementList slideIds = presentationDocument.PresentationPart.Presentation.SlideIdList.ChildElements;

        foreach (SlideId sID in slideIds) // loop thru the SlideIDList
        {
            string relId = sID.RelationshipId; // get first slide relationship
            SlidePart slide = (SlidePart)presentationDocument.PresentationPart.GetPartById(relId); // Get the slide part from the relationship ID. 

            var pictures = slide.Slide.Descendants<ShapeTree>().First().Descendants<Picture>().ToList();
            foreach (var picture in pictures)
            {
                // get photo desc to see if it matches search text 
                var nonVisualPictureProperties = picture.Descendants<NonVisualPictureProperties>().FirstOrDefault();
                if (nonVisualPictureProperties == null)
                    continue;
                var nonVisualDrawingProperties99 = nonVisualPictureProperties.Descendants<NonVisualDrawingProperties>().FirstOrDefault();
                if (nonVisualDrawingProperties99 == null)
                    continue;
                var desc = nonVisualDrawingProperties99.Description;
                if (desc == null || desc.Value == null || !desc.Value.Contains(alternateTextToFind))
                    continue;

                BlipFill blipFill = picture.Descendants<BlipFill>().First();
                var blip = blipFill.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().First();
                string embedId = blip.Embed; // now we need to find the embedded content and update it. 


                // find the content 
                ImagePart imagePart = (ImagePart)slide.GetPartById(embedId);
                if (imagePart != null)
                {
                    using (FileStream fileStream = new FileStream(newImagePath, FileMode.Open))
                    {
                        imagePart.FeedData(fileStream);
                        fileStream.Close();
                    }

                    return; // found the photo and replaced it. 
                }
            }
        }
    }
}
}
like image 530
Alan Schofield Avatar asked Mar 14 '16 12:03

Alan Schofield


People also ask

How do you resize an image in PowerPoint?

To resize a picture, on the Picture Tools Format tab, in the Size group, enter the new measurements into the Height and Width boxes. To resize a shape or other object, on the Drawing Tools Format tab, in the Size group, enter the measurements you want into the Height and Width boxes.

How do you resize a picture in PowerPoint answer?

On the shortcut menu, click Format<object type>. In the dialog box, click the Size tab. Under Scale, enter the percentage of the original height or width you want the object resized to. Note: To change the proportions but keep the original aspect ratio, select the Lock aspect ratio check box.


1 Answers

Typically after days for getting nowhere, as soon as I post the question, I find the answer! It was remarkably simple in the end.

I already had a reference to the picture so I simply modifed the trasnform there, the last bit of code now looks like this..

                // find the content 
                ImagePart imagePart = (ImagePart)slide.GetPartById(embedId);
                if (imagePart != null)
                {

                    d.Transform2D transform =  picture.Descendants<d.Transform2D>().First();
                    transform.Extents.Cx = 800000; // replace with correct calcualted values eventually
                    transform.Extents.Cy = 400000; // replace with correct calculated values eventually

                    using (FileStream fileStream = new FileStream(newImagePath, FileMode.Open))
                    {
                        imagePart.FeedData(fileStream);
                        fileStream.Close();
                    }

                    return; // found the photo and replaced it. 
                }

Guess I just couldn't see the wood for the trees.......

like image 54
Alan Schofield Avatar answered Nov 02 '22 01:11

Alan Schofield