@@ -228,6 +228,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
228228 this . currentStream . Position += 4 ; // Skip sequence number
229229 return length - 4 ;
230230 } ,
231+ lastFrameControl . Value ,
231232 cancellationToken ) ;
232233 lastFrameControl = null ;
233234 break ;
@@ -237,7 +238,9 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
237238 this . InitializeImage ( metadata , lastFrameControl , out image ) ;
238239 }
239240
240- this . ReadScanlines ( chunk . Length , image . Frames . RootFrame , pngMetadata , this . ReadNextDataChunk , cancellationToken ) ;
241+ FrameControl frameControl = lastFrameControl ?? new ( 0 , this . header . Width , this . header . Height , 0 , 0 , 0 , 0 , default , default ) ;
242+
243+ this . ReadScanlines ( chunk . Length , image . Frames . RootFrame , pngMetadata , this . ReadNextDataChunk , frameControl , cancellationToken ) ;
241244 lastFrameControl = null ;
242245 break ;
243246 case PngChunkType . Palette :
@@ -682,8 +685,9 @@ private int CalculateScanlineLength(int width)
682685 /// <param name="image"> The pixel data.</param>
683686 /// <param name="pngMetadata">The png metadata</param>
684687 /// <param name="getData">A delegate to get more data from the inner stream for <see cref="ZlibInflateStream"/>.</param>
688+ /// <param name="frameControl">The frame control</param>
685689 /// <param name="cancellationToken">The cancellation token.</param>
686- private void ReadScanlines < TPixel > ( int chunkLength , ImageFrame < TPixel > image , PngMetadata pngMetadata , Func < int > getData , CancellationToken cancellationToken )
690+ private void ReadScanlines < TPixel > ( int chunkLength , ImageFrame < TPixel > image , PngMetadata pngMetadata , Func < int > getData , FrameControl frameControl , CancellationToken cancellationToken )
687691 where TPixel : unmanaged, IPixel < TPixel >
688692 {
689693 using ZlibInflateStream deframeStream = new ( this . currentStream , getData ) ;
@@ -692,28 +696,29 @@ private void ReadScanlines<TPixel>(int chunkLength, ImageFrame<TPixel> image, Pn
692696
693697 if ( this . header . InterlaceMethod is PngInterlaceMode . Adam7 )
694698 {
695- this . DecodeInterlacedPixelData ( dataStream , image , pngMetadata , cancellationToken ) ;
699+ this . DecodeInterlacedPixelData ( frameControl , dataStream , image , pngMetadata , cancellationToken ) ;
696700 }
697701 else
698702 {
699- this . DecodePixelData ( dataStream , image , pngMetadata , cancellationToken ) ;
703+ this . DecodePixelData ( frameControl , dataStream , image , pngMetadata , cancellationToken ) ;
700704 }
701705 }
702706
703707 /// <summary>
704708 /// Decodes the raw pixel data row by row
705709 /// </summary>
706710 /// <typeparam name="TPixel">The pixel format.</typeparam>
711+ /// <param name="frameControl">The frame control</param>
707712 /// <param name="compressedStream">The compressed pixel data stream.</param>
708713 /// <param name="image">The image to decode to.</param>
709714 /// <param name="pngMetadata">The png metadata</param>
710715 /// <param name="cancellationToken">The CancellationToken</param>
711- private void DecodePixelData < TPixel > ( DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
716+ private void DecodePixelData < TPixel > ( FrameControl frameControl , DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
712717 where TPixel : unmanaged, IPixel < TPixel >
713718 {
714- int currentRow = Adam7 . FirstRow [ 0 ] ;
719+ int currentRow = frameControl . YOffset ;
715720 int currentRowBytesRead = 0 ;
716- int height = image . Metadata . TryGetPngFrameMetadata ( out PngFrameMetadata ? frameMetadata ) ? frameMetadata . Height : this . header . Height ;
721+ int height = frameControl . Height ;
717722 while ( currentRow < height )
718723 {
719724 cancellationToken . ThrowIfCancellationRequested ( ) ;
@@ -757,7 +762,7 @@ private void DecodePixelData<TPixel>(DeflateStream compressedStream, ImageFrame<
757762 break ;
758763 }
759764
760- this . ProcessDefilteredScanline ( currentRow , scanlineSpan , image , pngMetadata ) ;
765+ this . ProcessDefilteredScanline ( frameControl , currentRow , scanlineSpan , image , pngMetadata ) ;
761766
762767 this . SwapScanlineBuffers ( ) ;
763768 currentRow ++ ;
@@ -769,23 +774,19 @@ private void DecodePixelData<TPixel>(DeflateStream compressedStream, ImageFrame<
769774 /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
770775 /// </summary>
771776 /// <typeparam name="TPixel">The pixel format.</typeparam>
777+ /// <param name="frameControl">The frame control</param>
772778 /// <param name="compressedStream">The compressed pixel data stream.</param>
773779 /// <param name="image">The current image.</param>
774780 /// <param name="pngMetadata">The png metadata.</param>
775781 /// <param name="cancellationToken">The cancellation token.</param>
776- private void DecodeInterlacedPixelData < TPixel > ( DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
782+ private void DecodeInterlacedPixelData < TPixel > ( FrameControl frameControl , DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
777783 where TPixel : unmanaged, IPixel < TPixel >
778784 {
779- int currentRow = Adam7 . FirstRow [ 0 ] ;
785+ int currentRow = Adam7 . FirstRow [ 0 ] + frameControl . YOffset ;
780786 int currentRowBytesRead = 0 ;
781787 int pass = 0 ;
782- int width = this . header . Width ;
783- int height = this . header . Height ;
784- if ( image . Metadata . TryGetPngFrameMetadata ( out PngFrameMetadata ? frameMetadata ) )
785- {
786- width = frameMetadata . Width ;
787- height = frameMetadata . Height ;
788- }
788+ int width = frameControl . Width ;
789+ int height = frameControl . Height ;
789790
790791 Buffer2D < TPixel > imageBuffer = image . PixelBuffer ;
791792 while ( true )
@@ -848,7 +849,7 @@ private void DecodeInterlacedPixelData<TPixel>(DeflateStream compressedStream, I
848849 }
849850
850851 Span < TPixel > rowSpan = imageBuffer . DangerousGetRowSpan ( currentRow ) ;
851- this . ProcessInterlacedDefilteredScanline ( this . scanline . GetSpan ( ) , rowSpan , pngMetadata , Adam7 . FirstColumn [ pass ] , Adam7 . ColumnIncrement [ pass ] ) ;
852+ this . ProcessInterlacedDefilteredScanline ( frameControl , this . scanline . GetSpan ( ) , rowSpan , pngMetadata , pixelOffset : Adam7 . FirstColumn [ pass ] , increment : Adam7 . ColumnIncrement [ pass ] ) ;
852853
853854 this . SwapScanlineBuffers ( ) ;
854855
@@ -874,11 +875,12 @@ private void DecodeInterlacedPixelData<TPixel>(DeflateStream compressedStream, I
874875 /// Processes the de-filtered scanline filling the image pixel data
875876 /// </summary>
876877 /// <typeparam name="TPixel">The pixel format.</typeparam>
878+ /// <param name="frameControl">The frame control</param>
877879 /// <param name="currentRow">The index of the current scanline being processed.</param>
878880 /// <param name="defilteredScanline">The de-filtered scanline</param>
879881 /// <param name="pixels">The image</param>
880882 /// <param name="pngMetadata">The png metadata.</param>
881- private void ProcessDefilteredScanline < TPixel > ( int currentRow , ReadOnlySpan < byte > defilteredScanline , ImageFrame < TPixel > pixels , PngMetadata pngMetadata )
883+ private void ProcessDefilteredScanline < TPixel > ( FrameControl frameControl , int currentRow , ReadOnlySpan < byte > defilteredScanline , ImageFrame < TPixel > pixels , PngMetadata pngMetadata )
882884 where TPixel : unmanaged, IPixel < TPixel >
883885 {
884886 Span < TPixel > rowSpan = pixels . PixelBuffer . DangerousGetRowSpan ( currentRow ) ;
@@ -902,7 +904,8 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
902904 {
903905 case PngColorType . Grayscale :
904906 PngScanlineProcessor . ProcessGrayscaleScanline (
905- this . header ,
907+ this . header . BitDepth ,
908+ frameControl ,
906909 scanlineSpan ,
907910 rowSpan ,
908911 pngMetadata . HasTransparency ,
@@ -913,7 +916,8 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
913916
914917 case PngColorType . GrayscaleWithAlpha :
915918 PngScanlineProcessor . ProcessGrayscaleWithAlphaScanline (
916- this . header ,
919+ this . header . BitDepth ,
920+ frameControl ,
917921 scanlineSpan ,
918922 rowSpan ,
919923 ( uint ) this . bytesPerPixel ,
@@ -923,7 +927,7 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
923927
924928 case PngColorType . Palette :
925929 PngScanlineProcessor . ProcessPaletteScanline (
926- this . header ,
930+ frameControl ,
927931 scanlineSpan ,
928932 rowSpan ,
929933 this . palette ,
@@ -933,8 +937,8 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
933937
934938 case PngColorType . Rgb :
935939 PngScanlineProcessor . ProcessRgbScanline (
936- this . configuration ,
937- this . header ,
940+ this . header . BitDepth ,
941+ frameControl ,
938942 scanlineSpan ,
939943 rowSpan ,
940944 this . bytesPerPixel ,
@@ -947,8 +951,8 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
947951
948952 case PngColorType . RgbWithAlpha :
949953 PngScanlineProcessor . ProcessRgbaScanline (
950- this . configuration ,
951- this . header ,
954+ this . header . BitDepth ,
955+ frameControl ,
952956 scanlineSpan ,
953957 rowSpan ,
954958 this . bytesPerPixel ,
@@ -967,12 +971,13 @@ private void ProcessDefilteredScanline<TPixel>(int currentRow, ReadOnlySpan<byte
967971 /// Processes the interlaced de-filtered scanline filling the image pixel data
968972 /// </summary>
969973 /// <typeparam name="TPixel">The pixel format.</typeparam>
974+ /// <param name="frameControl">The frame control</param>
970975 /// <param name="defilteredScanline">The de-filtered scanline</param>
971976 /// <param name="rowSpan">The current image row.</param>
972977 /// <param name="pngMetadata">The png metadata.</param>
973978 /// <param name="pixelOffset">The column start index. Always 0 for none interlaced images.</param>
974979 /// <param name="increment">The column increment. Always 1 for none interlaced images.</param>
975- private void ProcessInterlacedDefilteredScanline < TPixel > ( ReadOnlySpan < byte > defilteredScanline , Span < TPixel > rowSpan , PngMetadata pngMetadata , int pixelOffset = 0 , int increment = 1 )
980+ private void ProcessInterlacedDefilteredScanline < TPixel > ( FrameControl frameControl , ReadOnlySpan < byte > defilteredScanline , Span < TPixel > rowSpan , PngMetadata pngMetadata , int pixelOffset = 0 , int increment = 1 )
976981 where TPixel : unmanaged, IPixel < TPixel >
977982 {
978983 // Trim the first marker byte from the buffer
@@ -994,7 +999,8 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(ReadOnlySpan<byte> defi
994999 {
9951000 case PngColorType . Grayscale :
9961001 PngScanlineProcessor . ProcessInterlacedGrayscaleScanline (
997- this . header ,
1002+ this . header . BitDepth ,
1003+ frameControl ,
9981004 scanlineSpan ,
9991005 rowSpan ,
10001006 ( uint ) pixelOffset ,
@@ -1007,7 +1013,8 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(ReadOnlySpan<byte> defi
10071013
10081014 case PngColorType . GrayscaleWithAlpha :
10091015 PngScanlineProcessor . ProcessInterlacedGrayscaleWithAlphaScanline (
1010- this . header ,
1016+ this . header . BitDepth ,
1017+ frameControl ,
10111018 scanlineSpan ,
10121019 rowSpan ,
10131020 ( uint ) pixelOffset ,
@@ -1019,7 +1026,7 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(ReadOnlySpan<byte> defi
10191026
10201027 case PngColorType . Palette :
10211028 PngScanlineProcessor . ProcessInterlacedPaletteScanline (
1022- this . header ,
1029+ frameControl ,
10231030 scanlineSpan ,
10241031 rowSpan ,
10251032 ( uint ) pixelOffset ,
@@ -1031,7 +1038,8 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(ReadOnlySpan<byte> defi
10311038
10321039 case PngColorType . Rgb :
10331040 PngScanlineProcessor . ProcessInterlacedRgbScanline (
1034- this . header ,
1041+ this . header . BitDepth ,
1042+ frameControl ,
10351043 scanlineSpan ,
10361044 rowSpan ,
10371045 ( uint ) pixelOffset ,
@@ -1046,7 +1054,8 @@ private void ProcessInterlacedDefilteredScanline<TPixel>(ReadOnlySpan<byte> defi
10461054
10471055 case PngColorType . RgbWithAlpha :
10481056 PngScanlineProcessor . ProcessInterlacedRgbaScanline (
1049- this . header ,
1057+ this . header . BitDepth ,
1058+ frameControl ,
10501059 scanlineSpan ,
10511060 rowSpan ,
10521061 ( uint ) pixelOffset ,
0 commit comments