Skip to content

Commit 21b1e71

Browse files
committed
Encoder Worked!
but AlphaMask have some problems
1 parent 54e87ab commit 21b1e71

File tree

6 files changed

+84
-48
lines changed

6 files changed

+84
-48
lines changed

src/ImageSharp/Formats/Cur/CurEncoderCore.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,6 @@
55

66
namespace SixLabors.ImageSharp.Formats.Cur;
77

8-
internal sealed class CurEncoderCore : IconEncoderCore
8+
internal sealed class CurEncoderCore() : IconEncoderCore(IconFileType.CUR)
99
{
10-
protected override void GetHeader(in Image image)
11-
{
12-
this.FileHeader = new(IconFileType.ICO, (ushort)image.Frames.Count);
13-
this.Entries = image.Frames.Select(i =>
14-
{
15-
CurFrameMetadata metadata = i.Metadata.GetCurMetadata();
16-
return metadata.ToIconDirEntry();
17-
}).ToArray();
18-
}
1910
}

src/ImageSharp/Formats/Cur/MetadataExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
// Licensed under the Six Labors Split License.
33

44
using System.Diagnostics.CodeAnalysis;
5+
using SixLabors.ImageSharp.Formats.Cur;
56
using SixLabors.ImageSharp.Metadata;
67

7-
namespace SixLabors.ImageSharp.Formats.Cur;
8+
namespace SixLabors.ImageSharp;
89

910
/// <summary>
1011
/// Extension methods for the <see cref="ImageMetadata"/> type.
1112
/// </summary>
12-
public static class MetadataExtensions
13+
public static partial class MetadataExtensions
1314
{
1415
/// <summary>
1516
/// Gets the Icon format specific metadata for the image.

src/ImageSharp/Formats/Ico/IcoEncoderCore.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,6 @@
55

66
namespace SixLabors.ImageSharp.Formats.Ico;
77

8-
internal sealed class IcoEncoderCore : IconEncoderCore
8+
internal sealed class IcoEncoderCore() : IconEncoderCore(IconFileType.ICO)
99
{
10-
protected override void GetHeader(in Image image)
11-
{
12-
this.FileHeader = new(IconFileType.ICO, (ushort)image.Frames.Count);
13-
this.Entries = image.Frames.Select(i =>
14-
{
15-
IcoFrameMetadata metadata = i.Metadata.GetIcoMetadata();
16-
return metadata.ToIconDirEntry();
17-
}).ToArray();
18-
}
1910
}

src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ internal void FromIconDirEntry(in IconDirEntry entry)
8888
BitCount = this.Compression switch
8989
{
9090
IconFrameCompression.Bmp => (ushort)this.BitsPerPixel,
91-
_ => 0,
91+
IconFrameCompression.Png => 32,
92+
_ => throw new NotSupportedException($"Value: {this.Compression}"),
9293
},
9394
};
9495
}

src/ImageSharp/Formats/Ico/MetadataExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
// Licensed under the Six Labors Split License.
33

44
using System.Diagnostics.CodeAnalysis;
5+
using SixLabors.ImageSharp.Formats.Ico;
56
using SixLabors.ImageSharp.Metadata;
67

7-
namespace SixLabors.ImageSharp.Formats.Ico;
8+
namespace SixLabors.ImageSharp;
89

