Browse Source

Encoder Worked!

but AlphaMask have some problems
pull/2579/head
舰队的偶像-岛风酱! 2 years ago
parent
commit
21b1e71062
No known key found for this signature in database GPG Key ID: 71F5B3A2B181950C
  1. 11
      src/ImageSharp/Formats/Cur/CurEncoderCore.cs
  2. 5
      src/ImageSharp/Formats/Cur/MetadataExtensions.cs
  3. 11
      src/ImageSharp/Formats/Ico/IcoEncoderCore.cs
  4. 3
      src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs
  5. 5
      src/ImageSharp/Formats/Ico/MetadataExtensions.cs
  6. 97
      src/ImageSharp/Formats/Icon/IconEncoderCore.cs

11
src/ImageSharp/Formats/Cur/CurEncoderCore.cs

@ -5,15 +5,6 @@ using SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Cur;
internal sealed class CurEncoderCore : IconEncoderCore
internal sealed class CurEncoderCore() : IconEncoderCore(IconFileType.CUR)
{
protected override void GetHeader(in Image image)
{
this.FileHeader = new(IconFileType.ICO, (ushort)image.Frames.Count);
this.Entries = image.Frames.Select(i =>
{
CurFrameMetadata metadata = i.Metadata.GetCurMetadata();
return metadata.ToIconDirEntry();
}).ToArray();
}
}

5
src/ImageSharp/Formats/Cur/MetadataExtensions.cs

@ -2,14 +2,15 @@
// Licensed under the Six Labors Split License.
using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats.Cur;
using SixLabors.ImageSharp.Metadata;
namespace SixLabors.ImageSharp.Formats.Cur;
namespace SixLabors.ImageSharp;
/// <summary>
/// Extension methods for the <see cref="ImageMetadata"/> type.
/// </summary>
public static class MetadataExtensions
public static partial class MetadataExtensions
{
/// <summary>
/// Gets the Icon format specific metadata for the image.

11
src/ImageSharp/Formats/Ico/IcoEncoderCore.cs

@ -5,15 +5,6 @@ using SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;
internal sealed class IcoEncoderCore : IconEncoderCore
internal sealed class IcoEncoderCore() : IconEncoderCore(IconFileType.ICO)
{
protected override void GetHeader(in Image image)
{
this.FileHeader = new(IconFileType.ICO, (ushort)image.Frames.Count);
this.Entries = image.Frames.Select(i =>
{
IcoFrameMetadata metadata = i.Metadata.GetIcoMetadata();
return metadata.ToIconDirEntry();
}).ToArray();
}
}

3
src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs

@ -88,7 +88,8 @@ public class IcoFrameMetadata : IDeepCloneable<IcoFrameMetadata>, IDeepCloneable
BitCount = this.Compression switch
{
IconFrameCompression.Bmp => (ushort)this.BitsPerPixel,
_ => 0,
IconFrameCompression.Png => 32,
_ => throw new NotSupportedException($"Value: {this.Compression}"),
},
};
}

5
src/ImageSharp/Formats/Ico/MetadataExtensions.cs

