Skip to content

Commit 4b083ea

Browse files
authored
Merge pull request #68 from synercoder/develop
Added transparency, overprint mode & separation images
2 parents a18269b + 30aca7b commit 4b083ea

31 files changed

+488
-129
lines changed

.github/workflows/dotnet-core.yml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ env:
1515
# Project name to pack and publish
1616
PROJECT_NAME: Synercoding.FileFormats.Pdf
1717
# GitHub Packages Feed settings
18-
GITHUB_FEED: https://nuget.pkg.github.com/synercoder/
18+
GITHUB_FEED: https://nuget.pkg.github.com/synercoder/index.json
1919
GITHUB_USER: synercoder
2020
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2121
# Official NuGet Feed settings
@@ -33,7 +33,7 @@ jobs:
3333
- name: Setup .NET Core
3434
uses: actions/setup-dotnet@v1
3535
with:
36-
dotnet-version: 7.0.x
36+
dotnet-version: 8.0.x
3737
- name: Restore
3838
run: dotnet restore
3939
- name: Build
@@ -45,7 +45,7 @@ jobs:
4545
run: dotnet pack -v normal -c Release --no-restore --include-symbols --include-source -p:SymbolPackageFormat=snupkg -p:PackageVersion=1.0.0-pre+$GITHUB_RUN_ID src/$PROJECT_NAME/$PROJECT_NAME.*proj
4646
- name: Upload Artifact
4747
if: matrix.os == 'ubuntu-latest'
48-
uses: actions/upload-artifact@v2
48+
uses: actions/upload-artifact@v4
4949
with:
5050
name: nupkg
5151
path: ./artifacts/pkg/Release/${{ env.PROJECT_NAME }}.*.nupkg
@@ -55,15 +55,16 @@ jobs:
5555
runs-on: ubuntu-latest
5656
steps:
5757
- name: Download Artifact
58-
uses: actions/download-artifact@v1
58+
uses: actions/download-artifact@v4
5959
with:
6060
name: nupkg
61-
- name: Push to GitHub Feed
62-
run: |
63-
for f in ./nupkg/*.nupkg
64-
do
65-
curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED
66-
done
61+
path: ./nupkg
62+
- name: Setup .NET Core @ Latest
63+
uses: actions/setup-dotnet@v1
64+
- name: Publish Nuget to GitHub registry
65+
run: dotnet nuget push ./nupkg/*.nupkg -k ${GITHUB_TOKEN} -s ${GITHUB_FEED} --skip-duplicate
66+
env:
67+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6768
deploy:
6869
needs: build
6970
if: github.event_name == 'release'
@@ -73,7 +74,7 @@ jobs:
7374
- name: Setup .NET Core
7475
uses: actions/setup-dotnet@v1
7576
with:
76-
dotnet-version: 7.0.x
77+
dotnet-version: 8.0.x
7778
- name: Create Release NuGet package
7879
run: |
7980
arrTag=(${GITHUB_REF//\// })
@@ -82,12 +83,10 @@ jobs:
8283
VERSION="${VERSION//v}"
8384
echo Clean Version: $VERSION
8485
dotnet pack -v normal -c Release --include-symbols --include-source -p:SymbolPackageFormat=snupkg -p:PackageVersion=$VERSION -o nupkg src/$PROJECT_NAME/$PROJECT_NAME.*proj
85-
- name: Push to GitHub Feed
86-
run: |
87-
for f in ./nupkg/*.nupkg
88-
do
89-
curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED
90-
done
86+
- name: Publish Nuget to GitHub registry
87+
run: dotnet nuget push ./nupkg/*.nupkg -k ${GITHUB_TOKEN} -s ${GITHUB_FEED} --skip-duplicate
88+
env:
89+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9190
- name: Push to NuGet Feed
9291
if: ${{ env.NUGET_FEED }} != ''
93-
run: dotnet nuget push ./nupkg/*.nupkg --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
92+
run: dotnet nuget push ./nupkg/*.nupkg --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</PropertyGroup>
4242

4343
<PropertyGroup>
44-
<LangVersion>11.0</LangVersion>
44+
<LangVersion>12.0</LangVersion>
4545
<Nullable>enable</Nullable>
4646
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
4747
<Features>strict</Features>

Directory.Build.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Update="SixLabors.ImageSharp" Version="3.0.*" />
10+
<PackageReference Update="SixLabors.ImageSharp" Version="3.1.*" />
1111
</ItemGroup>
1212

1313
<!-- Disable auto imports/usings from ImageSharp -->

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ The PDF files created in this library are not fully PDF 1.7 compliant, because t
4141
This shortcoming shall be remedied when broader font support is implemented.
4242

4343
### Sample program images
44-
The sample project called *Synercoding.FileFormats.Pdf.ConsoleTester* uses multiple images. Those images were taken from [Pexels.com](https://www.pexels.com/royalty-free-images/) and are licensed under the [Pexels License](https://www.pexels.com/photo-license/).
44+
The sample project called *Synercoding.FileFormats.Pdf.ConsoleTester* uses multiple images.
45+
Those images were taken from:
46+
- [Pexels.com](https://www.pexels.com/royalty-free-images/) and are licensed under the [Pexels License](https://www.pexels.com/photo-license/)
47+
- [FreePngImg.com](https://freepngimg.com/png/59872-jaguar-panther-royalty-free-cougar-black-cheetah) and are licensed under [Creative Commons (CC BY-NC 4.0)](https://creativecommons.org/licenses/by-nc/4.0/)
4548

4649
## Sample usage
4750

samples/Synercoding.FileFormats.Pdf.ConsoleTester/Program.cs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using SixLabors.ImageSharp.PixelFormats;
12
using Synercoding.FileFormats.Pdf.Extensions;
23
using Synercoding.FileFormats.Pdf.LowLevel.Colors;
34
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
@@ -63,7 +64,7 @@ public static void Main(string[] args)
6364
});
6465

6566
using (var forestStream = File.OpenRead("Pexels_com/android-wallpaper-art-backlit-1114897.jpg"))
66-
using (var forestImage = SixLabors.ImageSharp.Image.Load(forestStream))
67+
using (var forestImage = SixLabors.ImageSharp.Image.Load<Rgba32>(forestStream))
6768
{
6869
var scale = (double)forestImage.Width / forestImage.Height;
6970

@@ -81,7 +82,7 @@ public static void Main(string[] args)
8182
page.TrimBox = trimBox;
8283

8384
using (var barrenStream = File.OpenRead("Pexels_com/arid-barren-desert-1975514.jpg"))
84-
using (var barrenImage = SixLabors.ImageSharp.Image.Load(barrenStream))
85+
using (var barrenImage = SixLabors.ImageSharp.Image.Load<Rgba32>(barrenStream))
8586
{
8687
var scale = (double)barrenImage.Width / barrenImage.Height;
8788

@@ -175,7 +176,7 @@ public static void Main(string[] args)
175176
page.TrimBox = trimBox;
176177

177178
using (var forestStream = File.OpenRead("Pexels_com/android-wallpaper-art-backlit-1114897.jpg"))
178-
using (var forestImage = SixLabors.ImageSharp.Image.Load(forestStream))
179+
using (var forestImage = SixLabors.ImageSharp.Image.Load<Rgba32>(forestStream))
179180
{
180181
var scale = (double)forestImage.Width / forestImage.Height;
181182

@@ -187,7 +188,7 @@ public static void Main(string[] args)
187188
});
188189

189190
using (var blurStream = File.OpenRead("Pexels_com/4k-wallpaper-blur-bokeh-1484253.jpg"))
190-
using (var blurImage = SixLabors.ImageSharp.Image.Load(blurStream))
191+
using (var blurImage = SixLabors.ImageSharp.Image.Load<Rgba32>(blurStream))
191192
{
192193
var reusedImage = writer.AddImage(blurImage);
193194

@@ -216,12 +217,43 @@ public static void Main(string[] args)
216217

217218
page.Content.AddShapes(trimBox, static (trim, context) =>
218219
{
220+
context.SetExtendedGraphicsState(new ExtendedGraphicsState()
221+
{
222+
Overprint = true
223+
});
219224
context.SetStroke(new SpotColor(new Separation(LowLevel.PdfName.Get("CutContour"), PredefinedColors.Magenta), 1));
220225
context.Rectangle(trim);
221226
context.Stroke();
222227
});
223228
});
224229
}
230+
231+
using (var pantherPngStream = File.OpenRead("FreePngImage_com/59872-jaguar-panther-royalty-free-cougar-black-cheetah.png"))
232+
using (var pantherImage = SixLabors.ImageSharp.Image.Load<Rgba32>(pantherPngStream))
233+
{
234+
var pantherImg = writer.AddImage(pantherImage);
235+
var transparentPanther = writer.AddSeparationImage(new Separation(LowLevel.PdfName.Get("White"), PredefinedColors.Yellow), pantherImage, GrayScaleMethod.AlphaChannel);
236+
237+
writer.AddPage(page =>
238+
{
239+
page.MediaBox = mediaBox;
240+
page.TrimBox = trimBox;
241+
242+
var scale = (double)transparentPanther.Width / transparentPanther.Height;
243+
var pantherSize = new Rectangle(0, 0, 216, 216 / scale, Unit.Millimeters);
244+
245+
page.Content.AddImage(pantherImage, pantherSize);
246+
247+
page.Content.WrapInState(pantherImage, (image, content) =>
248+
{
249+
content.SetExtendedGraphicsState(new ExtendedGraphicsState()
250+
{
251+
Overprint = true
252+
});
253+
content.AddImage(transparentPanther, pantherSize);
254+
});
255+
});
256+
}
225257
}
226258
}
227259
}

samples/Synercoding.FileFormats.Pdf.ConsoleTester/Synercoding.FileFormats.Pdf.ConsoleTester.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFramework>net8.0</TargetFramework>
66
</PropertyGroup>
77

88
<ItemGroup>
@@ -15,4 +15,10 @@
1515
</None>
1616
</ItemGroup>
1717

18+
<ItemGroup>
19+
<None Update="FreePngImage_com\*.png">
20+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
21+
</None>
22+
</ItemGroup>
23+
1824
</Project>

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<Project>
33

44
<PropertyGroup>
5-
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
5+
<TargetFrameworks>net8.0</TargetFrameworks>
66
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props</MSBuildAllProjects>
77
<SynercodingProjectCategory>src</SynercodingProjectCategory>
88
</PropertyGroup>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace Synercoding.FileFormats.Pdf;
2+
3+
/// <summary>
4+
/// Class representing an ExtGState dictionary.
5+
/// </summary>
6+
public sealed record class ExtendedGraphicsState
7+
{
8+
/// <summary>
9+
/// A flag specifying whether to apply overprint.
10+
/// There are two separate overprint parameters: one for stroking and one for all other painting operations.
11+
/// Specifying an <see cref="Overprint"/> entry sets both parameters
12+
/// unless there is also an <see cref="OverprintNonStroking"/> entry in the same graphics state parameter dictionary,
13+
/// in which case the <see cref="Overprint"/> entry sets only the overprint parameter for stroking.
14+
/// </summary>
15+
public bool? Overprint { get; set; }
16+
17+
/// <summary>
18+
/// A flag specifying whether to apply overprint for painting operations other than stroking.
19+
/// If this entry is absent, the <see cref="Overprint"/> entry, if any, sets this parameter.
20+
/// </summary>
21+
public bool? OverprintNonStroking { get; set; }
22+
}
23+

src/Synercoding.FileFormats.Pdf/Extensions/IPageContentContextExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using SixLabors.ImageSharp.PixelFormats;
12
using Synercoding.FileFormats.Pdf.Internals;
23
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
34
using Synercoding.FileFormats.Pdf.LowLevel.Text;
@@ -61,7 +62,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Sys
6162
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
6263
public static IPageContentContext AddImage(this IPageContentContext context, System.IO.Stream stream)
6364
{
64-
using var image = SixLabors.ImageSharp.Image.Load(stream);
65+
using var image = SixLabors.ImageSharp.Image.Load<Rgba32>(stream);
6566

6667
return context.AddImage(image);
6768
}
@@ -73,7 +74,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Sys
7374
/// <param name="image">The image to place</param>
7475
/// <param name="matrix">The placement matrix to use</param>
7576
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
76-
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Matrix matrix)
77+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image<Rgba32> image, Matrix matrix)
7778
{
7879
return context.WrapInState((image, matrix), static (tuple, context) =>
7980
{
@@ -89,7 +90,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Six
8990
/// <param name="image">The image to place</param>
9091
/// <param name="rectangle">The rectangle of where to place the image.</param>
9192
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
92-
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Rectangle rectangle)
93+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image<Rgba32> image, Rectangle rectangle)
9394
=> context.AddImage(image, rectangle.AsPlacementMatrix());
9495

9596
/// <summary>
@@ -98,7 +99,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Six
9899
/// <param name="context">The context to add the image to.</param>
99100
/// <param name="image">The image to place</param>
100101
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
101-
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image)
102+
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image<Rgba32> image)
102103
{
103104
var name = context.RawContentStream.Resources.AddImage(image);
104105

src/Synercoding.FileFormats.Pdf/GraphicState.cs renamed to src/Synercoding.FileFormats.Pdf/GraphicsState.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ namespace Synercoding.FileFormats.Pdf;
77
/// <summary>
88
/// Class representing the grahpic state of a PDF at a certain moment in time.
99
/// </summary>
10-
public sealed class GraphicState
10+
public sealed class GraphicsState
1111
{
12-
internal GraphicState()
12+
internal GraphicsState()
1313
{
1414
CTM = Matrix.Identity;
1515
Fill = PredefinedColors.Black;
@@ -111,9 +111,9 @@ internal GraphicState()
111111
/// </summary>
112112
public double TextRise { get; internal set; }
113113

114-
internal GraphicState Clone()
114+
internal GraphicsState Clone()
115115
{
116-
return new GraphicState()
116+
return new GraphicsState()
117117
{
118118
CTM = CTM,
119119
Fill = Fill,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace Synercoding.FileFormats.Pdf;
2+
3+
/// <summary>
4+
/// What method is used to generate a 1 component grayscale pixel byte array
5+
/// </summary>
6+
public enum GrayScaleMethod
7+
{
8+
/// <summary>
9+
/// Use the red channel
10+
/// </summary>
11+
RedChannel,
12+
/// <summary>
13+
/// Use the green channel
14+
/// </summary>
15+
GreenChannel,
16+
/// <summary>
17+
/// Use the blue channel
18+
/// </summary>
19+
BlueChannel,
20+
/// <summary>
21+
/// Use the alpha channel
22+
/// </summary>
23+
AlphaChannel,
24+
/// <summary>
25+
/// Use the average of the Red, Green and Blue channels.
26+
/// </summary>
27+
AverageOfRGBChannels
28+
}

src/Synercoding.FileFormats.Pdf/IContentContext.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public interface IContentContext<TSelf>
1919
/// <summary>
2020
/// Represents the current graphic state
2121
/// </summary>
22-
GraphicState GraphicState { get; }
22+
GraphicsState GraphicState { get; }
2323

2424
/// <summary>
2525
/// Wrap the <paramref name="contentOperations"/> in save and restore state operators
@@ -40,7 +40,7 @@ public interface IContentContext<TSelf>
4040
Task<TSelf> WrapInStateAsync<T>(T data, Func<T, TSelf, Task> contentOperations);
4141

4242
/// <summary>
43-
/// Concatenate a matrix to <see cref="GraphicState.CTM"/>
43+
/// Concatenate a matrix to <see cref="GraphicsState.CTM"/>
4444
/// </summary>
4545
/// <param name="matrix">The matrix to concat</param>
4646
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
@@ -94,5 +94,12 @@ public interface IContentContext<TSelf>
9494
/// <param name="dashPattern">The dash pattern to set</param>
9595
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
9696
TSelf SetDashPattern(Dash dashPattern);
97+
98+
/// <summary>
99+
/// Set an extended graphics state (ExtGState) dictionary.
100+
/// </summary>
101+
/// <param name="extendedGraphicsState">The state to apply.</param>
102+
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
103+
TSelf SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState);
97104
}
98105

src/Synercoding.FileFormats.Pdf/ITextContentContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public interface ITextContentContext : IContentContext<ITextContentContext>
101101
ITextContentContext ShowTextOnNextLine(string text);
102102

103103
/// <summary>
104-
/// Operation to show text on the next line and setting the <see cref="GraphicState.WordSpacing"/> and <see cref="GraphicState.CharacterSpacing"/>
104+
/// Operation to show text on the next line and setting the <see cref="GraphicsState.WordSpacing"/> and <see cref="GraphicsState.CharacterSpacing"/>
105105
/// </summary>
106106
/// <param name="text">The text to show</param>
107107
/// <param name="wordSpacing">The word spacing to set</param>

0 commit comments

Comments
 (0)