910
/// <summary>
1011
/// Extension methods for the <see cref="ImageMetadata"/> type.
1112
/// </summary>
12-
public static class MetadataExtensions
13+
public static partial class MetadataExtensions
1314
{
1415
/// <summary>
1516
/// Gets the Ico format specific metadata for the image.

src/ImageSharp/Formats/Icon/IconEncoderCore.cs

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22
// Licensed under the Six Labors Split License.
33

44
using System.Diagnostics.CodeAnalysis;
5-
using SixLabors.ImageSharp.Formats.Bmp;
5+
using SixLabors.ImageSharp.Formats.Cur;
6+
using SixLabors.ImageSharp.Formats.Ico;
67
using SixLabors.ImageSharp.PixelFormats;
78

89
namespace SixLabors.ImageSharp.Formats.Icon;
910

10-
internal abstract class IconEncoderCore : IImageEncoderInternals
11+
internal abstract class IconEncoderCore(IconFileType iconFileType)
12+
: IImageEncoderInternals
1113
{
12-
protected IconDir FileHeader { get; set; }
14+
private IconDir fileHeader;
1315

14-
protected IconDirEntry[]? Entries { get; set; }
16+
private IconFrameMetadata[]? entries;
1517

1618
public void Encode<TPixel>(
1719
Image<TPixel> image,
@@ -26,44 +28,93 @@ public void Encode<TPixel>(
2628

2729
// Stream may not at 0.
2830
long basePosition = stream.Position;
29-
this.GetHeader(image);
31+
this.InitHeader(image);
3032

31-
int dataOffset = IconDir.Size + (IconDirEntry.Size * this.Entries.Length);
33+
int dataOffset = IconDir.Size + (IconDirEntry.Size * this.entries.Length);
3234
_ = stream.Seek(dataOffset, SeekOrigin.Current);
3335

3436
for (int i = 0; i < image.Frames.Count; i++)
3537
{
3638
ImageFrame<TPixel> frame = image.Frames[i];
37-
this.Entries[i].ImageOffset = (uint)stream.Position;
38-
Image<TPixel> img = new(Configuration.Default, frame.PixelBuffer, new());
39+
int width = this.entries[i].Entry.Width;
40+
if (width is 0)
41+
{
42+
width = frame.Width;
43+
}
44+
45+
int height = this.entries[i].Entry.Height;
46+
if (height is 0)
47+
{
48+
height = frame.Height;
49+
}
50+
51+
this.entries[i].Entry.ImageOffset = (uint)stream.Position;
3952

40-
// Note: this encoder are not supported PNG Data.
41-
BmpEncoder encoder = new()
53+
Image<TPixel> img = new(width, height);
54+
for (int y = 0; y < height; y++)
4255
{
43-
ProcessedAlphaMask = true,
44-
UseDoubleHeight = true,
45-
SkipFileHeader = true,
46-
SupportTransparency = false,
47-
BitsPerPixel = this.Entries[i].BitCount is 0
48-
? BmpBitsPerPixel.Pixel8
49-
: (BmpBitsPerPixel?)this.Entries[i].BitCount
56+
frame.PixelBuffer.DangerousGetRowSpan(y)[..width].CopyTo(img.GetRootFramePixelBuffer().DangerousGetRowSpan(y));
57+
}
58+
59+
QuantizingImageEncoder encoder = this.entries[i].Compression switch
60+
{
61+
IconFrameCompression.Bmp => new Bmp.BmpEncoder()
62+
{
63+
ProcessedAlphaMask = true,
64+
UseDoubleHeight = true,
65+
SkipFileHeader = true,
66+
SupportTransparency = false,
67+
BitsPerPixel = iconFileType is IconFileType.ICO
68+
? (Bmp.BmpBitsPerPixel?)this.entries[i].Entry.BitCount
69+
: Bmp.BmpBitsPerPixel.Pixel24 // TODO: Here you need to switch to selecting the corresponding value according to the size of the image
70+
},
71+
IconFrameCompression.Png => new Png.PngEncoder(),
72+
_ => throw new NotSupportedException(),
5073
};
5174

5275
encoder.Encode(img, stream);
53-
this.Entries[i].BytesInRes = this.Entries[i].ImageOffset - (uint)stream.Position;
76+
this.entries[i].Entry.BytesInRes = (uint)stream.Position - this.entries[i].Entry.ImageOffset;
5477
}
5578

5679
long endPosition = stream.Position;
5780
_ = stream.Seek(basePosition, SeekOrigin.Begin);
58-
this.FileHeader.WriteTo(stream);
59-
foreach (IconDirEntry entry in this.Entries)
81+
this.fileHeader.WriteTo(stream);
82+
foreach (IconFrameMetadata frame in this.entries)
6083
{
61-
entry.WriteTo(stream);
84+
frame.Entry.WriteTo(stream);
6285
}
6386

6487
_ = stream.Seek(endPosition, SeekOrigin.Begin);
6588
}
6689

67-
[MemberNotNull(nameof(Entries))]
68-
protected abstract void GetHeader(in Image image);
90+
[MemberNotNull(nameof(entries))]
91+
private void InitHeader(in Image image)
92+
{
93+
this.fileHeader = new(iconFileType, (ushort)image.Frames.Count);
94+
this.entries = iconFileType switch
95+
{
96+
IconFileType.ICO =>
97+
image.Frames.Select(i =>
98+
{
99+
IcoFrameMetadata metadata = i.Metadata.GetIcoMetadata();
100+
return new IconFrameMetadata(metadata.Compression, metadata.ToIconDirEntry());
101+
}).ToArray(),
102+
IconFileType.CUR =>
103+
image.Frames.Select(i =>
104+
{
105+
CurFrameMetadata metadata = i.Metadata.GetCurMetadata();
106+
return new IconFrameMetadata(metadata.Compression, metadata.ToIconDirEntry());
107+
}).ToArray(),
108+
_ => throw new NotSupportedException(),
109+
};
110+
}
111+
112+
internal sealed class IconFrameMetadata(IconFrameCompression compression, IconDirEntry iconDirEntry)
113+
{
114+
private IconDirEntry iconDirEntry = iconDirEntry;
115+
116+
public IconFrameCompression Compression { get; set; } = compression;
117+
118+
public ref IconDirEntry Entry => ref this.iconDirEntry;
119+
}
69120
}

0 commit comments

Comments
 (0)