Last active
September 9, 2019 20:56
-
-
Save equinox2k/1763c79d68fe01e8b0553c8c4209a34b to your computer and use it in GitHub Desktop.
Example ICNS encoder using ImageSharp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Linq; | |
| using System.IO; | |
| using SixLabors.ImageSharp; | |
| using SixLabors.ImageSharp.Processing; | |
| using SixLabors.ImageSharp.PixelFormats; | |
| namespace EQL.IconAutosizer.ImageEncoders | |
| { | |
| //https://en.wikipedia.org/wiki/Apple_Icon_Image_format | |
| public static class ICNSEncoder | |
| { | |
| private struct IconType | |
| { | |
| public string OsType { get; } | |
| public int Size { get; } | |
| public IconType(string osType, int size) | |
| { | |
| OsType = osType; | |
| Size = size; | |
| } | |
| } | |
| private static void ResizeImageToPngBinaryWriter(BinaryWriter binaryWriter, Image<Bgra32> image, int size, out int imageSize) | |
| { | |
| using (var sizedImage = image.Clone(i => i.Resize(size, size))) | |
| { | |
| var position = binaryWriter.BaseStream.Position; | |
| sizedImage.SaveAsPng(binaryWriter.BaseStream); | |
| imageSize = (int)(binaryWriter.BaseStream.Position - position); | |
| } | |
| } | |
| private static byte[] IntToBigEndian(int value) | |
| { | |
| byte[] bytes = BitConverter.GetBytes(value); | |
| if (BitConverter.IsLittleEndian) | |
| { | |
| Array.Reverse(bytes); | |
| } | |
| return bytes; | |
| } | |
| public static void Encode(string filePath, Image<Bgra32> image) | |
| { | |
| using (var fileStream = File.Create(filePath)) | |
| { | |
| Encode(fileStream, image); | |
| } | |
| } | |
| private static IconType[] GetIconTypes() | |
| { | |
| return new IconType[] | |
| { | |
| new IconType("icp4", 16), | |
| new IconType("icp5", 32), | |
| new IconType("icp6", 64), | |
| new IconType("ic07", 128), | |
| new IconType("ic08", 256), | |
| new IconType("ic09", 512), | |
| new IconType("ic10", 1024), | |
| new IconType("ic11", 32), | |
| new IconType("ic12", 64), | |
| new IconType("ic13", 256), | |
| new IconType("ic14", 512) | |
| }; | |
| } | |
| public static void Encode(Stream stream, Image<Bgra32> image) | |
| { | |
| if (!stream.CanSeek) | |
| { | |
| throw new Exception("Seekable stream is required"); | |
| } | |
| if (image.Width != image.Height || image.Width < 16) | |
| { | |
| throw new Exception("Image should be square and at least 16px in size"); | |
| } | |
| var iconTypes = GetIconTypes().Where(i => i.Size < image.Width).ToArray(); | |
| var totalSize = 8; | |
| using (var binaryWriter = new BinaryWriter(stream)) | |
| { | |
| binaryWriter.Write("icns".ToCharArray()); | |
| binaryWriter.Write(0); | |
| foreach (var iconType in iconTypes) | |
| { | |
| stream.Seek(0, SeekOrigin.End); | |
| binaryWriter.Write(iconType.OsType.ToCharArray()); | |
| binaryWriter.Write(0); | |
| ResizeImageToPngBinaryWriter(binaryWriter, image, iconType.Size, out var imageSize); | |
| stream.Position = totalSize + 4; | |
| var size = imageSize + 8; | |
| binaryWriter.Write(IntToBigEndian(size)); | |
| totalSize += size; | |
| } | |
| stream.Position = 4; | |
| binaryWriter.Write(IntToBigEndian(totalSize)); | |
| binaryWriter.Flush(); | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment