Skip to content

Commit 57cadfc

Browse files
committed
Refactor IconImageFormatDetector.
Signed-off-by: 舰队的偶像-岛风酱! <[email protected]>
1 parent d9d1688 commit 57cadfc

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

src/ImageSharp/Formats/Icon/IconImageFormatDetector.cs

+47-12
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Six Labors Split License.
33

44
using System.Diagnostics.CodeAnalysis;
5-
using System.Runtime.InteropServices;
65

76
namespace SixLabors.ImageSharp.Formats.Icon;
87

@@ -12,22 +11,58 @@ namespace SixLabors.ImageSharp.Formats.Icon;
1211
public class IconImageFormatDetector : IImageFormatDetector
1312
{
1413
/// <inheritdoc/>
15-
public int HeaderSize { get; } = 4;
14+
public int HeaderSize { get; } = IconDir.Size + IconDirEntry.Size;
1615

1716
/// <inheritdoc/>
1817
public bool TryDetectFormat(ReadOnlySpan<byte> header, [NotNullWhen(true)] out IImageFormat? format)
1918
{
20-
switch (MemoryMarshal.Cast<byte, uint>(header)[0])
19+
format = this.IsSupportedFileFormat(header) switch
2120
{
22-
case Ico.IcoConstants.FileHeader:
23-
format = Ico.IcoFormat.Instance;
24-
return true;
25-
case Cur.CurConstants.FileHeader:
26-
format = Cur.CurFormat.Instance;
27-
return true;
28-
default:
29-
format = default;
30-
return false;
21+
true => Ico.IcoFormat.Instance,
22+
false => Cur.CurFormat.Instance,
23+
null => default
24+
};
25+
26+
return format is not null;
27+
}
28+
29+
private bool? IsSupportedFileFormat(ReadOnlySpan<byte> header)
30+
{
31+
// There are no magic bytes in the first few bytes of a tga file,
32+
// so we try to figure out if its a valid tga by checking for valid tga header bytes.
33+
if (header.Length < this.HeaderSize)
34+
{
35+
return null;
36+
}
37+
38+
IconDir dir = IconDir.Parse(header);
39+
if (dir is not { Reserved: 0 } // Should be 0.
40+
or not { Type: IconFileType.ICO or IconFileType.CUR } // Unknown Type.
41+
or { Count: 0 }) // Should not be 0.
42+
{
43+
return null;
44+
}
45+
46+
IconDirEntry entry = IconDirEntry.Parse(header[IconDir.Size..]);
47+
if (entry is not { Reserved: 0 } // Should be 0.
48+
or { BytesInRes: 0 } // Should not be 0.
49+
|| entry.ImageOffset < IconDir.Size + (dir.Count * IconDirEntry.Size))
50+
{
51+
return null;
52+
}
53+
54+
if (dir.Type is IconFileType.ICO)
55+
{
56+
if (entry is not { BitCount: 1 or 4 or 8 or 16 or 24 or 32 } or not { Planes: 0 or 1 })
57+
{
58+
return null;
59+
}
60+
61+
return true;
62+
}
63+
else
64+
{
65+
return false;
3166
}
3267
}
3368
}

0 commit comments

Comments
 (0)