Exemple #1
0
        static byte[] decodeMonochromeIcon(byte[] payload, CSize size)
        {
            int totalPixels = size.cx * size.cy;

            int maskLineDwords  = (size.cx + 31) / 32;
            int maskStrideBytes = maskLineDwords * 4;
            int bytesMask       = size.cy * maskStrideBytes;

            int cbHeader = Marshal.SizeOf <BITMAPINFOHEADER>();

            // 8 is the color table, immediately after the header
            if (payload.Length != cbHeader + (bytesMask * 2) + 8)
            {
                throw new ArgumentException("Size doesn't match");
            }

            byte[]      image   = new byte[totalPixels];
            Span <byte> palette = stackalloc byte[4];
            {
                Span <uint> colorTable = stackalloc uint[2];
                payload.AsSpan()
                .Slice(cbHeader, 8)
                .castSpan <uint>()
                .CopyTo(colorTable);
                ePalette pal = getPalette(colorTable);
                decodePalette(pal, palette);
            }

            ReadOnlySpan <byte> bits = payload.AsSpan()
                                       .Slice(cbHeader + 8, bytesMask);

            ReadOnlySpan <byte> mask = payload.AsSpan()
                                       .Slice(cbHeader + 8 + bytesMask, bytesMask);

            if (0 == (size.cx % 32))
            {
                // No padding whatsoever
                decodeMonochrome(image.AsSpan(), bits, mask, palette, totalPixels);
            }
            else
            {
                // There is some padding
                Span <byte> imageSpan        = image.AsSpan();
                int         maskBytesPerLine = (size.cx + 7) / 8;
                int         destOffset       = 0;
                int         sourceOffset     = 0;
                for (int y = 0; y < size.cy; y++, destOffset += size.cx, sourceOffset += maskStrideBytes)
                {
                    Span <byte>         destSpan = imageSpan.Slice(destOffset, size.cx);
                    ReadOnlySpan <byte> lineBits = bits.Slice(sourceOffset, maskBytesPerLine);
                    ReadOnlySpan <byte> lineMask = mask.Slice(sourceOffset, maskBytesPerLine);
                    decodeMonochrome(destSpan, lineBits, lineMask, palette, size.cx);
                }
            }
            return(image);
        }
Exemple #2
0
        static void decodePalette(ePalette pal, Span <byte> values)
        {
            Debug.Assert(values.Length == 4);
            // https://devblogs.microsoft.com/oldnewthing/20101018-00/?p=12513
            switch (pal)
            {
            case ePalette.FirstBlack:
                values[0] = 0;                                  // mask 0 image 0 = black
                values[1] = 0x55;                               // mask 0 image 1 = white
                values[2] = 0xAA;                               // mask 1 image 0 = nop
                values[3] = 0xFF;                               // mask 1 image 1 = invert
                break;

            case ePalette.FirstWhite:
                values[0] = 0x55;                               // mask 0 image 1 = white
                values[1] = 0;                                  // mask 0 image 0 = black
                values[2] = 0xFF;                               // mask 1 image 1 = invert
                values[3] = 0xAA;                               // mask 1 image 0 = nop
                break;
            }
        }