Exemplo n.º 1
0
        /// <summary>
        /// Creates a Blp2 object from the specified data stream.
        /// </summary>
        /// <param name="stream">A stream that contains the data of a Blp2 or System.Drawing.Image picture.</param>
        /// <returns>Blp2 object containing the image of the stream.</returns>
        /// <exception cref=""></exception>
        public static Blp2 FromStream(Stream stream)
        {
            using (BinaryReader br = new BinaryReader(stream)) {
                Blp2Header header = Blp2Header.FromBinaryReader(br);

                Blp2 ret = new Blp2();

                if (new string(header.fourCC) == "BLP2")
                {
                    ret.bmp = new Bitmap((int)header.width, (int)header.height, PixelFormat.Format32bppArgb);

                    BitmapData bmpData = ret.bmp.LockBits(new Rectangle(0, 0, ret.bmp.Width, ret.bmp.Height), ImageLockMode.ReadWrite, ret.bmp.PixelFormat);

                    byte[] imgData = new byte[header.lengths[0]];
                    br.BaseStream.Seek(header.offsets[0], SeekOrigin.Begin);
                    imgData = br.ReadBytes(imgData.Length);

                    // BLP2 conversion
                    if (header.type == DataType.Uncompressed_DirectX && header.encoding == Encoding.RAW1 &&
                        (header.alphaDepth == AlphaDepth.NoAlpha || header.alphaDepth == AlphaDepth.Alpha1Bit || header.alphaDepth == AlphaDepth.Alpha8Bit))
                    {
                        // Uncompressed paletted image
                        ret.format = FileFormat.Raw;

                        // Load palette (4-byte BGRA color values)
                        br.BaseStream.Seek(Marshal.SizeOf(typeof(Blp2Header)), SeekOrigin.Begin);
                        byte[]  colorData = br.ReadBytes(256 * 4);
                        Color[] c         = new Color[256];
                        for (int i = 0; i < 1024; i += 4)
                        {
                            c[i / 4] = Color.FromArgb(255, colorData[i], colorData[i + 1], colorData[i + 2]);
                        }

                        // Read indexed bitmap
                        byte[] decompImgData = new byte[header.width * header.height * 4];
                        for (int i = 0; i < (header.width * header.height); i++)
                        {
                            decompImgData[i * 4]     = c[imgData[i]].R;
                            decompImgData[i * 4 + 1] = c[imgData[i]].G;
                            decompImgData[i * 4 + 2] = c[imgData[i]].B;
                            decompImgData[i * 4 + 3] = 255;
                        }

                        // Apply alpha channels
                        if (header.alphaDepth == AlphaDepth.Alpha8Bit)
                        {
                            // 8-bits alpha
                            br.BaseStream.Seek(header.offsets[0] + header.width * header.height, SeekOrigin.Begin);
                            byte[] alphaData = br.ReadBytes((int)(header.width * header.height));
                            for (int i = 0; i < (header.width * header.height); i++)
                            {
                                decompImgData[i * 4 + 3] = alphaData[i];
                            }
                        }
                        else if (header.alphaDepth == AlphaDepth.Alpha1Bit)
                        {
                            // 1-bits alpha
                            br.BaseStream.Seek(header.offsets[0] + (header.width * header.height), SeekOrigin.Begin);
                            byte[] alphaData = br.ReadBytes((int)(header.width * header.height / 8));
                            for (int i = 0; i < (header.width * header.height / 8); i++)
                            {
                                for (int j = 0; j < 8; j++)
                                {
                                    decompImgData[i * 32 + ((j + 1) * 4) - 1] = (byte)((alphaData[i] & 1 << j) == 1 << j ? 255 : 0);
                                }
                            }
                        }

                        Marshal.Copy(decompImgData, 0, bmpData.Scan0, decompImgData.Length);
                    }
                    else if (header.type == DataType.Uncompressed_DirectX && header.encoding == Encoding.RAW3 &&

                             (header.alphaDepth == AlphaDepth.NoAlpha || header.alphaDepth == AlphaDepth.Alpha1Bit || header.alphaDepth == AlphaDepth.Alpha8Bit))
                    {
                        // Uncompressed BGRA image
                        ret.format = FileFormat.Raw;
                        Marshal.Copy(imgData, 0, bmpData.Scan0, imgData.Length);
                    }
                    else if (header.type == DataType.Uncompressed_DirectX && header.encoding == Encoding.DXT &&
                             (header.alphaEncoding == AlphaEncoding.DXT1 || header.alphaEncoding == AlphaEncoding.DXT3 || header.alphaEncoding == AlphaEncoding.DXT5))
                    {
                        // DXT1/3/5
                        ret.format = FileFormat.Dxt;

                        byte[] decompImgData = new byte[header.width * header.height * 4];

                        LibSquish.DxtFormat flags = 0;
                        switch (header.alphaEncoding)
                        {
                        case AlphaEncoding.DXT1:
                            flags = LibSquish.DxtFormat.Dxt1;
                            break;

                        case AlphaEncoding.DXT3:
                            flags = LibSquish.DxtFormat.Dxt3;
                            break;

                        case AlphaEncoding.DXT5:
                            flags = LibSquish.DxtFormat.Dxt5;
                            break;
                        }

                        LibSquish.DecompressImage(decompImgData, header.width, header.height, imgData, (int)flags);
                        RemapRGBA(ref decompImgData);
                        Marshal.Copy(decompImgData, 0, bmpData.Scan0, decompImgData.Length);
                    }
                    else if (header.type == DataType.JPEG)
                    {
                        ret.format = FileFormat.Jpeg;
                        ret.bmp.UnlockBits(bmpData);
                        throw new NotImplementedException();
                    }
                    else
                    {
                        ret.bmp.UnlockBits(bmpData);
                        throw new BlpFormatException("The given BLP2 format is not supported.");
                    }

                    ret.bmp.UnlockBits(bmpData);
                }
                else
                {
                    try {
                        // Let System.Drawing.Image handle loading
                        ret.bmp    = (Bitmap)Image.FromStream(stream);
                        ret.format = FileFormat.Image;
                    } catch (ArgumentException e) {
                        throw new BlpFormatException("The stream did not contain valid image data.", e.InnerException);
                    }
                }

                ret.header = header;
                return(ret);
            }
        }