/// <summary> /// Create a slide model from a powerpoint slide /// </summary> /// <param name="pageSetup"></param> /// <param name="pptpm"></param> /// <param name="deck"></param> /// <param name="tempFileCollection"></param> /// <param name="dirpath"></param> /// <param name="currentSlide"></param> /// <returns></returns> private static SlideModel CreateSlide(PowerPoint.PageSetup pageSetup, PPTPaneManagement.PPTPaneManager pptpm, DeckModel deck, TempFileCollection tempFileCollection, string dirpath, PowerPoint._Slide currentSlide) { int slideWidth = (int)pageSetup.SlideWidth; //Standard = 720 => 6000 int slideHeight = (int)pageSetup.SlideHeight; //Standard = 540 => 4500 float emfWidth = slideWidth * 25 / 3; float emfHeight = slideHeight * 25 / 3; PowerPoint.Shapes currentShapes = currentSlide.Shapes; List <TaggedShape> taggedShapeList = PPTDeckIO.BuildTaggedShapeList(currentShapes, pptpm); //Create a new SlideModel SlideModel newSlideModel = new SlideModel(Guid.NewGuid(), new LocalId(), SlideDisposition.Empty, new Rectangle(0, 0, slideWidth, slideHeight)); //Lock it using (Synchronizer.Lock(newSlideModel.SyncRoot)) { //Set the slide's title newSlideModel.Title = PPTDeckIO.FindSlideTitle(taggedShapeList); PPTDeckIO.MakeShapesInvisible(currentShapes); //Create the Background image //Generate a new filename string filename = PPTDeckIO.GenerateFilename(); bool bitmapMode = true; if (bitmapMode) { filename = dirpath + "\\" + filename + ".JPG"; currentSlide.Export(filename, "JPG", 0, 0); // Need to also export as EMF to get the size of the slide in inches currentSlide.Export(filename + "_TEMP", "EMF", 0, 0); tempFileCollection.AddFile(filename + "_TEMP", false); } else { filename = dirpath + "\\" + filename + ".emf"; currentSlide.Export(filename, "EMF", 0, 0); } tempFileCollection.AddFile(filename, false); //Compute the MD5 of the BG FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); MD5 md5Provider = new MD5CryptoServiceProvider(); byte[] md5 = md5Provider.ComputeHash(fs); fs.Seek(0, SeekOrigin.Begin); Image image = Image.FromStream(fs); if (bitmapMode) { image = DisassociateBitmap(image); } fs.Close(); // Open the EMF version if we used a bitmap to get the conversion if (bitmapMode) { FileStream fsEMF = new FileStream(filename + "_TEMP", FileMode.Open, FileAccess.Read); Image image_emf = Image.FromStream(fsEMF); emfWidth = image_emf.Width; emfHeight = image_emf.Height; fsEMF.Close(); image_emf.Dispose(); } else { emfWidth = image.Width; emfHeight = image.Height; } //Create the ImageSheet ImageSheetModel sheet = new ImageSheetModel(deck, Guid.NewGuid(), Model.Presentation.SheetDisposition.Background, new Rectangle(0, 0, slideWidth, slideHeight), (ByteArray)md5, 1); //Add the ImageSheet to the Slide newSlideModel.ContentSheets.Add(sheet); //Add the Image+MD5 to the deck deck.AddSlideContent((ByteArray)md5, image); // Restore visibility - this makes everything visible - a bug? PPTDeckIO.MakeShapesVisible(currentShapes); List <List <TaggedShape> > layerList = PPTDeckIO.SeparateIntoLayers(taggedShapeList); int startHeight = 2; foreach (List <TaggedShape> layer in layerList) { PPTDeckIO.ProcessLayer(layer, tempFileCollection, currentShapes, deck, newSlideModel, slideWidth / emfWidth, slideHeight / emfHeight, startHeight++); } //Add SlideModel to the deck deck.InsertSlide(newSlideModel); } return(newSlideModel); }
/// <summary> /// Open a PPT deck and create a directory of jpg images, one for each slide in the deck. /// </summary> /// <param name="g"></param> /// <param name="file"></param> private void processPpt(Guid g, FileInfo file) { if (stopNow) { return; } if (pptApp == null) { try { pptApp = new PowerPoint.Application(); // Check if PPT was already running. pptAlreadyOpen = (pptApp.Visible == MsoTriState.msoTrue); } catch (Exception e) { log.WriteLine("Failed to create PowerPoint application instance. " + e.ToString()); log.ErrorLevel = 6; pptApp = null; return; } } try { PowerPoint._Presentation ppPres = pptApp.Presentations.Open(file.FullName, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse); PowerPoint.Slides slides = ppPres.Slides; String tempDirName = Utility.GetTempDir(); Directory.CreateDirectory(tempDirName); int slideCount = slides.Count; int ptStart = progressTracker.CurrentValue; for (int i = 1; i <= slides.Count; i++) { if (stopNow) { break; } //The image looks much better and is reasonably small if we save to wmf format first, then // convert to jpg. I guess the .Net jpeg encoder is better than the PPT encoder?? // Sometimes we may want to use the jpeg export with certain decks because we can get better // fidelity with some less common symbols. PowerPoint._Slide ppSlide = (PowerPoint._Slide)slides._Index(i); String jpgfile = Path.Combine(tempDirName, "slide" + i.ToString() + ".jpg"); Image img = null; string tmpfile = null; if (useNativeJpegExport) { tmpfile = Path.Combine(tempDirName, "slidetmp" + i.ToString() + ".JPG"); ppSlide.Export(tmpfile, "JPG", 0, 0); img = Image.FromFile(tmpfile); } else { tmpfile = Path.Combine(tempDirName, "slide" + i.ToString() + ".WMF"); ppSlide.Export(tmpfile, "WMF", 0, 0); img = Image.FromFile(tmpfile); } try { //The right shift is used to work around a CP3 issue: Some slide decks are shifted to the right, so we also // need to do this to keep ink from being mis-aligned. As of 2013 this should no longer be needed when // using a current version of CP3. if (rightShift > 0) { Image shiftedImage; RightImageShift(img, rightShift, out shiftedImage); shiftedImage.Save(jpgfile, ImageFormat.Jpeg); shiftedImage.Dispose(); } else { img.Save(jpgfile, ImageFormat.Jpeg); } } catch (Exception e) { log.WriteLine("Failed to save image for slide " + jpgfile + " exception: " + e.ToString()); log.ErrorLevel = 6; } img.Dispose(); System.IO.File.Delete(tmpfile); progressTracker.CurrentValue = ((i * 100) / slideCount) + ptStart; } ppPres.Close(); ppPres = null; this.outputDirs.Add(g, tempDirName); } catch (Exception e) { log.WriteLine(e.ToString()); log.ErrorLevel = 6; } }