1- using PdfSharpCore . Drawing ;
1+ using BitMiracle . LibTiff . Classic ;
2+ using PdfSharpCore . Drawing ;
23using PdfSharpCore . Fonts ;
34using PdfSharpCore . Pdf ;
45using PdfSharpCore . Utils ;
5- using SixLabors . ImageSharp ;
6+ using SkiaSharp ;
7+ using System . Collections . Generic ;
68using System . IO ;
9+ using System . Runtime . InteropServices ;
710using System . Threading . Tasks ;
811
912namespace 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}
0 commit comments