1+ using Syncfusion . Drawing ;
2+ using Syncfusion . Presentation ;
3+
4+ public static class Program
5+ {
6+ public static int imageIndex = 0 ;
7+ public static string outputPath = @"Output" ;
8+
9+ public static void Main ( )
10+ {
11+ // Open the PowerPoint file as a stream.
12+ using ( FileStream inputStream = new FileStream ( Path . GetFullPath ( @"Data/Input.pptx" ) , FileMode . Open , FileAccess . Read ) )
13+ {
14+ // Load the presentation from the stream.
15+ using ( IPresentation presentation = Presentation . Open ( inputStream ) )
16+ {
17+ // Extract EMF images from Masters and their Layout slides
18+ foreach ( IMasterSlide master in presentation . Masters )
19+ {
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 )
27+ {
28+ foreach ( IShape shape in layoutSlide . Shapes )
29+ {
30+ ProcessShape ( shape ) ;
31+ }
32+ }
33+ }
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+ }
42+ }
43+ }
44+ }
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