Skip to content

Added transparency, overprint mode & separation images #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 17 additions & 18 deletions .github/workflows/dotnet-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
# Project name to pack and publish
PROJECT_NAME: Synercoding.FileFormats.Pdf
# GitHub Packages Feed settings
GITHUB_FEED: https://nuget.pkg.github.com/synercoder/
GITHUB_FEED: https://nuget.pkg.github.com/synercoder/index.json
GITHUB_USER: synercoder
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Official NuGet Feed settings
Expand All @@ -33,7 +33,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 8.0.x
- name: Restore
run: dotnet restore
- name: Build
Expand All @@ -45,7 +45,7 @@ jobs:
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
- name: Upload Artifact
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: nupkg
path: ./artifacts/pkg/Release/${{ env.PROJECT_NAME }}.*.nupkg
Expand All @@ -55,15 +55,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download Artifact
uses: actions/download-artifact@v1
uses: actions/download-artifact@v4
with:
name: nupkg
- name: Push to GitHub Feed
run: |
for f in ./nupkg/*.nupkg
do
curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED
done
path: ./nupkg
- name: Setup .NET Core @ Latest
uses: actions/setup-dotnet@v1
- name: Publish Nuget to GitHub registry
run: dotnet nuget push ./nupkg/*.nupkg -k ${GITHUB_TOKEN} -s ${GITHUB_FEED} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
deploy:
needs: build
if: github.event_name == 'release'
Expand All @@ -73,7 +74,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.0.x
dotnet-version: 8.0.x
- name: Create Release NuGet package
run: |
arrTag=(${GITHUB_REF//\// })
Expand All @@ -82,12 +83,10 @@ jobs:
VERSION="${VERSION//v}"
echo Clean Version: $VERSION
dotnet pack -v normal -c Release --include-symbols --include-source -p:SymbolPackageFormat=snupkg -p:PackageVersion=$VERSION -o nupkg src/$PROJECT_NAME/$PROJECT_NAME.*proj
- name: Push to GitHub Feed
run: |
for f in ./nupkg/*.nupkg
do
curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED
done
- name: Publish Nuget to GitHub registry
run: dotnet nuget push ./nupkg/*.nupkg -k ${GITHUB_TOKEN} -s ${GITHUB_FEED} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Push to NuGet Feed
if: ${{ env.NUGET_FEED }} != ''
run: dotnet nuget push ./nupkg/*.nupkg --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
run: dotnet nuget push ./nupkg/*.nupkg --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
</PropertyGroup>

<PropertyGroup>
<LangVersion>11.0</LangVersion>
<LangVersion>12.0</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Features>strict</Features>
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Update="SixLabors.ImageSharp" Version="3.0.*" />
<PackageReference Update="SixLabors.ImageSharp" Version="3.1.*" />
</ItemGroup>

<!-- Disable auto imports/usings from ImageSharp -->
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ The PDF files created in this library are not fully PDF 1.7 compliant, because t
This shortcoming shall be remedied when broader font support is implemented.

### Sample program images
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/).
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/)
- [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/)

## Sample usage

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 36 additions & 4 deletions samples/Synercoding.FileFormats.Pdf.ConsoleTester/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using SixLabors.ImageSharp.PixelFormats;
using Synercoding.FileFormats.Pdf.Extensions;
using Synercoding.FileFormats.Pdf.LowLevel.Colors;
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
Expand Down Expand Up @@ -63,7 +64,7 @@ public static void Main(string[] args)
});

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

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

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

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

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

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

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

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

page.Content.AddShapes(trimBox, static (trim, context) =>
{
context.SetExtendedGraphicsState(new ExtendedGraphicsState()
{
Overprint = true
});
context.SetStroke(new SpotColor(new Separation(LowLevel.PdfName.Get("CutContour"), PredefinedColors.Magenta), 1));
context.Rectangle(trim);
context.Stroke();
});
});
}

using (var pantherPngStream = File.OpenRead("FreePngImage_com/59872-jaguar-panther-royalty-free-cougar-black-cheetah.png"))
using (var pantherImage = SixLabors.ImageSharp.Image.Load<Rgba32>(pantherPngStream))
{
var pantherImg = writer.AddImage(pantherImage);
var transparentPanther = writer.AddSeparationImage(new Separation(LowLevel.PdfName.Get("White"), PredefinedColors.Yellow), pantherImage, GrayScaleMethod.AlphaChannel);

writer.AddPage(page =>
{
page.MediaBox = mediaBox;
page.TrimBox = trimBox;

var scale = (double)transparentPanther.Width / transparentPanther.Height;
var pantherSize = new Rectangle(0, 0, 216, 216 / scale, Unit.Millimeters);

page.Content.AddImage(pantherImage, pantherSize);

page.Content.WrapInState(pantherImage, (image, content) =>
{
content.SetExtendedGraphicsState(new ExtendedGraphicsState()
{
Overprint = true
});
content.AddImage(transparentPanther, pantherSize);
});
});
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand All @@ -15,4 +15,10 @@
</None>
</ItemGroup>

<ItemGroup>
<None Update="FreePngImage_com\*.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>

<PropertyGroup>
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props</MSBuildAllProjects>
<SynercodingProjectCategory>src</SynercodingProjectCategory>
</PropertyGroup>
Expand Down
23 changes: 23 additions & 0 deletions src/Synercoding.FileFormats.Pdf/ExtendedGraphicsState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Synercoding.FileFormats.Pdf;

/// <summary>
/// Class representing an ExtGState dictionary.
/// </summary>
public sealed record class ExtendedGraphicsState
{
/// <summary>
/// A flag specifying whether to apply overprint.
/// There are two separate overprint parameters: one for stroking and one for all other painting operations.
/// Specifying an <see cref="Overprint"/> entry sets both parameters
/// unless there is also an <see cref="OverprintNonStroking"/> entry in the same graphics state parameter dictionary,
/// in which case the <see cref="Overprint"/> entry sets only the overprint parameter for stroking.
/// </summary>
public bool? Overprint { get; set; }

/// <summary>
/// A flag specifying whether to apply overprint for painting operations other than stroking.
/// If this entry is absent, the <see cref="Overprint"/> entry, if any, sets this parameter.
/// </summary>
public bool? OverprintNonStroking { get; set; }
}

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using SixLabors.ImageSharp.PixelFormats;
using Synercoding.FileFormats.Pdf.Internals;
using Synercoding.FileFormats.Pdf.LowLevel.Colors.ColorSpaces;
using Synercoding.FileFormats.Pdf.LowLevel.Text;
Expand Down Expand Up @@ -61,7 +62,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Sys
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
public static IPageContentContext AddImage(this IPageContentContext context, System.IO.Stream stream)
{
using var image = SixLabors.ImageSharp.Image.Load(stream);
using var image = SixLabors.ImageSharp.Image.Load<Rgba32>(stream);

return context.AddImage(image);
}
Expand All @@ -73,7 +74,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Sys
/// <param name="image">The image to place</param>
/// <param name="matrix">The placement matrix to use</param>
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Matrix matrix)
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image<Rgba32> image, Matrix matrix)
{
return context.WrapInState((image, matrix), static (tuple, context) =>
{
Expand All @@ -89,7 +90,7 @@ public static IPageContentContext AddImage(this IPageContentContext context, Six
/// <param name="image">The image to place</param>
/// <param name="rectangle">The rectangle of where to place the image.</param>
/// <returns>The same <paramref name="context"/> to enable chaining operations.</returns>
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image image, Rectangle rectangle)
public static IPageContentContext AddImage(this IPageContentContext context, SixLabors.ImageSharp.Image<Rgba32> image, Rectangle rectangle)
=> context.AddImage(image, rectangle.AsPlacementMatrix());

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ namespace Synercoding.FileFormats.Pdf;
/// <summary>
/// Class representing the grahpic state of a PDF at a certain moment in time.
/// </summary>
public sealed class GraphicState
public sealed class GraphicsState
{
internal GraphicState()
internal GraphicsState()
{
CTM = Matrix.Identity;
Fill = PredefinedColors.Black;
Expand Down Expand Up @@ -111,9 +111,9 @@ internal GraphicState()
/// </summary>
public double TextRise { get; internal set; }

internal GraphicState Clone()
internal GraphicsState Clone()
{
return new GraphicState()
return new GraphicsState()
{
CTM = CTM,
Fill = Fill,
Expand Down
28 changes: 28 additions & 0 deletions src/Synercoding.FileFormats.Pdf/GrayScaleMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Synercoding.FileFormats.Pdf;

/// <summary>
/// What method is used to generate a 1 component grayscale pixel byte array
/// </summary>
public enum GrayScaleMethod
{
/// <summary>
/// Use the red channel
/// </summary>
RedChannel,
/// <summary>
/// Use the green channel
/// </summary>
GreenChannel,
/// <summary>
/// Use the blue channel
/// </summary>
BlueChannel,
/// <summary>
/// Use the alpha channel
/// </summary>
AlphaChannel,
/// <summary>
/// Use the average of the Red, Green and Blue channels.
/// </summary>
AverageOfRGBChannels
}
11 changes: 9 additions & 2 deletions src/Synercoding.FileFormats.Pdf/IContentContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface IContentContext<TSelf>
/// <summary>
/// Represents the current graphic state
/// </summary>
GraphicState GraphicState { get; }
GraphicsState GraphicState { get; }

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

/// <summary>
/// Concatenate a matrix to <see cref="GraphicState.CTM"/>
/// Concatenate a matrix to <see cref="GraphicsState.CTM"/>
/// </summary>
/// <param name="matrix">The matrix to concat</param>
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
Expand Down Expand Up @@ -94,5 +94,12 @@ public interface IContentContext<TSelf>
/// <param name="dashPattern">The dash pattern to set</param>
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
TSelf SetDashPattern(Dash dashPattern);

/// <summary>
/// Set an extended graphics state (ExtGState) dictionary.
/// </summary>
/// <param name="extendedGraphicsState">The state to apply.</param>
/// <returns>This <see cref="IContentContext{TSelf}"/> to enable chaining operations</returns>
TSelf SetExtendedGraphicsState(ExtendedGraphicsState extendedGraphicsState);
}

2 changes: 1 addition & 1 deletion src/Synercoding.FileFormats.Pdf/ITextContentContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public interface ITextContentContext : IContentContext<ITextContentContext>
ITextContentContext ShowTextOnNextLine(string text);

/// <summary>
/// Operation to show text on the next line and setting the <see cref="GraphicState.WordSpacing"/> and <see cref="GraphicState.CharacterSpacing"/>
/// Operation to show text on the next line and setting the <see cref="GraphicsState.WordSpacing"/> and <see cref="GraphicsState.CharacterSpacing"/>
/// </summary>
/// <param name="text">The text to show</param>
/// <param name="wordSpacing">The word spacing to set</param>
Expand Down
Loading
Loading