@ -2,14 +2,15 @@
// Licensed under the Six Labors Split License.
using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats.Ico;
using SixLabors.ImageSharp.Metadata;
namespace SixLabors.ImageSharp.Formats.Ico;
namespace SixLabors.ImageSharp;
/// <summary>
/// Extension methods for the <see cref="ImageMetadata"/> type.
/// </summary>
public static class MetadataExtensions
public static partial class MetadataExtensions
{
/// <summary>
/// Gets the Ico format specific metadata for the image.

97
src/ImageSharp/Formats/Icon/IconEncoderCore.cs

@ -2,16 +2,18 @@
// Licensed under the Six Labors Split License.
using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Cur;
using SixLabors.ImageSharp.Formats.Ico;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Icon;
internal abstract class IconEncoderCore : IImageEncoderInternals
internal abstract class IconEncoderCore(IconFileType iconFileType)
: IImageEncoderInternals
{
protected IconDir FileHeader { get; set; }
private IconDir fileHeader;
protected IconDirEntry[]? Entries { get; set; }
private IconFrameMetadata[]? entries;
public void Encode<TPixel>(
Image<TPixel> image,
@ -26,44 +28,93 @@ internal abstract class IconEncoderCore : IImageEncoderInternals
// Stream may not at 0.
long basePosition = stream.Position;
this.GetHeader(image);
this.InitHeader(image);
int dataOffset = IconDir.Size + (IconDirEntry.Size * this.Entries.Length);
int dataOffset = IconDir.Size + (IconDirEntry.Size * this.entries.Length);
_ = stream.Seek(dataOffset, SeekOrigin.Current);
for (int i = 0; i < image.Frames.Count; i++)
{
ImageFrame<TPixel> frame = image.Frames[i];
this.Entries[i].ImageOffset = (uint)stream.Position;
Image<TPixel> img = new(Configuration.Default, frame.PixelBuffer, new());
int width = this.entries[i].Entry.Width;
if (width is 0)
{
width = frame.Width;
}
int height = this.entries[i].Entry.Height;
if (height is 0)
{
height = frame.Height;
}
this.entries[i].Entry.ImageOffset = (uint)stream.Position;
// Note: this encoder are not supported PNG Data.
BmpEncoder encoder = new()
Image<TPixel> img = new(width, height);
for (int y = 0; y < height; y++)
{
ProcessedAlphaMask = true,
UseDoubleHeight = true,
SkipFileHeader = true,
SupportTransparency = false,
BitsPerPixel = this.Entries[i].BitCount is 0
? BmpBitsPerPixel.Pixel8
: (BmpBitsPerPixel?)this.Entries[i].BitCount
frame.PixelBuffer.DangerousGetRowSpan(y)[..width].CopyTo(img.GetRootFramePixelBuffer().DangerousGetRowSpan(y));
}
QuantizingImageEncoder encoder = this.entries[i].Compression switch
{
IconFrameCompression.Bmp => new Bmp.BmpEncoder()
{
ProcessedAlphaMask = true,
UseDoubleHeight = true,
SkipFileHeader = true,
SupportTransparency = false,
BitsPerPixel = iconFileType is IconFileType.ICO
? (Bmp.BmpBitsPerPixel?)this.entries[i].Entry.BitCount
: Bmp.BmpBitsPerPixel.Pixel24 // TODO: Here you need to switch to selecting the corresponding value according to the size of the image
},
IconFrameCompression.Png => new Png.PngEncoder(),
_ => throw new NotSupportedException(),
};
encoder.Encode(img, stream);
this.Entries[i].BytesInRes = this.Entries[i].ImageOffset - (uint)stream.Position;
this.entries[i].Entry.BytesInRes = (uint)stream.Position - this.entries[i].Entry.ImageOffset;
}
long endPosition = stream.Position;
_ = stream.Seek(basePosition, SeekOrigin.Begin);
this.FileHeader.WriteTo(stream);
foreach (IconDirEntry entry in this.Entries)
this.fileHeader.WriteTo(stream);
foreach (IconFrameMetadata frame in this.entries)
{
entry.WriteTo(stream);
frame.Entry.WriteTo(stream);
}
_ = stream.Seek(endPosition, SeekOrigin.Begin);
}
[MemberNotNull(nameof(Entries))]
protected abstract void GetHeader(in Image image);
[MemberNotNull(nameof(entries))]
private void InitHeader(in Image image)
{
this.fileHeader = new(iconFileType, (ushort)image.Frames.Count);
this.entries = iconFileType switch
{
IconFileType.ICO =>
image.Frames.Select(i =>
{
IcoFrameMetadata metadata = i.Metadata.GetIcoMetadata();
return new IconFrameMetadata(metadata.Compression, metadata.ToIconDirEntry());
}).ToArray(),
IconFileType.CUR =>
image.Frames.Select(i =>
{
CurFrameMetadata metadata = i.Metadata.GetCurMetadata();
return new IconFrameMetadata(metadata.Compression, metadata.ToIconDirEntry());
}).ToArray(),
_ => throw new NotSupportedException(),
};
}
internal sealed class IconFrameMetadata(IconFrameCompression compression, IconDirEntry iconDirEntry)
{
private IconDirEntry iconDirEntry = iconDirEntry;
public IconFrameCompression Compression { get; set; } = compression;
public ref IconDirEntry Entry => ref this.iconDirEntry;
}
}

Loading…
Cancel
Save