private static IcoFrame ProcessIcoFrame(ByteReader reader, ParseContext context) { var bWidth = reader.NextUint8(); var bHeight = reader.NextUint8(); var bColorCount = reader.NextUint8(); var bReserved = reader.NextUint8(); var wPlanes = reader.NextUint16(); var wBitCount = reader.NextUint16(); var dwBytesInRes = reader.NextUint32(); var dwImageOffset = reader.NextUint32(); if (bWidth != bHeight) { context.Reporter.WarnLine(IcoErrorCode.NotSquare, $"Icon is not square ({bWidth}x{bHeight}).", context.DisplayedPath, context.ImageDirectoryIndex.Value); } if (bReserved != FileFormatConstants._iconEntryReserved) { throw new InvalidIcoFileException(IcoErrorCode.InvalidFrameHeader_bReserved, $"ICONDIRECTORY.bReserved should be {FileFormatConstants._iconEntryReserved}, was {bReserved}.", context); } if (wPlanes > 1) { throw new InvalidIcoFileException(IcoErrorCode.InvalidFrameHeader_wPlanes, $"ICONDIRECTORY.wPlanes is {wPlanes}. Only single-plane bitmaps are supported.", context); } if (dwBytesInRes > int.MaxValue) { throw new InvalidIcoFileException(IcoErrorCode.InvalidFrameHeader_dwBytesInRes, $"ICONDIRECTORY.dwBytesInRes == {dwBytesInRes}, which is unreasonably large.", context); } if (dwImageOffset > int.MaxValue) { throw new InvalidIcoFileException(IcoErrorCode.InvalidFrameHeader_dwImageOffset, $"ICONDIRECTORY.dwImageOffset == {dwImageOffset}, which is unreasonably large.", context); } var source = new IcoFrame { TotalDiskUsage = dwBytesInRes + /* sizeof(ICONDIRENTRY) */ 16, Encoding = new IcoFrameEncoding { ClaimedBitDepth = wBitCount, ClaimedHeight = bHeight > 0 ? bHeight : 256u, ClaimedWidth = bWidth > 0 ? bWidth : 256u, }, }; source.RawData = reader.Data.Slice((int)dwImageOffset, (int)dwBytesInRes).ToArray(); var bitmapHeader = new ByteReader(source.RawData, ByteOrder.LittleEndian); var signature = bitmapHeader.NextUint64(); bitmapHeader.SeekOffset = 0; if (PngDecoder.IsProbablyPngFile(ByteOrderConverter.To(ByteOrder.NetworkEndian, signature))) { PngDecoder.DoPngEntry(bitmapHeader, context, source); } else { BmpDecoder.DoBitmapEntry(bitmapHeader, context, source); } return(source); }
private static IcoFrame GenerateFrame(CommandLineOptions opts, ParseContext context) { var frame = new IcoFrame { Encoding = new IcoFrameEncoding(), }; var sourceFile = File.ReadAllBytes(opts.SourceImagePath); var reader = new ByteReader(sourceFile, ByteOrder.LittleEndian); var signature = reader.NextUint64(); var sourceEncoding = PngDecoder.IsProbablyPngFile(ByteOrderConverter.To(ByteOrder.NetworkEndian, signature)) ? IcoEncodingType.Png : IcoEncodingType.Bitmap; bool canSourceBePreserved = false; switch (sourceEncoding) { case IcoEncodingType.Bitmap: ReadBmpFile(opts, context, frame, sourceFile); break; case IcoEncodingType.Png: ReadPngFile(opts, context, frame, sourceFile, out canSourceBePreserved); break; } frame.Encoding.ActualHeight = (uint)frame.CookedData.Height; frame.Encoding.ClaimedHeight = (uint)frame.CookedData.Height; frame.Encoding.ActualWidth = (uint)frame.CookedData.Width; frame.Encoding.ClaimedWidth = (uint)frame.CookedData.Width; var outputEncoding = opts.EncodingOverride ?? sourceEncoding; if (outputEncoding != IcoEncodingType.Bitmap && opts.BitmapEncodingOverride.HasValue) { Reporter.WarnLine(IcoErrorCode.OnlySupportedOnBitmaps, "Ignoring bitmap encoding configuration because we're not emitting a bitmap frame"); } if (outputEncoding != sourceEncoding) { canSourceBePreserved = false; } if (canSourceBePreserved || opts.KeepRawFrameData) { frame.RawData = sourceFile; } else { switch (outputEncoding) { case IcoEncodingType.Bitmap: WriteBmpFrame(opts, context, frame); break; case IcoEncodingType.Png: WritePngFrame(opts, context, frame); break; } } if (opts.BitDepthOverride.HasValue) { frame.Encoding.ClaimedBitDepth = (uint)opts.BitDepthOverride.Value; } return(frame); }