@@ -153,6 +153,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
153153 this . currentStream . Skip ( 8 ) ;
154154 Image < TPixel > ? image = null ;
155155 FrameControl ? previousFrameControl = null ;
156+ ImageFrame < TPixel > ? previousFrame = null ;
156157 ImageFrame < TPixel > ? currentFrame = null ;
157158 Span < byte > buffer = stackalloc byte [ 20 ] ;
158159
@@ -213,7 +214,21 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
213214 }
214215
215216 this . currentStream . Position += 4 ;
216- this . ReadScanlines ( chunk . Length - 4 , currentFrame , pngMetadata , this . ReadNextDataChunkAndSkipSeq , previousFrameControl . Value , cancellationToken ) ;
217+ this . ReadScanlines (
218+ chunk . Length - 4 ,
219+ currentFrame ,
220+ pngMetadata ,
221+ this . ReadNextDataChunkAndSkipSeq ,
222+ previousFrameControl . Value ,
223+ cancellationToken ) ;
224+
225+ PngFrameMetadata pngFrameMetadata = currentFrame . Metadata . GetPngFrameMetadata ( ) ;
226+ if ( previousFrame != null && pngFrameMetadata . BlendMethod == PngBlendMethod . Over )
227+ {
228+ this . AlphaBlend ( previousFrame , currentFrame ) ;
229+ }
230+
231+ previousFrame = currentFrame ;
217232 previousFrameControl = null ;
218233 break ;
219234 case PngChunkType . Data :
@@ -225,8 +240,15 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
225240 AssignColorPalette ( this . palette , this . paletteAlpha , pngMetadata ) ;
226241 }
227242
228- FrameControl frameControl = previousFrameControl ?? new ( 0 , ( uint ) this . header . Width , ( uint ) this . header . Height , 0 , 0 , 0 , 0 , default , default ) ;
229- this . ReadScanlines ( chunk . Length , image . Frames . RootFrame , pngMetadata , this . ReadNextDataChunk , in frameControl , cancellationToken ) ;
243+ FrameControl frameControl = previousFrameControl ?? new ( ( uint ) this . header . Width , ( uint ) this . header . Height ) ;
244+ this . ReadScanlines (
245+ chunk . Length ,
246+ image . Frames . RootFrame ,
247+ pngMetadata ,
248+ this . ReadNextDataChunk ,
249+ in frameControl ,
250+ cancellationToken ) ;
251+
230252 previousFrameControl = null ;
231253 break ;
232254 case PngChunkType . Palette :
@@ -698,10 +720,15 @@ private void ReadScanlines<TPixel>(int chunkLength, ImageFrame<TPixel> image, Pn
698720 /// <typeparam name="TPixel">The pixel format.</typeparam>
699721 /// <param name="frameControl">The frame control</param>
700722 /// <param name="compressedStream">The compressed pixel data stream.</param>
701- /// <param name="image ">The image to decode to.</param>
723+ /// <param name="imageFrame ">The image frame to decode to.</param>
702724 /// <param name="pngMetadata">The png metadata</param>
703725 /// <param name="cancellationToken">The CancellationToken</param>
704- private void DecodePixelData < TPixel > ( FrameControl frameControl , DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
726+ private void DecodePixelData < TPixel > (
727+ FrameControl frameControl ,
728+ DeflateStream compressedStream ,
729+ ImageFrame < TPixel > imageFrame ,
730+ PngMetadata pngMetadata ,
731+ CancellationToken cancellationToken )
705732 where TPixel : unmanaged, IPixel < TPixel >
706733 {
707734 int currentRow = ( int ) frameControl . YOffset ;
@@ -750,24 +777,27 @@ private void DecodePixelData<TPixel>(FrameControl frameControl, DeflateStream co
750777 break ;
751778 }
752779
753- this . ProcessDefilteredScanline ( frameControl , currentRow , scanlineSpan , image , pngMetadata ) ;
754-
780+ this . ProcessDefilteredScanline ( frameControl , currentRow , scanlineSpan , imageFrame , pngMetadata ) ;
755781 this . SwapScanlineBuffers ( ) ;
756782 currentRow ++ ;
757783 }
758784 }
759785
760786 /// <summary>
761787 /// Decodes the raw interlaced pixel data row by row
762- /// <see href="https://github.com/juehv/DentalImageViewer/blob/8a1a4424b15d6cc453b5de3f273daf3ff5e3a90d/DentalImageViewer/lib/jiu-0.14.3/net/sourceforge/jiu/codecs/PNGCodec.java"/>
763788 /// </summary>
764789 /// <typeparam name="TPixel">The pixel format.</typeparam>
765790 /// <param name="frameControl">The frame control</param>
766791 /// <param name="compressedStream">The compressed pixel data stream.</param>
767792 /// <param name="image">The current image.</param>
768793 /// <param name="pngMetadata">The png metadata.</param>
769794 /// <param name="cancellationToken">The cancellation token.</param>
770- private void DecodeInterlacedPixelData < TPixel > ( in FrameControl frameControl , DeflateStream compressedStream , ImageFrame < TPixel > image , PngMetadata pngMetadata , CancellationToken cancellationToken )
795+ private void DecodeInterlacedPixelData < TPixel > (
796+ in FrameControl frameControl ,
797+ DeflateStream compressedStream ,
798+ ImageFrame < TPixel > image ,
799+ PngMetadata pngMetadata ,
800+ CancellationToken cancellationToken )
771801 where TPixel : unmanaged, IPixel < TPixel >
772802 {
773803 int currentRow = Adam7 . FirstRow [ 0 ] + ( int ) frameControl . YOffset ;
@@ -845,6 +875,7 @@ private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, Def
845875 pixelOffset : Adam7 . FirstColumn [ pass ] ,
846876 increment : Adam7 . ColumnIncrement [ pass ] ) ;
847877
878+ // TODO: Alpha blending.
848879 this . SwapScanlineBuffers ( ) ;
849880
850881 currentRow += Adam7 . RowIncrement [ pass ] ;
@@ -874,7 +905,12 @@ private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, Def
874905 /// <param name="defilteredScanline">The de-filtered scanline</param>
875906 /// <param name="pixels">The image</param>
876907 /// <param name="pngMetadata">The png metadata.</param>
877- private void ProcessDefilteredScanline < TPixel > ( in FrameControl frameControl , int currentRow , ReadOnlySpan < byte > defilteredScanline , ImageFrame < TPixel > pixels , PngMetadata pngMetadata )
908+ private void ProcessDefilteredScanline < TPixel > (
909+ in FrameControl frameControl ,
910+ int currentRow ,
911+ ReadOnlySpan < byte > defilteredScanline ,
912+ ImageFrame < TPixel > pixels ,
913+ PngMetadata pngMetadata )
878914 where TPixel : unmanaged, IPixel < TPixel >
879915 {
880916 Span < TPixel > rowSpan = pixels . PixelBuffer . DangerousGetRowSpan ( currentRow ) ;
@@ -1841,4 +1877,21 @@ private static bool IsXmpTextData(ReadOnlySpan<byte> keywordBytes)
18411877
18421878 private void SwapScanlineBuffers ( )
18431879 => ( this . scanline , this . previousScanline ) = ( this . previousScanline , this . scanline ) ;
1880+
1881+ private void AlphaBlend < TPixel > ( ImageFrame < TPixel > src , ImageFrame < TPixel > dst )
1882+ where TPixel : unmanaged, IPixel < TPixel >
1883+ {
1884+ Buffer2D < TPixel > srcPixels = src . PixelBuffer ;
1885+ Buffer2D < TPixel > dstPixels = dst . PixelBuffer ;
1886+ PixelBlender < TPixel > blender =
1887+ PixelOperations < TPixel > . Instance . GetPixelBlender ( PixelColorBlendingMode . Normal , PixelAlphaCompositionMode . SrcOver ) ;
1888+
1889+ for ( int y = 0 ; y < src . Height ; y ++ )
1890+ {
1891+ Span < TPixel > srcPixelRow = srcPixels . DangerousGetRowSpan ( y ) ;
1892+ Span < TPixel > dstPixelRow = dstPixels . DangerousGetRowSpan ( y ) ;
1893+
1894+ blender . Blend < TPixel > ( this . configuration , dstPixelRow , srcPixelRow , dstPixelRow , 1f ) ;
1895+ }
1896+ }
18441897}
0 commit comments