mirror of
https://github.com/rmcrackan/Libation.git
synced 2025-12-23 22:17:52 -05:00
Add multiple image sizes in windows folder icons
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -11,39 +13,57 @@ namespace WindowsConfigApp;
|
||||
public class IcoEncoder : IImageEncoder
|
||||
{
|
||||
public bool SkipMetadata { get; init; } = true;
|
||||
public ReadOnlyCollection<int> ExportSizes { get; }
|
||||
public IcoEncoder(): this(512, 256, 128, 96, 64, 48, 32, 24) { }
|
||||
public IcoEncoder(params int[] icoSizes)
|
||||
{
|
||||
Array.Sort(icoSizes);
|
||||
ExportSizes = new(icoSizes);
|
||||
}
|
||||
|
||||
public void Encode<TPixel>(Image<TPixel> image, Stream stream) where TPixel : unmanaged, IPixel<TPixel>
|
||||
{
|
||||
// https://stackoverflow.com/a/21389253
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
//Knowing the image size ahead of time removes the
|
||||
//requirement of the output stream to support seeking.
|
||||
image.SaveAsPng(ms);
|
||||
byte[][] iconPngs = new byte[ExportSizes.Count][];
|
||||
for (int i = 0; i < ExportSizes.Count; i++)
|
||||
{
|
||||
int size = ExportSizes[i];
|
||||
using var resized = image.Clone(x => x.Resize(size, size, KnownResamplers.Lanczos2));
|
||||
using var pngMs = new MemoryStream();
|
||||
resized.SaveAsPng(pngMs);
|
||||
iconPngs[i] = pngMs.ToArray();
|
||||
}
|
||||
|
||||
//Disposing of the BinaryWriter disposes the soutput stream. Let the caller clean up.
|
||||
var bw = new BinaryWriter(stream);
|
||||
|
||||
// Header
|
||||
bw.Write((short)0); // 0-1 : reserved
|
||||
bw.Write((short)1); // 2-3 : 1=ico, 2=cur
|
||||
bw.Write((short)1); // 4-5 : number of images
|
||||
bw.Write((short)0); // 0-1 : reserved
|
||||
bw.Write((short)1); // 2-3 : 1=ico, 2=cur
|
||||
bw.Write((short)ExportSizes.Count); // 4-5 : number of images
|
||||
|
||||
int dataStart = 6 + (16 * ExportSizes.Count);
|
||||
// Image directory
|
||||
var w = image.Width;
|
||||
if (w >= 256) w = 0;
|
||||
bw.Write((byte)w); // 0 : width of image
|
||||
var h = image.Height;
|
||||
if (h >= 256) h = 0;
|
||||
bw.Write((byte)h); // 1 : height of image
|
||||
bw.Write((byte)0); // 2 : number of colors in palette
|
||||
bw.Write((byte)0); // 3 : reserved
|
||||
bw.Write((short)0); // 4 : number of color planes
|
||||
bw.Write((short)0); // 6 : bits per pixel
|
||||
bw.Write((int)ms.Position); // 8 : image size
|
||||
bw.Write((int)stream.Position + 4); // 12: offset of image data
|
||||
ms.Position = 0;
|
||||
ms.CopyTo(stream); // Image data
|
||||
for (int i = 0; i < ExportSizes.Count; i++)
|
||||
{
|
||||
var size = ExportSizes[i] < 256 ? ExportSizes[i] : 0;
|
||||
bw.Write((byte)size); // 0 : width of image
|
||||
bw.Write((byte)size); // 1 : height of image
|
||||
bw.Write((byte)0); // 2 : number of colors in palette
|
||||
bw.Write((byte)0); // 3 : reserved
|
||||
bw.Write((short)0); // 4 : number of color planes
|
||||
bw.Write((short)0); // 6 : bits per pixel
|
||||
bw.Write(iconPngs[i].Length); // 8 : image size
|
||||
bw.Write(dataStart); // 12: offset of image data
|
||||
dataStart += iconPngs[i].Length;
|
||||
}
|
||||
|
||||
// Image data
|
||||
for (int i = 0; i < ExportSizes.Count; i++)
|
||||
bw.Write(iconPngs[i]);
|
||||
}
|
||||
|
||||
public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel<TPixel>
|
||||
|
||||
Reference in New Issue
Block a user