public static void WriteImage(Bitmap src, Stream stream) { IcnsType imageType = IcnsType.FindType(src.Width, src.Height, 32, IcnsType.TypeDetails.None); if (imageType == null) { throw new NotSupportedException($"Invalid/unsupported source: {src.Width}x{src.Height}"); } Write4Bytes(stream, ICNS_MAGIC); Write4Bytes(stream, 4 + 4 + 4 + 4 + 4 * imageType.Width * imageType.Height + 4 + 4 + imageType.Width * imageType.Height); Write4Bytes(stream, imageType.Type); Write4Bytes(stream, 4 + 4 + 4 * imageType.Width * imageType.Height); BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // the image for (int y = 0; y < src.Height; y++) { for (int x = 0; x < src.Width; x++) { uint argb = IcnsDecoder.GetPixel(bitmapData, x, y); stream.WriteByte(0); stream.WriteByte((byte)((argb & 0x00ff0000) >> 16)); stream.WriteByte((byte)((argb & 0x0000ff00) >> 8)); stream.WriteByte((byte)((argb & 0x000000ff) >> 0)); } } // mask IcnsType maskType = IcnsType.FindType(src.Width, src.Height, 8, IcnsType.TypeDetails.Mask); Write4Bytes(stream, maskType.Type); Write4Bytes(stream, 4 + 4 + imageType.Width * imageType.Width); for (int y = 0; y < src.Height; y++) { for (int x = 0; x < src.Width; x++) { uint argb = IcnsDecoder.GetPixel(bitmapData, x, y); stream.WriteByte((byte)((argb & 0xff000000) >> 24)); } } }
private static IcnsImage DecodeImage(IcnsImageParser.IcnsElement imageElement, IcnsImageParser.IcnsElement[] icnsElements) { IcnsType imageType = IcnsType.FindType(imageElement.type, IcnsType.TypeDetails.Mask); if (imageType == null) { return(null); } IcnsType maskType = null; IcnsImageParser.IcnsElement maskElement = null; if (imageType.Details == IcnsType.TypeDetails.HasMask) { maskType = imageType; maskElement = imageElement; } else if (imageType.Details == IcnsType.TypeDetails.None) { maskType = IcnsType.FindType(imageType.Width, imageType.Height, 8, IcnsType.TypeDetails.Mask); if (maskType != null) { maskElement = FindElement(icnsElements, maskType.Type); } if (maskElement == null) { maskType = IcnsType.FindType(imageType.Width, imageType.Height, 1, IcnsType.TypeDetails.Mask); if (maskType != null) { maskElement = FindElement(icnsElements, maskType.Type); } } } if (imageType.Details == IcnsType.TypeDetails.Compressed || imageType.Details == IcnsType.TypeDetails.Retina) { IcnsImage result = TryDecodingPng(imageElement, imageType); if (result != null) { return(result); // png } if (LoadJ2kImage == null) { return(null); // couldn't be loaded } return(LoadJ2kImage(imageElement, imageType)); } int expectedSize = (imageType.Width * imageType.Height * imageType.BitsPerPixel + 7) / 8; byte[] imageData; if (imageElement.data.Length < expectedSize) { if (imageType.BitsPerPixel == 32) { imageData = Rle24Compression.Decompress(imageType.Width, imageType.Height, imageElement.data); } else { throw new Exception("Short image data but not a 32 bit compressed type"); } } else { imageData = imageElement.data; } Bitmap image = new Bitmap(imageType.Width, imageType.Height, PixelFormat.Format32bppArgb); BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); switch (imageType.BitsPerPixel) { case 1: Decode1BPPImage(imageType, imageData, bitmapData); break; case 4: Decode4BPPImage(imageType, imageData, bitmapData); break; case 8: Decode8BPPImage(imageType, imageData, bitmapData); break; case 32: if (imageType.Details == IcnsType.TypeDetails.ARGB) { Decode32BPPImageARGB(imageType, imageData, bitmapData); } else { Decode32BPPImage(imageType, imageData, bitmapData); } break; default: image.UnlockBits(bitmapData); image.Dispose(); throw new NotSupportedException("Unsupported bit depth " + imageType.BitsPerPixel); } if (maskElement != null) { switch (maskType.BitsPerPixel) { case 1: Apply1BPPMask(maskElement.data, bitmapData); break; case 8: Apply8BPPMask(maskElement.data, bitmapData); break; default: image.UnlockBits(bitmapData); image.Dispose(); throw new NotSupportedException("Unsupport mask bit depth " + maskType.BitsPerPixel); } } image.UnlockBits(bitmapData); return(new IcnsImage(image, imageType)); }