Skip to content

Commit e1435ea

Browse files
Merge pull request #130 from SyncfusionExamples/992103-ExtractEMF
992103-How to extract an .EMF images from the PPTX file
2 parents 70f8ce7 + f595902 commit e1435ea

File tree

10 files changed

+153
-0
lines changed

10 files changed

+153
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.11.35327.3
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Extract-EMF-Images", "Extract-EMF-Images\Extract-EMF-Images.csproj", "{82E919F2-6EA6-4E54-BF73-9D3133B56F4A}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{82E919F2-6EA6-4E54-BF73-9D3133B56F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{82E919F2-6EA6-4E54-BF73-9D3133B56F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{82E919F2-6EA6-4E54-BF73-9D3133B56F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{82E919F2-6EA6-4E54-BF73-9D3133B56F4A}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {446047E7-FDD0-4F0E-A910-B67785529857}
24+
EndGlobalSection
25+
EndGlobal
Binary file not shown.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<RootNamespace>Extract_EMF_Images</RootNamespace>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Syncfusion.PresentationRenderer.Net.Core" Version="*" />
13+
</ItemGroup>
14+
<ItemGroup>
15+
<None Update="Data\Input.pptx">
16+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
17+
</None>
18+
<None Update="Output\.gitkeep">
19+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
20+
</None>
21+
</ItemGroup>
22+
</Project>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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

Comments
 (0)