Skip to content

Commit

Permalink
revert force frames size
Browse files Browse the repository at this point in the history
  • Loading branch information
Poker-sang authored and frg2089 committed Nov 9, 2023
1 parent 36cf43a commit 6f211c1
Show file tree
Hide file tree
Showing 14 changed files with 133 additions and 140 deletions.
6 changes: 3 additions & 3 deletions src/ImageSharp/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Icon;
using SixLabors.ImageSharp.Formats.Ico;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.Formats.Png;
Expand Down Expand Up @@ -215,7 +215,7 @@ public void Configure(IImageFormatConfigurationModule configuration)
/// <see cref="TiffConfigurationModule"/>.
/// <see cref="WebpConfigurationModule"/>.
/// <see cref="QoiConfigurationModule"/>.
/// <see cref="IconConfigurationModule"/>.
/// <see cref="IcoConfigurationModule"/>.
/// </summary>
/// <returns>The default configuration of <see cref="Configuration"/>.</returns>
internal static Configuration CreateDefaultInstance() => new(
Expand All @@ -228,5 +228,5 @@ public void Configure(IImageFormatConfigurationModule configuration)
new TiffConfigurationModule(),
new WebpConfigurationModule(),
new QoiConfigurationModule(),
new IconConfigurationModule());
new IcoConfigurationModule());
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

using SixLabors.ImageSharp.Formats.Bmp;

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

