@@ -153,6 +153,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
153
153
this . currentStream . Skip ( 8 ) ;
154
154
Image < TPixel > ? image = null ;
155
155
FrameControl ? previousFrameControl = null ;
156
+ ImageFrame < TPixel > ? previousFrame = null ;
156
157
ImageFrame < TPixel > ? currentFrame = null ;
157
158
Span < byte > buffer = stackalloc byte [ 20 ] ;
158
159
@@ -213,7 +214,21 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
213
214
}
214
215
215
216
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 ;
217
232
previousFrameControl = null ;
218
233
break ;
219
234
case PngChunkType . Data :
@@ -225,8 +240,15 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
225
240
AssignColorPalette ( this . palette , this . paletteAlpha , pngMetadata ) ;
226
241
}
227
242
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
+
230
252
previousFrameControl = null ;
231
253
break ;
232
254
case PngChunkType . Palette :
@@ -698,10 +720,15 @@ private void ReadScanlines<TPixel>(int chunkLength, ImageFrame<TPixel> image, Pn
698
720
/// <typeparam name="TPixel">The pixel format.</typeparam>
699
721
/// <param name="frameControl">The frame control</param>
700
722
/// <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>
702
724
/// <param name="pngMetadata">The png metadata</param>
703
725
/// <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 )
705
732
where TPixel : unmanaged, IPixel < TPixel >
706
733
{
707
734
int currentRow = ( int ) frameControl . YOffset ;
@@ -750,24 +777,27 @@ private void DecodePixelData<TPixel>(FrameControl frameControl, DeflateStream co
750
777
break ;
751
778
}
752
779
753
- this . ProcessDefilteredScanline ( frameControl , currentRow , scanlineSpan , image , pngMetadata ) ;
754
-
780
+ this . ProcessDefilteredScanline ( frameControl , currentRow , scanlineSpan , imageFrame , pngMetadata ) ;
755
781
this . SwapScanlineBuffers ( ) ;
756
782
currentRow ++ ;
757
783
}
758
784
}
759
785
760
786
/// <summary>
761
787
/// 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"/>
763
788
/// </summary>
764
789
/// <typeparam name="TPixel">The pixel format.</typeparam>
765
790
/// <param name="frameControl">The frame control</param>
766
791
/// <param name="compressedStream">The compressed pixel data stream.</param>
767
792
/// <param name="image">The current image.</param>
768
793
/// <param name="pngMetadata">The png metadata.</param>
769
794
/// <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 )
771
801
where TPixel : unmanaged, IPixel < TPixel >
772
802
{
773
803
int currentRow = Adam7 . FirstRow [ 0 ] + ( int ) frameControl . YOffset ;
@@ -845,6 +875,7 @@ private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, Def
845
875
pixelOffset : Adam7 . FirstColumn [ pass ] ,
846
876
increment : Adam7 . ColumnIncrement [ pass ] ) ;
847
877
878
+ // TODO: Alpha blending.
848
879
this . SwapScanlineBuffers ( ) ;
849
880
850
881
currentRow += Adam7 . RowIncrement [ pass ] ;
@@ -874,7 +905,12 @@ private void DecodeInterlacedPixelData<TPixel>(in FrameControl frameControl, Def
874
905
/// <param name="defilteredScanline">The de-filtered scanline</param>
875
906
/// <param name="pixels">The image</param>
876
907
/// <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 )
878
914
where TPixel : unmanaged, IPixel < TPixel >
879
915
{
880
916
Span < TPixel > rowSpan = pixels . PixelBuffer . DangerousGetRowSpan ( currentRow ) ;
@@ -1841,4 +1877,21 @@ private static bool IsXmpTextData(ReadOnlySpan<byte> keywordBytes)
1841
1877
1842
1878
private void SwapScanlineBuffers ( )
1843
1879
=> ( 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
+ }
1844
1897
}
0 commit comments