Skip to content

Commit c18d119

Browse files
committed
SkiaSharp based TIFf to PDF poc
1 parent 11ee8e0 commit c18d119

File tree

3 files changed

+123
-18
lines changed

3 files changed

+123
-18
lines changed

GithubActionsHelloWorld/GithubActionsHelloWorld.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
</PropertyGroup>
2121

2222
<ItemGroup>
23+
<PackageReference Include="BitMiracle.LibTiff.NET" Version="2.4.649" />
2324
<PackageReference Include="PdfSharpCore" Version="1.3.40" />
24-
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
25+
<PackageReference Include="SkiaSharp" Version="2.88.2" />
2526
</ItemGroup>
2627

2728
</Project>

GithubActionsHelloWorld/Program.cs

Lines changed: 121 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
using PdfSharpCore.Drawing;
1+
using BitMiracle.LibTiff.Classic;
2+
using PdfSharpCore.Drawing;
23
using PdfSharpCore.Fonts;
34
using PdfSharpCore.Pdf;
45
using PdfSharpCore.Utils;
5-
using SixLabors.ImageSharp;
6+
using SkiaSharp;
7+
using System.Collections.Generic;
68
using System.IO;
9+
using System.Runtime.InteropServices;
710
using System.Threading.Tasks;
811

912
namespace GithubActionsHelloWorld
@@ -15,17 +18,22 @@ public static async Task Main(string[] args)
1518
GlobalFontSettings.FontResolver = new FontResolver();
1619

1720
var document = new PdfDocument();
21+
var fileStream = File.OpenRead(args[0]); ;
1822

19-
using (var tiff = Image.Load(args[0]))
23+
var pageImages = tiffToBitmap(args[0]);
24+
for (int pageIndex = 0; pageIndex < pageImages.Count; pageIndex++)
2025

21-
for (var pageIndex = 0; pageIndex < tiff.Frames.Count; pageIndex++)
22-
{
23-
var pageImage = await ConvertToXImageAsync(tiff.Frames.CloneFrame(pageIndex));
24-
var pageWithImage = new PdfPage();
25-
document.Pages.Add(pageWithImage);
26-
var xgr = XGraphics.FromPdfPage(document.Pages[pageIndex]);
27-
xgr.DrawImage(pageImage, 0, 0);
28-
}
26+
{
27+
var pageWithImage = new PdfPage();
28+
document.Pages.Add(pageWithImage);
29+
var xgr = XGraphics.FromPdfPage(document.Pages[pageIndex]);
30+
31+
// var memorystream = new MemoryStream(pageImage.Bytes);
32+
//memorystream.Position = 0;
33+
//var xImage = XImage.FromStream(() => memorystream);
34+
var xImage = XImage.FromStream(() => File.OpenRead(pageImages[pageIndex]));
35+
xgr.DrawImage(xImage, 0, 0);
36+
}
2937

3038
var page = document.AddPage();
3139
var gfx = XGraphics.FromPdfPage(page);
@@ -40,13 +48,109 @@ public static async Task Main(string[] args)
4048
document.Save("helloworld.pdf");
4149
}
4250

43-
private static async Task<XImage> ConvertToXImageAsync(Image imageFrame)
51+
private static List<string> tiffToBitmap(string fileName)
52+
{
53+
var tempPaths = new List<string>();
54+
55+
using var tiff = Tiff.Open(fileName, "r");
56+
57+
var numberIfTiffPages = getNumberofTiffPages(tiff);
58+
59+
for (short i = 0; i < numberIfTiffPages; i++)
60+
{
61+
tiff.SetDirectory(i);
62+
63+
// read the dimensions
64+
var width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
65+
var height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
66+
67+
// create the bitmap
68+
var bitmap = new SKBitmap();
69+
var info = new SKImageInfo(width, height);
70+
71+
// create the buffer that will hold the pixels
72+
var raster = new int[width * height];
73+
74+
// get a pointer to the buffer, and give it to the bitmap
75+
var ptr = GCHandle.Alloc(raster, GCHandleType.Pinned);
76+
bitmap.InstallPixels(info, ptr.AddrOfPinnedObject(), info.RowBytes, null, (addr, ctx) => ptr.Free(), null);
77+
78+
// read the image into the memory buffer
79+
if (!tiff.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT))
80+
{
81+
// not a valid TIF image.
82+
return null;
83+
}
84+
85+
// swap the red and blue because SkiaSharp may differ from the tiff
86+
if (SKImageInfo.PlatformColorType == SKColorType.Bgra8888)
87+
{
88+
SKSwizzle.SwapRedBlue(ptr.AddrOfPinnedObject(), raster.Length);
89+
}
90+
91+
var encodedData = bitmap.Encode(SKEncodedImageFormat.Png, 100);
92+
93+
var tempPath = Path.Combine(Path.GetTempFileName() + ".png");
94+
using var bitmapImageStream = File.Open(tempPath, FileMode.Create, FileAccess.Write, FileShare.None);
95+
encodedData.SaveTo(bitmapImageStream);
96+
tempPaths.Add(tempPath);
97+
}
98+
return tempPaths;
99+
}
100+
101+
public static int getNumberofTiffPages(Tiff image)
102+
{
103+
int pageCount = 0;
104+
do
105+
{
106+
++pageCount;
107+
} while (image.ReadDirectory());
108+
109+
return pageCount;
110+
}
111+
112+
public static SKBitmap OpenTiff(Stream tiffStream)
44113
{
45-
using var memoryStream = new MemoryStream();
46-
await imageFrame.SaveAsPngAsync(memoryStream);
47-
memoryStream.Position = 0;
48-
var image = XImage.FromStream(() => memoryStream);
49-
return image;
114+
// https://stackoverflow.com/questions/50312937/skiasharp-tiff-support
115+
116+
tiffStream.Position = 0;
117+
// open a TIFF stored in the stream
118+
using (var tifImg = Tiff.ClientOpen("in-memory", "r", tiffStream, new TiffStream()))
119+
{
120+
tifImg.SetDirectory(1);
121+
122+
// read the dimensions
123+
var width = tifImg.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
124+
var height = tifImg.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
125+
126+
// create the bitmap
127+
var bitmap = new SKBitmap();
128+
var info = new SKImageInfo(width, height);
129+
130+
// create the buffer that will hold the pixels
131+
var raster = new int[width * height];
132+
133+
// get a pointer to the buffer, and give it to the bitmap
134+
var ptr = GCHandle.Alloc(raster, GCHandleType.Pinned);
135+
bitmap.InstallPixels(info, ptr.AddrOfPinnedObject(), info.RowBytes, null, (addr, ctx) => ptr.Free(), null);
136+
137+
// read the image into the memory buffer
138+
if (!tifImg.ReadRGBAImageOriented(width, height, raster, Orientation.TOPLEFT, true))
139+
{
140+
// not a valid TIF image.
141+
return null;
142+
}
143+
144+
// swap the red and blue because SkiaSharp may differ from the tiff
145+
if (SKImageInfo.PlatformColorType == SKColorType.Bgra8888)
146+
{
147+
SKSwizzle.SwapRedBlue(ptr.AddrOfPinnedObject(), raster.Length);
148+
}
149+
150+
File.WriteAllBytes("test.bmp", bitmap.Bytes);
151+
152+
return bitmap;
153+
}
50154
}
51155
}
52156
}
14 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)