Skip to content

Commit 6beeba1

Browse files
Cleanup and fix issues
1 parent cb45a39 commit 6beeba1

18 files changed

+263
-196
lines changed

src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics.CodeAnalysis;
77
using System.Numerics;
88
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
910
using SixLabors.ImageSharp.Common.Helpers;
1011
using SixLabors.ImageSharp.IO;
1112
using SixLabors.ImageSharp.Memory;
@@ -1599,6 +1600,14 @@ private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out b
15991600
}
16001601
}
16011602

1603+
if (palette.Length > 0)
1604+
{
1605+
Color[] colorTable = new Color[palette.Length / Unsafe.SizeOf<Bgr24>()];
1606+
ReadOnlySpan<Bgr24> rgbTable = MemoryMarshal.Cast<byte, Bgr24>(palette);
1607+
Color.FromPixel(rgbTable, colorTable);
1608+
this.bmpMetadata.ColorTable = colorTable;
1609+
}
1610+
16021611
int skipAmount = 0;
16031612
if (this.fileHeader.HasValue)
16041613
{

src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public BmpEncoderCore(BmpEncoder encoder, MemoryAllocator memoryAllocator)
109109
{
110110
this.memoryAllocator = memoryAllocator;
111111
this.bitsPerPixel = encoder.BitsPerPixel;
112+
113+
// TODO: Use a palette quantizer if supplied.
112114
this.quantizer = encoder.Quantizer ?? KnownQuantizers.Octree;
113115
this.pixelSamplingStrategy = encoder.PixelSamplingStrategy;
114116
this.infoHeaderType = encoder.SupportTransparency ? BmpInfoHeaderType.WinVersion4 : BmpInfoHeaderType.WinVersion3;

src/ImageSharp/Formats/Bmp/BmpMetadata.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

44
namespace SixLabors.ImageSharp.Formats.Bmp;
@@ -23,6 +23,11 @@ private BmpMetadata(BmpMetadata other)
2323
{
2424
this.BitsPerPixel = other.BitsPerPixel;
2525
this.InfoHeaderType = other.InfoHeaderType;
26+
27+
if (other.ColorTable?.Length > 0)
28+
{
29+
this.ColorTable = other.ColorTable.Value.ToArray();
30+
}
2631
}
2732

2833
/// <summary>
@@ -35,8 +40,11 @@ private BmpMetadata(BmpMetadata other)
3540
/// </summary>
3641
public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
3742

43+
/// <summary>
44+
/// Gets or sets the color table, if any.
45+
/// </summary>
46+
public ReadOnlyMemory<Color>? ColorTable { get; set; }
47+
3848
/// <inheritdoc/>
3949
public IDeepCloneable DeepClone() => new BmpMetadata(this);
40-
41-
// TODO: Colors used once we support encoding palette bmps.
4250
}

src/ImageSharp/Formats/Cur/CurConstants.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,31 @@ namespace SixLabors.ImageSharp.Formats.Cur;
99
internal static class CurConstants
1010
{
1111
/// <summary>
12-
/// The list of mimetypes that equate to a ico.
12+
/// The list of mime types that equate to a cur.
1313
/// </summary>
1414
/// <remarks>
1515
/// See <see href="https://en.wikipedia.org/wiki/ICO_(file_format)#MIME_type"/>
1616
/// </remarks>
17-
public static readonly IEnumerable<string> MimeTypes = new[]
18-
{
19-
"application/octet-stream",
20-
};
17+
public static readonly IEnumerable<string> MimeTypes =
18+
[
19+
20+
// IANA-registered
21+
"image/vnd.microsoft.icon",
22+
23+
// ICO & CUR types used by Windows
24+
"image/x-icon",
25+
26+
// Erroneous types but have been used
27+
"image/ico",
28+
"image/icon",
29+
"text/ico",
30+
"application/ico",
31+
];
2132

2233
/// <summary>
23-
/// The list of file extensions that equate to a ico.
34+
/// The list of file extensions that equate to a cur.
2435
/// </summary>
25-
public static readonly IEnumerable<string> FileExtensions = new[] { "cur" };
36+
public static readonly IEnumerable<string> FileExtensions = ["cur"];
2637

2738
public const uint FileHeader = 0x00_02_00_00;
2839
}
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using SixLabors.ImageSharp.Formats.Bmp;
45
using SixLabors.ImageSharp.Formats.Icon;
56
using SixLabors.ImageSharp.Metadata;
67

78
namespace SixLabors.ImageSharp.Formats.Cur;
89

9-
internal sealed class CurDecoderCore(DecoderOptions options) : IconDecoderCore(options)
10+
internal sealed class CurDecoderCore : IconDecoderCore
1011
{
11-
protected override void SetFrameMetadata(ImageFrameMetadata metadata, in IconDirEntry entry, IconFrameCompression compression, Bmp.BmpBitsPerPixel bitsPerPixel)
12+
public CurDecoderCore(DecoderOptions options)
13+
: base(options)
14+
{
15+
}
16+
17+
protected override void SetFrameMetadata(ImageFrameMetadata metadata, in IconDirEntry entry, IconFrameCompression compression, BmpBitsPerPixel bitsPerPixel)
1218
{
1319
CurFrameMetadata curFrameMetadata = metadata.GetCurMetadata();
1420
curFrameMetadata.FromIconDirEntry(entry);
1521
curFrameMetadata.Compression = compression;
16-
curFrameMetadata.BitsPerPixel = bitsPerPixel;
22+
curFrameMetadata.BmpBitsPerPixel = bitsPerPixel;
1723
}
1824
}

src/ImageSharp/Formats/Cur/CurEncoderCore.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
namespace SixLabors.ImageSharp.Formats.Cur;
77

8-
internal sealed class CurEncoderCore() : IconEncoderCore(IconFileType.CUR)
8+
internal sealed class CurEncoderCore : IconEncoderCore
99
{
10+
public CurEncoderCore()
11+
: base(IconFileType.CUR)
12+
{
13+
}
1014
}
Lines changed: 34 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using SixLabors.ImageSharp.Formats.Bmp;
45
using SixLabors.ImageSharp.Formats.Icon;
56

67
namespace SixLabors.ImageSharp.Formats.Cur;
@@ -17,92 +18,76 @@ public CurFrameMetadata()
1718
{
1819
}
1920

20-
/// <summary>
21-
/// Initializes a new instance of the <see cref="CurFrameMetadata"/> class.
22-
/// </summary>
23-
/// <param name="width">width</param>
24-
/// <param name="height">height</param>
25-
/// <param name="colorCount">colorCount</param>
26-
/// <param name="hotspotX">hotspotX</param>
27-
/// <param name="hotspotY">hotspotY</param>
28-
public CurFrameMetadata(byte width, byte height, byte colorCount, ushort hotspotX, ushort hotspotY)
29-
{
30-
this.EncodingWidth = width;
31-
this.EncodingHeight = height;
32-
this.ColorCount = colorCount;
33-
this.HotspotX = hotspotX;
34-
this.HotspotY = hotspotY;
35-
}
36-
37-
/// <inheritdoc cref="CurFrameMetadata()"/>
38-
public CurFrameMetadata(CurFrameMetadata metadata)
21+
private CurFrameMetadata(CurFrameMetadata metadata)
3922
{
40-
this.EncodingWidth = metadata.EncodingWidth;
41-
this.EncodingHeight = metadata.EncodingHeight;
42-
this.ColorCount = metadata.ColorCount;
23+
this.Compression = metadata.Compression;
4324
this.HotspotX = metadata.HotspotX;
4425
this.HotspotY = metadata.HotspotY;
45-
this.Compression = metadata.Compression;
26+
this.EncodingWidth = metadata.EncodingWidth;
27+
this.EncodingHeight = metadata.EncodingHeight;
28+
this.BmpBitsPerPixel = metadata.BmpBitsPerPixel;
4629
}
4730

4831
/// <summary>
49-
/// Gets or sets icoFrameCompression.
32+
/// Gets or sets the frame compressions format.
5033
/// </summary>
5134
public IconFrameCompression Compression { get; set; }
5235

5336
/// <summary>
54-
/// Gets or sets ColorCount field. <br />
55-
/// Specifies number of colors in the color palette. Should be 0 if the image does not use a color palette.
37+
/// Gets or sets the horizontal coordinates of the hotspot in number of pixels from the left.
5638
/// </summary>
57-
// TODO: BmpMetadata does not supported palette yet.
58-
public byte ColorCount { get; set; }
39+
public ushort HotspotX { get; set; }
5940

6041
/// <summary>
61-
/// Gets or sets Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
42+
/// Gets or sets the vertical coordinates of the hotspot in number of pixels from the top.
6243
/// </summary>
63-
public ushort HotspotX { get; set; }
44+
public ushort HotspotY { get; set; }
6445

6546
/// <summary>
66-
/// Gets or sets Specifies the vertical coordinates of the hotspot in number of pixels from the top.
47+
/// Gets or sets the encoding width. <br />
48+
/// Can be any number between 0 and 255. Value 0 means a frame height of 256 pixels.
6749
/// </summary>
68-
public ushort HotspotY { get; set; }
50+
public byte EncodingWidth { get; set; }
6951

7052
/// <summary>
71-
/// Gets or sets Height field. <br />
72-
/// Specifies image height in pixels. Can be any number between 0 and 255. Value 0 means image height is 256 pixels.
53+
/// Gets or sets the encoding height. <br />
54+
/// Can be any number between 0 and 255. Value 0 means a frame height of 256 pixels.
7355
/// </summary>
7456
public byte EncodingHeight { get; set; }
7557

7658
/// <summary>
77-
/// Gets or sets Width field. <br />
78-
/// Specifies image width in pixels. Can be any number between 0 and 255. Value 0 means image width is 256 pixels.
59+
/// Gets or sets the number of bits per pixel.<br/>
60+
/// Used when <see cref="Compression"/> is <see cref="IconFrameCompression.Bmp"/>
7961
/// </summary>
80-
public byte EncodingWidth { get; set; }
81-
82-
/// <inheritdoc cref="Bmp.BmpMetadata.BitsPerPixel" />
83-
public Bmp.BmpBitsPerPixel BitsPerPixel { get; set; } = Bmp.BmpBitsPerPixel.Pixel24;
62+
public BmpBitsPerPixel BmpBitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel32;
8463

8564
/// <inheritdoc/>
8665
public CurFrameMetadata DeepClone() => new(this);
8766

8867
/// <inheritdoc/>
8968
IDeepCloneable IDeepCloneable.DeepClone() => this.DeepClone();
9069

91-
internal void FromIconDirEntry(in IconDirEntry entry)
70+
internal void FromIconDirEntry(IconDirEntry entry)
9271
{
9372
this.EncodingWidth = entry.Width;
9473
this.EncodingHeight = entry.Height;
95-
this.ColorCount = entry.ColorCount;
9674
this.HotspotX = entry.Planes;
9775
this.HotspotY = entry.BitCount;
9876
}
9977

100-
internal IconDirEntry ToIconDirEntry() => new()
78+
internal IconDirEntry ToIconDirEntry()
10179
{
102-
Width = this.EncodingWidth,
103-
Height = this.EncodingHeight,
104-
ColorCount = this.ColorCount,
105-
Planes = this.HotspotX,
106-
BitCount = this.HotspotY,
107-
};
80+
byte colorCount = this.Compression == IconFrameCompression.Png || this.BmpBitsPerPixel > BmpBitsPerPixel.Pixel8
81+
? (byte)0
82+
: (byte)ColorNumerics.GetColorCountForBitDepth((int)this.BmpBitsPerPixel);
83+
84+
return new()
85+
{
86+
Width = this.EncodingWidth,
87+
Height = this.EncodingHeight,
88+
Planes = this.HotspotX,
89+
BitCount = this.HotspotY,
90+
ColorCount = colorCount
91+
};
92+
}
10893
}

