55using SixLabors . ImageSharp . IO ;
66using SixLabors . ImageSharp . Metadata ;
77using SixLabors . ImageSharp . PixelFormats ;
8+ using SixLabors . ImageSharp . Processing ;
89
9- namespace SixLabors . ImageSharp . Formats . Icon ;
10+ namespace SixLabors . ImageSharp . Formats . Ico ;
1011
11- internal sealed class IconDecoderCore : IImageDecoderInternals
12+ internal sealed class IcoDecoderCore : IImageDecoderInternals
1213{
13- private IconDir iconDir ;
14- private IconDirEntry [ ] iconDirEntries = Array . Empty < IconDirEntry > ( ) ;
14+ private IcoDir icoDir ;
15+ private IcoDirEntry [ ] icoDirEntries = Array . Empty < IcoDirEntry > ( ) ;
1516 private readonly WeakReference < Png . PngDecoderCore ? > pngDecoder = new ( default ) ;
1617 private readonly WeakReference < Bmp . BmpDecoderCore ? > bmpDecoder = new ( default ) ;
1718
18- public IconDecoderCore ( DecoderOptions options ) => this . Options = options ;
19+ public IcoDecoderCore ( DecoderOptions options ) => this . Options = options ;
1920
2021 public DecoderOptions Options { get ; }
2122
22- public Size Dimensions => new (
23- this . iconDirEntries . Select ( i => i . Width ) . Max ( ) ,
24- this . iconDirEntries . Select ( i => i . Height ) . Max ( ) ) ;
23+ public Size Dimensions { get ; private set ; }
2524
2625 public Image < TPixel > Decode < TPixel > ( BufferedReadStream stream , CancellationToken cancellationToken )
2726 where TPixel : unmanaged, IPixel < TPixel >
2827 {
29- ReadHeader ( stream , out this . iconDir , out this . iconDirEntries ) ;
28+ ReadHeader ( stream , out this . icoDir , out this . icoDirEntries ) ;
29+ this . Dimensions = new (
30+ this . icoDirEntries . Max ( i => i . Width ) ,
31+ this . icoDirEntries . Max ( i => i . Height ) ) ;
3032
3133 byte [ ] buffer = new byte [ 4096 ] ;
3234 Span < byte > flag = stackalloc byte [ Png . PngConstants . HeaderBytes . Length ] ;
3335
34- ImageFrame < TPixel > [ ] frames = new ImageFrame < TPixel > [ this . iconDirEntries . Length ] ;
35- for ( int i = 0 ; i < this . iconDirEntries . Length ; i ++ )
36+ Image < TPixel > image = new ( this . Options . Configuration , this . Dimensions . Width , this . Dimensions . Height ) ;
37+ image . Metadata . GetIcoMetadata ( ) . Set ( this . icoDir ) ;
38+
39+ for ( int i = 0 ; i < this . icoDirEntries . Length ; i ++ )
3640 {
37- _ = stream . Seek ( this . iconDirEntries [ i ] . ImageOffset , SeekOrigin . Begin ) ;
41+ _ = stream . Seek ( this . icoDirEntries [ i ] . ImageOffset , SeekOrigin . Begin ) ;
3842
3943 int size = stream . Read ( flag ) ;
4044 _ = stream . Seek ( - size , SeekOrigin . Current ) ;
4145
4246 bool isPng = flag . SequenceEqual ( Png . PngConstants . HeaderBytes ) ;
4347
44- Debug . WriteLine ( $ "#{ i } :\t { ( isPng ? "PNG" : "BMP" ) } " ) ;
48+ Debug . WriteLine ( $ "#{ i } :\t " + ( isPng ? "PNG" : "BMP" ) ) ;
4549 using Image < TPixel > img = this . ReadImage < TPixel > (
4650 stream ,
4751 isPng ,
48- ( int ) this . iconDirEntries [ i ] . BytesInRes ,
52+ ( int ) this . icoDirEntries [ i ] . BytesInRes ,
4953 buffer ,
5054 cancellationToken ) ;
5155
52- frames [ i ] = img . Frames . RootFrameUnsafe . Clone ( ) ;
53- IconFrameMetadata iconFrameMetadata = frames [ i ] . Metadata . GetIcoMetadata ( ) ;
54- iconFrameMetadata . Set ( this . iconDirEntries [ i ] ) ;
56+ // TODO: Any way to read the frame more efficiently?
57+ Size imgSize = img . Size ;
58+ img . Mutate ( x => x . Resize ( new ResizeOptions
59+ {
60+ Size = this . Dimensions ,
61+ Mode = ResizeMode . Manual ,
62+ TargetRectangle = new Rectangle ( Point . Empty , imgSize )
63+ } ) ) ;
64+ ImageFrame < TPixel > newFrame = image . Frames . AddFrame ( img . Frames . RootFrame ) ;
65+ IcoFrameMetadata iconFrameMetadata = newFrame . Metadata . GetIcoMetadata ( ) ;
66+ iconFrameMetadata . SetMetadata ( this . icoDirEntries [ i ] ) ;
5567
5668 if ( isPng )
5769 {
@@ -63,41 +75,32 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
6375 }
6476 }
6577
66- ImageMetadata metadata = new ( ) ;
67- metadata . GetIcoMetadata ( ) . Set ( this . iconDir ) ;
68-
69- Image < TPixel > image = new (
70- this . Options . Configuration ,
71- metadata ,
72- frames ,
73- false ) ;
74-
7578 return image ;
7679 }
7780
7881 public ImageInfo Identify ( BufferedReadStream stream , CancellationToken cancellationToken )
7982 {
80- ReadHeader ( stream , out this . iconDir , out this . iconDirEntries ) ;
83+ ReadHeader ( stream , out this . icoDir , out this . icoDirEntries ) ;
8184 ImageMetadata metadata = new ( ) ;
82- ImageFrameMetadata [ ] frames = new ImageFrameMetadata [ this . iconDir . Count ] ;
83- metadata . GetIcoMetadata ( ) . Set ( this . iconDir ) ;
85+ ImageFrameMetadata [ ] frames = new ImageFrameMetadata [ this . icoDir . Count ] ;
86+ metadata . GetIcoMetadata ( ) . Set ( this . icoDir ) ;
8487 for ( int i = 0 ; i < frames . Length ; i ++ )
8588 {
8689 frames [ i ] = new ( ) ;
87- IconFrameMetadata icoFrameMetadata = frames [ i ] . GetIcoMetadata ( ) ;
88- icoFrameMetadata . Set ( this . iconDirEntries [ i ] ) ;
90+ IcoFrameMetadata icoFrameMetadata = frames [ i ] . GetIcoMetadata ( ) ;
91+ icoFrameMetadata . SetMetadata ( this . icoDirEntries [ i ] ) ;
8992 }
9093
9194 return new ( new ( 32 ) , new ( 0 ) , metadata , frames ) ;
9295 }
9396
94- private static void ReadHeader ( Stream stream , out IconDir iconDir , out IconDirEntry [ ] iconDirEntries )
97+ private static void ReadHeader ( Stream stream , out IcoDir iconDir , out IcoDirEntry [ ] iconDirEntries )
9598 {
96- _ = Read ( stream , out iconDir , IconDir . Size ) ;
97- iconDirEntries = new IconDirEntry [ iconDir . Count ] ;
99+ _ = Read ( stream , out iconDir , IcoDir . Size ) ;
100+ iconDirEntries = new IcoDirEntry [ iconDir . Count ] ;
98101 for ( int i = 0 ; i < iconDirEntries . Length ; i ++ )
99102 {
100- _ = Read ( stream , out iconDirEntries [ i ] , IconDirEntry . Size ) ;
103+ _ = Read ( stream , out iconDirEntries [ i ] , IcoDirEntry . Size ) ;
101104 }
102105 }
103106
@@ -121,7 +124,7 @@ private static void StreamClone(Stream src, Stream dst, byte[] buffer, int size)
121124 while ( size > 0 )
122125 {
123126 int length = Math . Min ( buffer . Length , size ) ;
124- length = IconAssertHelper . EndOfStream ( src . Read ( buffer , 0 , length ) , length ) ;
127+ length = IcoAssertHelper . EndOfStream ( src . Read ( buffer , 0 , length ) , length ) ;
125128 size -= length ;
126129 dst . Write ( buffer , 0 , length ) ;
127130 }
@@ -143,10 +146,10 @@ private Image<TPixel> ReadImage<TPixel>(
143146 {
144147 const int headerSize = Bmp . BmpFileHeader . Size + Bmp . BmpInfoHeader . SizeV3 ;
145148 Span < byte > bytes = stackalloc byte [ Bmp . BmpInfoHeader . SizeV3 ] ;
146- _ = IconAssertHelper . EndOfStream ( stream . Read ( bytes ) , Bmp . BmpInfoHeader . SizeV3 ) ;
149+ _ = IcoAssertHelper . EndOfStream ( stream . Read ( bytes ) , Bmp . BmpInfoHeader . SizeV3 ) ;
147150
148151 Bmp . BmpInfoHeader infoHeader = Bmp . BmpInfoHeader . ParseV3 ( bytes ) ;
149- IconAssertHelper . IsV3Header ( infoHeader ) ;
152+ IcoAssertHelper . IsV3Header ( infoHeader ) ;
150153 infoHeader . Height >>= 1 ;
151154
152155 int paletteSize = infoHeader . ClrUsed ;
0 commit comments