Skip to content
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
7 changes: 7 additions & 0 deletions examples-dotnet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Concurrency.Tests"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Xunit", "src\Examples.Xunit\Examples.Xunit.csproj", "{AF338717-EFC2-4DE9-8D7E-DD88F6C5C17E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Graphics.Console", "src\Examples.Graphics.Console\Examples.Graphics.Console.csproj", "{83FE1916-A3C2-485F-A1DC-83C32F3CDD11}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -98,6 +100,10 @@ Global
{AF338717-EFC2-4DE9-8D7E-DD88F6C5C17E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF338717-EFC2-4DE9-8D7E-DD88F6C5C17E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF338717-EFC2-4DE9-8D7E-DD88F6C5C17E}.Release|Any CPU.Build.0 = Release|Any CPU
{83FE1916-A3C2-485F-A1DC-83C32F3CDD11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83FE1916-A3C2-485F-A1DC-83C32F3CDD11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83FE1916-A3C2-485F-A1DC-83C32F3CDD11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83FE1916-A3C2-485F-A1DC-83C32F3CDD11}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CAE56FA8-47C5-4B1F-AB39-2F7D046A9021} = {016D6892-C42E-41BB-92C0-10AFDD607B64}
Expand All @@ -114,5 +120,6 @@ Global
{283EA675-8B59-4141-A7F3-90CFADAC33A8} = {016D6892-C42E-41BB-92C0-10AFDD607B64}
{6B2188FC-D14C-42D6-93A1-9CCB6FDFC104} = {016D6892-C42E-41BB-92C0-10AFDD607B64}
{AF338717-EFC2-4DE9-8D7E-DD88F6C5C17E} = {016D6892-C42E-41BB-92C0-10AFDD607B64}
{83FE1916-A3C2-485F-A1DC-83C32F3CDD11} = {016D6892-C42E-41BB-92C0-10AFDD607B64}
EndGlobalSection
EndGlobal
17 changes: 17 additions & 0 deletions src/Examples.Graphics.Console/Examples.Graphics.Console.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Examples</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PDFiumSharpV2" Version="1.1.4" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.8" />
</ItemGroup>

</Project>
27 changes: 27 additions & 0 deletions src/Examples.Graphics.Console/Graphics/ImageExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Examples.Graphics;

public static class ImageExtensions
{
public static string GetMimeType(this byte[] source)
{
var found = images.FirstOrDefault(x => source.Length > x.MagicNumber.Length
&& x.MagicNumber.AsSpan().SequenceEqual(source.AsSpan()[..x.MagicNumber.Length])
);
if (found is not null)
{
return found.MimeType;
}

return "application/octet-stream";
}

private record Entry(string MimeType, byte[] MagicNumber);
private static readonly IEnumerable<Entry> images = [
new("image/jpeg", [0xff, 0xd8]),
new("image/png", [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
new("image/gif", [0x47, 0x49, 0x46, 0x38, 0x37, 0x61])

];

}

84 changes: 84 additions & 0 deletions src/Examples.Graphics.Console/Graphics/PdfConvertor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Runtime.InteropServices;
using PDFiumSharp;
using SkiaSharp;

namespace Examples.Graphics;

public class PdfConvertor
{
private static readonly byte[] Header = [0x25, 0x50, 0x44, 0x46];

static PdfConvertor()
{
// ???

NativeLibrary.SetDllImportResolver(typeof(PDFium).Assembly, (name, assembly, searchPath) =>
{
IntPtr libHandle = IntPtr.Zero;

if (name == "pdfium_x64" && RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
if (!NativeLibrary.TryLoad("./runtimes/linux-x64/native/libpdfium.so",
assembly,
DllImportSearchPath.ApplicationDirectory,
out libHandle))
{
NativeLibrary.TryLoad("libpdfium.so",
assembly,
DllImportSearchPath.ApplicationDirectory,
out libHandle);
}
}

return libHandle;
});
}


public static bool IsPdf(byte[] source)
{
return Header.AsSpan().SequenceEqual(source.AsSpan()[..Header.Length]);
}

public static ImageSource? ToPng(byte[] source)
{
if (!IsPdf(source)) { throw new ArgumentException($"{nameof(source)} is not PDF."); }

using var doc = new PdfDocument(source);
return ToImage(doc, SKEncodedImageFormat.Png);
}

public static ImageSource? ToJpeg(byte[] source, int quality)
{
if (!IsPdf(source)) { throw new ArgumentException($"{nameof(source)} is not PDF."); }

using var doc = new PdfDocument(source);
return ToImage(doc, SKEncodedImageFormat.Jpeg, quality);
}

public static ImageSource? ToImage(PdfDocument doc, SKEncodedImageFormat format, int quality = 100)
{
using var page = doc.Pages.FirstOrDefault();

var width = (int?)page?.Width ?? 640;
var height = (int?)page?.Height ?? 480;

using var bitmap = new PDFiumBitmap(width, height, hasAlpha: true);

bitmap.Fill(new PDFiumSharp.Types.FPDF_COLOR(255, 255, 255));
page?.Render(bitmap);

using var pixmap = new SKPixmap(
new(bitmap.Width, bitmap.Height, SKColorType.Bgra8888),
bitmap.Scan0,
bitmap.Stride);

using var encoded = pixmap.Encode(format, quality);

return new(encoded.ToArray(), pixmap.Width, pixmap.Height);
}

public record ImageSource(byte[] Data, double Width, double Height);


}
2 changes: 2 additions & 0 deletions src/Examples.Graphics.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");