Пример #1
0
        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);
        }
Пример #2
0
        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);
        }