Beispiel #1
0
        static DecodedBitmap DecodeBitmap(BitmapInfoHeader header, IList <Rgb> palette, byte[] data)
        {
            if (header.BitmapCompression != BitmapCompression.None)
            {
                return(null);
            }

            DecodedBitmap bitmap = new DecodedBitmap
            {
                BitsPerPixel = header.BitsPerPlane,
                Height       = header.Height,
                Width        = header.Width,
                Pixels       = new int[header.Width * header.Height]
            };

            int[] argbPalette = new int[palette.Count];

            for (int c = 0; c < palette.Count; c++)
            {
                argbPalette[c] = (palette[c].Red << 16) + (palette[c].Green << 8) + palette[c].Blue;
            }

            long pos = 0;

            for (int y = 0; y < bitmap.Height; y++)
            {
                int x = 0;
                while (x < bitmap.Width)
                {
                    for (int k = (int)(8 - bitmap.BitsPerPixel); k >= 0; k -= (int)bitmap.BitsPerPixel)
                    {
                        bitmap.Pixels[y * bitmap.Width + x] =
                            argbPalette[(data[pos] >> k) & ((1 << (int)bitmap.BitsPerPixel) - 1)];
                        x++;

                        if (x == bitmap.Width)
                        {
                            break;
                        }
                    }

                    pos++;
                }

                pos += pos % 2;
            }

            return(bitmap);
        }
Beispiel #2
0
        /// <summary>
        ///     This will decode an icon
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>A <see cref="DecodedBitmap" /> with the icon, null if the icon could not be decoded</returns>
        public static DecodedBitmap DecodeIcon(byte[] data)
        {
            long pos = 0;

            byte[] buffer = new byte[Marshal.SizeOf(typeof(BitmapInfoHeader))];
            Array.Copy(data, pos, buffer, 0, buffer.Length);
            BitmapInfoHeader bitmapFileHeader =
                BigEndianMarshal.ByteArrayToStructureLittleEndian <BitmapInfoHeader>(buffer);

            // Stop at unknown header
            if (bitmapFileHeader.HeaderSize != 40)
            {
                return(null);
            }

            // Multiplanes not supported
            if (bitmapFileHeader.Planes != 1)
            {
                return(null);
            }

            // TODO: Non paletted?
            pos += bitmapFileHeader.HeaderSize;
            Rgb[] palette = new Rgb[1 << bitmapFileHeader.BitsPerPlane];
            buffer = new byte[Marshal.SizeOf(typeof(Rgb))];
            for (int i = 0; i < palette.Length; i++)
            {
                Array.Copy(data, pos, buffer, 0, buffer.Length);
                pos       += buffer.Length;
                palette[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Rgb>(buffer);
            }

            // First let's do the icon itself
            bitmapFileHeader.Height /= 2;
            long dataLength = 0;

            for (int y = 0; y < bitmapFileHeader.Height; y++)
            {
                int x = 0;
                while (x < bitmapFileHeader.Width)
                {
                    for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane)
                    {
                        x++;
                    }

                    dataLength++;
                }

                dataLength += dataLength % 2;
            }

            buffer = new byte[dataLength];
            Array.Copy(data, pos, buffer, 0, buffer.Length);

            DecodedBitmap icon = DecodeBitmap(bitmapFileHeader, palette, buffer);

            // Then the mask
            pos += dataLength;
            bitmapFileHeader.BitsPerPlane = 1;
            dataLength = 0;
            for (int y = 0; y < bitmapFileHeader.Height; y++)
            {
                int x = 0;
                while (x < bitmapFileHeader.Width)
                {
                    for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane)
                    {
                        x++;
                    }

                    dataLength++;
                }

                dataLength += dataLength % 2;
            }

            buffer = new byte[dataLength];
            Array.Copy(data, pos, buffer, 0, buffer.Length);

            DecodedBitmap mask = DecodeBitmap(bitmapFileHeader, palette, buffer);

            // Mask palette
            int[] argbPalette = new int[palette.Length];
            for (int c = 0; c < palette.Length; c++)
            {
                argbPalette[c] = (palette[c].Red << 16) + (palette[c].Green << 8) + palette[c].Blue;
            }

            DecodedBitmap bitmap = new DecodedBitmap
            {
                BitsPerPixel = icon.BitsPerPixel,
                Height       = icon.Height,
                Width        = icon.Width,
                Pixels       = new int[icon.Pixels.Length]
            };

            for (int px = 0; px < bitmap.Pixels.Length; px++)
            {
                bitmap.Pixels[px] = icon.Pixels[px] + (mask.Pixels[px] == argbPalette[0] ? VISIBLE : 0);
            }

            // Need to reverse first all pixels then by line
            int[] pixels = bitmap.Pixels.Reverse().ToArray();
            for (int y = 0; y < bitmap.Height; y++)
            {
                for (int x = 0; x < bitmap.Width; x++)
                {
                    bitmap.Pixels[y * bitmap.Width + (bitmap.Width - x - 1)] = pixels[y * bitmap.Width + x];
                }
            }

            return(bitmap);
        }