src/ImageSharp/Formats/Ico/IcoConstants.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ namespace SixLabors.ImageSharp.Formats.Ico;
99
internal static class IcoConstants
1010
{
1111
/// <summary>
12-
/// The list of mimetypes that equate to a ico.
12+
/// The list of mime types that equate to a ico.
1313
/// </summary>
1414
/// <remarks>
1515
/// See <see href="https://en.wikipedia.org/wiki/ICO_(file_format)#MIME_type"/>
1616
/// </remarks>
17-
public static readonly IEnumerable<string> MimeTypes = new[]
18-
{
17+
public static readonly IEnumerable<string> MimeTypes =
18+
[
19+
1920
// IANA-registered
2021
"image/vnd.microsoft.icon",
2122

@@ -27,12 +28,12 @@ internal static class IcoConstants
2728
"image/icon",
2829
"text/ico",
2930
"application/ico",
30-
};
31+
];
3132

3233
/// <summary>
3334
/// The list of file extensions that equate to a ico.
3435
/// </summary>
35-
public static readonly IEnumerable<string> FileExtensions = new[] { "ico" };
36+
public static readonly IEnumerable<string> FileExtensions = ["ico"];
3637

3738
public const uint FileHeader = 0x00_01_00_00;
3839
}
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4+
using SixLabors.ImageSharp.Formats.Bmp;
45
using SixLabors.ImageSharp.Formats.Icon;
56
using SixLabors.ImageSharp.Metadata;
67

