using System; using System.Collections.Generic; using System.Linq; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Presentation; using D = DocumentFormat.OpenXml.Drawing; namespace BetterEN5.Services.Conversion; public class PptxImporter { public DocumentModel Import(string pptxPath) { var doc = new DocumentModel(); using var presentation = PresentationDocument.Open(pptxPath, false); var presPart = presentation.PresentationPart!; var pres = presPart.Presentation; var slideSize = pres.SlideSize!; doc.SlideWidth = slideSize.Cx!.Value; doc.SlideHeight = slideSize.Cy!.Value; int slideIndex = 0; foreach (var slideId in pres.SlideIdList!.ChildElements.OfType()) { slideIndex++; var slidePart = presPart.GetPartById(slideId.RelationshipId!) as SlidePart; if (slidePart == null) continue; var slide = slidePart.Slide; var slideModel = new SlideModel { Name = $"Slide{slideIndex}", Width = doc.SlideWidth, Height = doc.SlideHeight }; ParseSlideElements(slidePart, slide, slideModel, doc); doc.Slides.Add(slideModel); } return doc; } private void ParseSlideElements(SlidePart slidePart, Slide slide, SlideModel slideModel, DocumentModel doc) { if (slide.CommonSlideData?.ShapeTree == null) return; foreach (var element in slide.CommonSlideData.ShapeTree.ChildElements) { switch (element) { case Picture pic: ParsePicture(slidePart, pic, slideModel); break; case Shape shape: ParseShape(shape, slideModel); break; } } } private void ParsePicture(SlidePart slidePart, Picture pic, SlideModel slideModel) { var blipFill = pic.BlipFill; if (blipFill?.Blip == null) return; var embed = blipFill.Blip.Embed?.Value; if (string.IsNullOrEmpty(embed)) return; var imagePart = slidePart.GetPartById(embed) as ImagePart; if (imagePart == null) return; using var stream = imagePart.GetStream(); var data = new byte[stream.Length]; stream.Read(data, 0, data.Length); var transform = pic.ShapeProperties?.Transform2D; var img = new ImageElement { Data = data, ContentType = imagePart.ContentType, FileName = $"image{slideModel.Elements.Count + 1}{GetExtension(imagePart.ContentType)}", X = transform?.Offset?.X?.Value ?? 0, Y = transform?.Offset?.Y?.Value ?? 0, Width = transform?.Extents?.Cx?.Value ?? 0, Height = transform?.Extents?.Cy?.Value ?? 0 }; slideModel.Elements.Add(img); } private void ParseShape(Shape shape, SlideModel slideModel) { var textBody = shape.TextBody; if (textBody == null) return; var text = string.Concat( textBody.Descendants().Select(t => t.Text)); if (string.IsNullOrWhiteSpace(text)) return; var transform = shape.ShapeProperties?.Transform2D; var textElem = new TextElement { Text = text.Trim(), X = transform?.Offset?.X?.Value ?? 0, Y = transform?.Offset?.Y?.Value ?? 0, Width = transform?.Extents?.Cx?.Value ?? 0, Height = transform?.Extents?.Cy?.Value ?? 0 }; var firstRun = textBody.Descendants().FirstOrDefault(); if (firstRun?.RunProperties != null) { var rp = firstRun.RunProperties; textElem.FontSize = (rp.FontSize?.Value ?? 1800) / 100.0; textElem.IsBold = rp.Bold?.Value ?? false; var solidFill = rp.GetFirstChild(); if (solidFill?.RgbColorModelHex?.Val?.Value != null) textElem.FontColor = $"#{solidFill.RgbColorModelHex.Val.Value}"; else if (solidFill?.SchemeColor?.Val?.Value != null) textElem.FontColor = $"#{solidFill.SchemeColor.Val}"; } slideModel.Elements.Add(textElem); } private static string GetExtension(string contentType) { return contentType switch { "image/png" => ".png", "image/jpeg" => ".jpg", "image/gif" => ".gif", "image/bmp" => ".bmp", "image/tiff" => ".tiff", _ => ".bin" }; } }