@@ -676,6 +676,23 @@ public void CreateMultiFrameTiffStream_Empty_Sequence_Throws()
676676 act . Should ( ) . Throw < ArgumentException > ( ) ;
677677 }
678678
679+ [ FactWithAutomaticDisplayName ]
680+ public void CreateMultiFrameTiffBytes_PreservesResolution_FromPixelsPerMeterSource ( )
681+ {
682+ const double dpi = 300d ;
683+ double pixelsPerMetre = dpi / 0.0254d ; // 300 DPI expressed in pixels per metre
684+
685+ using var page = MakeBitmapWithResolution ( 220 , 300 , new Rgb24 ( 40 , 90 , 160 ) ,
686+ pixelsPerMetre , PixelResolutionUnit . PixelsPerMeter ) ;
687+
688+ byte [ ] tiff = AnyBitmap . CreateMultiFrameTiffBytes ( new [ ] { page } ) ;
689+ var pages = ReadTiffDirectories ( tiff ) ;
690+
691+ pages . Should ( ) . ContainSingle ( ) ;
692+ ToDotsPerInch ( pages [ 0 ] . XResolution , pages [ 0 ] . ResolutionUnit )
693+ . Should ( ) . BeApproximately ( dpi , 2d ) ;
694+ }
695+
679696 [ FactWithAutomaticDisplayName ]
680697 public void CreateMultiFrameTiff_Preserves_Rgb24_Pixels ( )
681698 {
@@ -707,12 +724,68 @@ public void CreateMultiFrameTiff_Preserves_Rgb24_Pixels()
707724 }
708725 }
709726
727+ [ TheoryWithAutomaticDisplayName ]
728+ [ InlineData ( "Rgb24" ) ]
729+ [ InlineData ( "Bgr24" ) ]
730+ [ InlineData ( "Rgba32" ) ]
731+ [ InlineData ( "Bgra32" ) ]
732+ [ InlineData ( "Abgr32" ) ]
733+ [ InlineData ( "Argb32" ) ]
734+ public void CreateMultiFrameTiff_PreservesColors_ForAllPixelFormats ( string pixelFormat )
735+ {
736+ const byte r = 10 , g = 120 , b = 240 ;
737+ using var bmp = MakeSolidBitmapOfFormat ( pixelFormat , 64 , 48 , r , g , b ) ;
738+
739+ using var result = AnyBitmap . CreateMultiFrameTiff ( new [ ] { bmp } ) ;
740+
741+ result . Width . Should ( ) . Be ( 64 ) ;
742+ result . Height . Should ( ) . Be ( 48 ) ;
743+
744+ foreach ( var ( x , y ) in new [ ] { ( 0 , 0 ) , ( 63 , 0 ) , ( 0 , 47 ) , ( 32 , 24 ) , ( 63 , 47 ) } )
745+ {
746+ var px = result . GetPixel ( x , y ) ;
747+ px . R . Should ( ) . Be ( r , $ "R at ({ x } ,{ y } ) for { pixelFormat } ") ;
748+ px . G . Should ( ) . Be ( g , $ "G at ({ x } ,{ y } ) for { pixelFormat } ") ;
749+ px . B . Should ( ) . Be ( b , $ "B at ({ x } ,{ y } ) for { pixelFormat } ") ;
750+ }
751+ }
752+
753+ /// <summary>
754+ /// Builds a solid <see cref="AnyBitmap"/> whose backing image uses the requested
755+ /// ImageSharp pixel format. The colour is given in logical R,G,B order regardless of
756+ /// the format's in-memory byte layout. The image is force-loaded so the original
757+ /// pixel format (not a re-encoded copy) reaches the TIFF writer.
758+ /// </summary>
759+ private static AnyBitmap MakeSolidBitmapOfFormat ( string format , int width , int height , byte r , byte g , byte b )
760+ {
761+ Image image = format switch
762+ {
763+ "Rgb24" => new Image < Rgb24 > ( width , height , new Rgb24 ( r , g , b ) ) ,
764+ "Bgr24" => new Image < Bgr24 > ( width , height , new Bgr24 ( r , g , b ) ) ,
765+ "Rgba32" => new Image < Rgba32 > ( width , height , new Rgba32 ( r , g , b , 255 ) ) ,
766+ "Bgra32" => new Image < Bgra32 > ( width , height , new Bgra32 ( r , g , b , 255 ) ) ,
767+ "Abgr32" => new Image < Abgr32 > ( width , height , new Abgr32 ( r , g , b , 255 ) ) ,
768+ "Argb32" => new Image < Argb32 > ( width , height , new Argb32 ( r , g , b , 255 ) ) ,
769+ _ => throw new ArgumentOutOfRangeException ( nameof ( format ) , format , "Unsupported pixel format" )
770+ } ;
771+
772+ var bitmap = ( AnyBitmap ) image ;
773+ _ = bitmap . Width ; // materialise so the original pixel format reaches the writer
774+ return bitmap ;
775+ }
776+
710777 private static AnyBitmap CreateSolidBitmap ( int width , int height , Rgb24 color , int dpi )
778+ {
779+ return MakeBitmapWithResolution ( width , height , color , dpi , PixelResolutionUnit . PixelsPerInch ) ;
780+ }
781+
782+ private static AnyBitmap MakeBitmapWithResolution ( int width , int height , Rgb24 color ,
783+ double resolution , PixelResolutionUnit unit )
711784 {
712785 var image = new SixLabors . ImageSharp . Image < Rgb24 > ( width , height , color ) ;
713- image . Metadata . HorizontalResolution = dpi ;
714- image . Metadata . VerticalResolution = dpi ;
715- image . Metadata . ResolutionUnits = PixelResolutionUnit . PixelsPerInch ;
786+ image . Metadata . HorizontalResolution = resolution ;
787+ image . Metadata . VerticalResolution = resolution ;
788+ image . Metadata . ResolutionUnits = unit ;
716789 return image ;
717790 }
718791
0 commit comments