78
namespace SixLabors.ImageSharp.Formats.Ico;
89

9-
internal sealed class IcoDecoderCore(DecoderOptions options) : IconDecoderCore(options)
10+
internal sealed class IcoDecoderCore : IconDecoderCore
1011
{
11-
protected override void SetFrameMetadata(ImageFrameMetadata metadata, in IconDirEntry entry, IconFrameCompression compression, Bmp.BmpBitsPerPixel bitsPerPixel)
12+
public IcoDecoderCore(DecoderOptions options)
13+
: base(options)
14+
{
15+
}
16+
17+
protected override void SetFrameMetadata(ImageFrameMetadata metadata, in IconDirEntry entry, IconFrameCompression compression, BmpBitsPerPixel bitsPerPixel)
1218
{
1319
IcoFrameMetadata icoFrameMetadata = metadata.GetIcoMetadata();
1420
icoFrameMetadata.FromIconDirEntry(entry);
1521
icoFrameMetadata.Compression = compression;
16-
icoFrameMetadata.BitsPerPixel = bitsPerPixel;
22+
icoFrameMetadata.BmpBitsPerPixel = bitsPerPixel;
1723
}
1824
}

src/ImageSharp/Formats/Ico/IcoEncoder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

44
namespace SixLabors.ImageSharp.Formats.Ico;
55

66
/// <summary>
77
/// Image encoder for writing an image to a stream as a Windows Icon.
88
/// </summary>
9-
public sealed class IcoEncoder : QuantizingImageEncoder
9+
public sealed class IcoEncoder : ImageEncoder
1010
{
1111
/// <inheritdoc/>
1212
protected override void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)