1- using Syncfusion . Presentation ;
2- using Syncfusion . Drawing ;
1+ using Syncfusion . Drawing ;
2+ using Syncfusion . Presentation ;
33
44public static class Program
55{
6+ public static int imageIndex = 0 ;
7+ public static string outputPath = @"Output" ;
8+
69 public static void Main ( )
710 {
811 // Open the PowerPoint file as a stream.
9- using ( FileStream inputStream = new FileStream ( Path . GetFullPath ( @"Data/Input.pptx" , FileMode . Open , FileAccess . Read ) )
12+ using ( FileStream inputStream = new FileStream ( Path . GetFullPath ( @"Data/Input.pptx" ) , FileMode . Open , FileAccess . Read ) )
1013 {
1114 // Load the presentation from the stream.
1215 using ( IPresentation presentation = Presentation . Open ( inputStream ) )
1316 {
14- int imageIndex = 0 ;
15-
16- // Iterate through each slide in the presentation.
17- foreach ( ISlide slide in presentation. Slides )
17+ // Extract EMF images from Masters and their Layout slides
18+ foreach ( IMasterSlide master in presentation . Masters )
1819 {
19- // Iterate through each shape in the slide.
20- foreach ( IShape shape in slide . Shapes )
20+ // Process shapes placed on the master slide
21+ foreach ( IShape shape in master . Shapes )
22+ {
23+ ProcessShape ( shape ) ;
24+ }
25+ // Process shapes placed on each layout slide under this master
26+ foreach ( ILayoutSlide layoutSlide in master . LayoutSlides )
2127 {
22- // Check if the shape is an image.
23- if ( shape is IPicture picture && picture . ImageFormat == ImageFormat . Emf )
28+ foreach ( IShape shape in layoutSlide . Shapes )
2429 {
25- // Retrieve the raw image data.
26- byte [ ] imageData = picture . ImageData ;
27-
28- // Proceed only if image data is valid.
29- if ( imageData != null && imageData . Length > 0 )
30- {
31- // Determine the image format extension.
32- string extension = picture . ImageFormat . ToString ( ) ;
33- string outputPath = Path . Combine ( $ "Output/Slide{ slide . SlideNumber } _Image{ ++ imageIndex } .{ extension } ") ;
34- // Save the image data to the specified path.
35- File . WriteAllBytes ( outputPath , imageData ) ;
36- }
30+ ProcessShape ( shape ) ;
3731 }
3832 }
3933 }
34+ // Extract EMF images from Normal slides
35+ foreach ( ISlide slide in presentation . Slides )
36+ {
37+ foreach ( IShape shape in slide . Shapes )
38+ {
39+ ProcessShape ( shape ) ;
40+ }
41+ }
4042 }
4143 }
4244 }
43- }
45+
46+ /// <summary>
47+ /// Processes a shape: saves EMF images and recurses through group shapes.
48+ /// </summary>
49+ private static void ProcessShape ( IShape shape )
50+ {
51+ // If the shape is a picture with EMF format
52+ if ( shape is IPicture picture && picture . ImageFormat == ImageFormat . Emf )
53+ {
54+ SaveEMFImage ( picture ) ;
55+ }
56+ // Shape is not a picture object, but its FILL contains a picture(Picture Fill)
57+ if ( shape . Fill != null && shape . Fill . FillType == FillType . Picture )
58+ {
59+ // Validate bytes exist and check if those bytes represent an EMF file
60+ var bytes = shape . Fill . PictureFill . ImageBytes ;
61+ if ( bytes != null && bytes . Length > 0 && IsEmf ( bytes ) )
62+ {
63+ string filePath = Path . Combine ( outputPath , $ "Slide_Image_{ ++ imageIndex } .emf") ;
64+ File . WriteAllBytes ( filePath , bytes ) ;
65+ }
66+ }
67+
68+ // If the shape is a group, process child shapes
69+ if ( shape is IGroupShape group )
70+ {
71+ foreach ( IShape child in group . Shapes )
72+ {
73+ ProcessShape ( child ) ;
74+ }
75+ }
76+ }
77+
78+ /// <summary>
79+ /// Saves EMF image from the picture shape.
80+ /// </summary>
81+ private static void SaveEMFImage ( IPicture picture )
82+ {
83+ byte [ ] imageData = picture . ImageData ;
84+
85+ if ( imageData != null && imageData . Length > 0 )
86+ {
87+ string extension = picture . ImageFormat . ToString ( ) . ToLower ( ) ;
88+ string filePath = Path . Combine ( outputPath , $ "Slide_Image_{ ++ imageIndex } .{ extension } ") ;
89+ File . WriteAllBytes ( filePath , imageData ) ;
90+ }
91+ }
92+
93+ /// <summary>
94+ /// Checks whether the given byte[] looks like an EMF file.
95+ /// </summary>
96+ private static bool IsEmf ( byte [ ] bytes )
97+ {
98+ if ( bytes == null || bytes . Length < 44 ) return false ;
99+
100+ // EMF signature " EMF" = 0x20 0x45 0x4D 0x46 (little endian uint32 => 0x464D4520)
101+ // At offset 40..43
102+ uint signature = BitConverter . ToUInt32 ( bytes , 40 ) ;
103+ return signature == 0x464D4520 ;
104+ }
105+ }
0 commit comments