internal class IconAssertHelper
internal class IcoAssertHelper
{
internal static int EndOfStream(int v, int length)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

/// <summary>
/// Registers the image encoders, decoders and mime type detectors for the Ico format.
/// </summary>
public sealed class IconConfigurationModule : IImageFormatConfigurationModule
public sealed class IcoConfigurationModule : IImageFormatConfigurationModule
{
/// <inheritdoc/>
public void Configure(Configuration configuration)
{
// TODO: IcoEncoder
// configuration.ImageFormatsManager.SetEncoder(IcoFormat.Instance, new IcoEncoder());
configuration.ImageFormatsManager.SetDecoder(IconFormat.Instance, IconDecoder.Instance);
configuration.ImageFormatsManager.SetDecoder(IcoFormat.Instance, IcoDecoder.Instance);

// ICO(CUR) File haven't Magic Code.
// configuration.ImageFormatsManager.AddImageFormatDetector(new IcoImageFormatDetector());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

/// <summary>
/// Defines constants relating to ICOs
/// </summary>
internal static class IconConstants
internal static class IcoConstants
{
/// <summary>
/// The list of mimetypes that equate to a ico.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@

using SixLabors.ImageSharp.PixelFormats;

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

/// <summary>
/// Decoder for generating an image out of a ico/cur encoded stream.
/// </summary>
public sealed class IconDecoder : ImageDecoder
public sealed class IcoDecoder : ImageDecoder
{
private IconDecoder()
private IcoDecoder()
{
}

/// <summary>
/// Gets the shared instance.
/// </summary>
public static IconDecoder Instance { get; } = new();
public static IcoDecoder Instance { get; } = new();

/// <inheritdoc/>
protected override Image<TPixel> Decode<TPixel>(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));

Image<TPixel> image = new IconDecoderCore(options).Decode<TPixel>(options.Configuration, stream, cancellationToken);
Image<TPixel> image = new IcoDecoderCore(options).Decode<TPixel>(options.Configuration, stream, cancellationToken);

ScaleToTargetSize(options, image);

Expand All @@ -42,6 +42,6 @@ protected override ImageInfo Identify(DecoderOptions options, Stream stream, Can
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));

return new IconDecoderCore(options).Identify(options.Configuration, stream, cancellationToken);
return new IcoDecoderCore(options).Identify(options.Configuration, stream, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,65 @@
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

internal sealed class IconDecoderCore : IImageDecoderInternals
internal sealed class IcoDecoderCore : IImageDecoderInternals
{
private IconDir iconDir;
private IconDirEntry[] iconDirEntries = Array.Empty<IconDirEntry>();
private IcoDir icoDir;
private IcoDirEntry[] icoDirEntries = Array.Empty<IcoDirEntry>();
private readonly WeakReference<Png.PngDecoderCore?> pngDecoder = new(default);
private readonly WeakReference<Bmp.BmpDecoderCore?> bmpDecoder = new(default);

public IconDecoderCore(DecoderOptions options) => this.Options = options;
public IcoDecoderCore(DecoderOptions options) => this.Options = options;

public DecoderOptions Options { get; }

public Size Dimensions => new(
this.iconDirEntries.Select(i => i.Width).Max(),
this.iconDirEntries.Select(i => i.Height).Max());
public Size Dimensions { get; private set; }

public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
ReadHeader(stream, out this.iconDir, out this.iconDirEntries);
ReadHeader(stream, out this.icoDir, out this.icoDirEntries);
this.Dimensions = new(
this.icoDirEntries.Max(i => i.Width),
this.icoDirEntries.Max(i => i.Height));

byte[] buffer = new byte[4096];
Span<byte> flag = stackalloc byte[Png.PngConstants.HeaderBytes.Length];

ImageFrame<TPixel>[] frames = new ImageFrame<TPixel>[this.iconDirEntries.Length];
for (int i = 0; i < this.iconDirEntries.Length; i++)
Image<TPixel> image = new(this.Options.Configuration, this.Dimensions.Width, this.Dimensions.Height);
image.Metadata.GetIcoMetadata().Set(this.icoDir);

for (int i = 0; i < this.icoDirEntries.Length; i++)
{
_ = stream.Seek(this.iconDirEntries[i].ImageOffset, SeekOrigin.Begin);
_ = stream.Seek(this.icoDirEntries[i].ImageOffset, SeekOrigin.Begin);

int size = stream.Read(flag);
_ = stream.Seek(-size, SeekOrigin.Current);

bool isPng = flag.SequenceEqual(Png.PngConstants.HeaderBytes);

Debug.WriteLine($"#{i}:\t{(isPng ? "PNG" : "BMP")}");
Debug.WriteLine($"#{i}:\t" + (isPng ? "PNG" : "BMP"));
using Image<TPixel> img = this.ReadImage<TPixel>(
stream,
isPng,
(int)this.iconDirEntries[i].BytesInRes,
(int)this.icoDirEntries[i].BytesInRes,
buffer,
cancellationToken);

frames[i] = img.Frames.RootFrameUnsafe.Clone();
IconFrameMetadata iconFrameMetadata = frames[i].Metadata.GetIcoMetadata();
iconFrameMetadata.Set(this.iconDirEntries[i]);
// TODO: Any way to read the frame more efficiently?
Size imgSize = img.Size;
img.Mutate(x => x.Resize(new ResizeOptions
{
Size = this.Dimensions,
Mode = ResizeMode.Manual,
TargetRectangle = new Rectangle(Point.Empty, imgSize)
}));
ImageFrame<TPixel> newFrame = image.Frames.AddFrame(img.Frames.RootFrame);
IcoFrameMetadata iconFrameMetadata = newFrame.Metadata.GetIcoMetadata();
iconFrameMetadata.SetMetadata(this.icoDirEntries[i]);

if (isPng)
{
Expand All @@ -63,41 +75,32 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
}
}

ImageMetadata metadata = new();
metadata.GetIcoMetadata().Set(this.iconDir);

Image<TPixel> image = new(
this.Options.Configuration,
metadata,
frames,
false);

return image;
}

public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
ReadHeader(stream, out this.iconDir, out this.iconDirEntries);
ReadHeader(stream, out this.icoDir, out this.icoDirEntries);
ImageMetadata metadata = new();
ImageFrameMetadata[] frames = new ImageFrameMetadata[this.iconDir.Count];
metadata.GetIcoMetadata().Set(this.iconDir);
ImageFrameMetadata[] frames = new ImageFrameMetadata[this.icoDir.Count];
metadata.GetIcoMetadata().Set(this.icoDir);
for (int i = 0; i < frames.Length; i++)
{
frames[i] = new();
IconFrameMetadata icoFrameMetadata = frames[i].GetIcoMetadata();
icoFrameMetadata.Set(this.iconDirEntries[i]);
IcoFrameMetadata icoFrameMetadata = frames[i].GetIcoMetadata();
icoFrameMetadata.SetMetadata(this.icoDirEntries[i]);
}

return new(new(32), new(0), metadata, frames);
}

private static void ReadHeader(Stream stream, out IconDir iconDir, out IconDirEntry[] iconDirEntries)
private static void ReadHeader(Stream stream, out IcoDir iconDir, out IcoDirEntry[] iconDirEntries)
{
_ = Read(stream, out iconDir, IconDir.Size);
iconDirEntries = new IconDirEntry[iconDir.Count];
_ = Read(stream, out iconDir, IcoDir.Size);
iconDirEntries = new IcoDirEntry[iconDir.Count];
for (int i = 0; i < iconDirEntries.Length; i++)
{
_ = Read(stream, out iconDirEntries[i], IconDirEntry.Size);
_ = Read(stream, out iconDirEntries[i], IcoDirEntry.Size);
}
}

Expand All @@ -121,7 +124,7 @@ private static void StreamClone(Stream src, Stream dst, byte[] buffer, int size)
while (size > 0)
{
int length = Math.Min(buffer.Length, size);
length = IconAssertHelper.EndOfStream(src.Read(buffer, 0, length), length);
length = IcoAssertHelper.EndOfStream(src.Read(buffer, 0, length), length);
size -= length;
dst.Write(buffer, 0, length);
}
Expand All @@ -143,10 +146,10 @@ private Image<TPixel> ReadImage<TPixel>(
{
const int headerSize = Bmp.BmpFileHeader.Size + Bmp.BmpInfoHeader.SizeV3;
Span<byte> bytes = stackalloc byte[Bmp.BmpInfoHeader.SizeV3];
_ = IconAssertHelper.EndOfStream(stream.Read(bytes), Bmp.BmpInfoHeader.SizeV3);
_ = IcoAssertHelper.EndOfStream(stream.Read(bytes), Bmp.BmpInfoHeader.SizeV3);

Bmp.BmpInfoHeader infoHeader = Bmp.BmpInfoHeader.ParseV3(bytes);
IconAssertHelper.IsV3Header(infoHeader);
IcoAssertHelper.IsV3Header(infoHeader);
infoHeader.Height >>= 1;

int paletteSize = infoHeader.ClrUsed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

using System.Runtime.InteropServices;

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

[StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)]
internal struct IconDir
internal struct IcoDir
{
public const int Size = 3 * sizeof(ushort);
public ushort Reserved;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

using System.Runtime.InteropServices;

namespace SixLabors.ImageSharp.Formats.Icon;
namespace SixLabors.ImageSharp.Formats.Ico;

[StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)]
internal struct IconDirEntry
internal struct IcoDirEntry
{
public const int Size = (4 * sizeof(byte)) + (2 * sizeof(ushort)) + (2 * sizeof(uint));

Expand Down
37 changes: 37 additions & 0 deletions src/ImageSharp/Formats/Ico/IcoFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Formats.Ico;

/// <summary>
/// Registers the image encoders, decoders and mime type detectors for the ICO format.
/// </summary>
public sealed class IcoFormat : IImageFormat<IcoMetadata, IcoFrameMetadata>
{
private IcoFormat()
{
}

/// <summary>
/// Gets the shared instance.
/// </summary>
public static IcoFormat Instance { get; } = new();

/// <inheritdoc/>
public string Name => "ICO";

/// <inheritdoc/>
public string DefaultMimeType => IcoConstants.MimeTypes.First();

/// <inheritdoc/>
public IEnumerable<string> MimeTypes => IcoConstants.MimeTypes;

/// <inheritdoc/>
public IEnumerable<string> FileExtensions => IcoConstants.FileExtensions;

/// <inheritdoc/>
public IcoMetadata CreateDefaultFormatMetadata() => new();

/// <inheritdoc/>
public IcoFrameMetadata CreateDefaultFormatFrameMetadata() => new();
}
Loading

0 comments on commit 6f211c1

Please sign in to comment.