Пример #1
0
        public void replaceMipMaps(List <MipMap> newMipMaps)
        {
            mipMapsList = newMipMaps;
            textureData.Dispose();
            textureData = new MemoryStream();
            if (GameData.gameType != MeType.ME3_TYPE)
            {
                textureData.WriteZeros(12);
                textureData.WriteUInt32(0); // filled later
            }
            textureData.WriteInt32(newMipMaps.Count);
            for (int l = 0; l < newMipMaps.Count; l++)
            {
                MipMap mipmap = mipMapsList[l];
                textureData.WriteUInt32((uint)mipmap.storageType);
                textureData.WriteInt32(mipmap.uncompressedSize);
                textureData.WriteInt32(mipmap.compressedSize);
                textureData.WriteUInt32(mipmap.dataOffset);

                if (mipmap.storageType == StorageTypes.pccUnc ||
                    mipmap.storageType == StorageTypes.pccLZO ||
                    mipmap.storageType == StorageTypes.pccZlib)
                {
                    mipmap.internalOffset = (uint)textureData.Position;
                    textureData.WriteFromBuffer(mipmap.newData);
                }
                mipMapsList[l] = mipmap;
            }
        }
Пример #2
0
        static private byte[] convertToFormat(PixelFormat srcFormat, byte[] src, int w, int h, PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128)
        {
            byte[] tempData;

            switch (dstFormat)
            {
            case PixelFormat.DXT1:
            case PixelFormat.DXT3:
            case PixelFormat.DXT5:
            case PixelFormat.ATI2:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                if (dstFormat == PixelFormat.ATI2 && (w < 4 || h < 4))
                {
                    tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)];
                }
                else if (w < 4 || h < 4)
                {
                    if (w < 4)
                    {
                        w = 4;
                    }
                    if (h < 4)
                    {
                        h = 4;
                    }
                    tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)];
                }
                else
                {
                    tempData = compressMipmap(dstFormat, tempData, w, h, dxt1HasAlpha, dxt1Threshold);
                }
                break;

            case PixelFormat.ARGB:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                break;

            case PixelFormat.RGB:
                tempData = convertRawToRGB(src, w, h, srcFormat);
                break;

            case PixelFormat.V8U8:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                tempData = ARGBtoV8U8(tempData, w, h);
                break;

            case PixelFormat.G8:
                tempData = convertRawToARGB(src, w, h, srcFormat);
                tempData = ARGBtoG8(tempData, w, h);
                break;

            default:
                throw new Exception("not supported format");
            }

            return(tempData);
        }
Пример #3
0
 public uint getCrcMipmap(MipMap mipmap)
 {
     byte[] data = getMipMapData(mipmap);
     if (data == null)
     {
         return(0);
     }
     return(getCrcData(data));
 }
Пример #4
0
        public MipMap getTopMipmap()
        {
            MipMap mipmap = mipMapsList.Find(b => b.storageType != StorageTypes.empty);

            if (mipmap.width == 0)
            {
                throw new Exception();
            }

            return(mipmap);
        }
Пример #5
0
        public Image convertToRGB()
        {
            for (int i = 0; i < mipMaps.Count; i++)
            {
                mipMaps[i] = new MipMap(convertRawToRGB(mipMaps[i].data, mipMaps[i].width, mipMaps[i].height, pixelFormat),
                                        mipMaps[i].width, mipMaps[i].height, PixelFormat.RGB);
            }
            pixelFormat = PixelFormat.RGB;

            return(this);
        }
Пример #6
0
        public byte[] toArray(uint pccTextureDataOffset, bool updateOffset = true)
        {
            using (MemoryStream newData = new MemoryStream())
            {
                if (GameData.gameType != MeType.ME3_TYPE)
                {
                    newData.WriteZeros(16);
                }
                newData.WriteInt32(mipMapsList.Count());
                for (int l = 0; l < mipMapsList.Count(); l++)
                {
                    MipMap mipmap = mipMapsList[l];
                    newData.WriteInt32((int)mipmap.storageType);
                    newData.WriteInt32(mipmap.uncompressedSize);
                    newData.WriteInt32(mipmap.compressedSize);
                    if (mipmap.storageType == StorageTypes.pccUnc)
                    {
                        newData.WriteUInt32(0);
                        textureData.JumpTo(mipmap.internalOffset);
                        if (updateOffset)
                        {
                            mipmap.internalOffset = (uint)newData.Position;
                        }
                        newData.WriteFromBuffer(textureData.ReadToBuffer(mipmap.uncompressedSize));
                    }
                    else if (mipmap.storageType == StorageTypes.pccLZO ||
                             mipmap.storageType == StorageTypes.pccZlib)
                    {
                        mipmap.dataOffset = (uint)newData.Position + pccTextureDataOffset + 4;
                        newData.WriteUInt32(mipmap.dataOffset);
                        textureData.JumpTo(mipmap.internalOffset);
                        if (updateOffset)
                        {
                            mipmap.internalOffset = (uint)newData.Position;
                        }
                        newData.WriteFromBuffer(textureData.ReadToBuffer(mipmap.compressedSize));
                    }
                    else
                    {
                        newData.WriteUInt32(mipmap.dataOffset);
                    }
                    newData.WriteInt32(mipmap.width);
                    newData.WriteInt32(mipmap.height);
                    mipMapsList[l] = mipmap;
                }

                newData.WriteFromBuffer(restOfData);

                return(newData.ToArray());
            }
        }
Пример #7
0
        public void StoreImageToDDS(Stream stream, PixelFormat format = PixelFormat.Unknown)
        {
            stream.WriteUInt32(DDS_TAG);
            stream.WriteInt32(DDS_HEADER_dwSize);
            stream.WriteUInt32(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE);
            stream.WriteInt32(mipMaps[0].height);
            stream.WriteInt32(mipMaps[0].width);

            int dataSize = 0;

            for (int i = 0; i < mipMaps.Count; i++)
            {
                dataSize += MipMap.getBufferSize(mipMaps[i].width, mipMaps[i].height, format == PixelFormat.Unknown ? pixelFormat : format);
            }
            stream.WriteInt32(dataSize);

            stream.WriteUInt32(0); // dwDepth
            stream.WriteInt32(mipMaps.Count);
            stream.WriteZeros(44); // dwReserved1

            stream.WriteInt32(DDS_PIXELFORMAT_dwSize);
            DDS_PF pixfmt = getDDSPixelFormat(format == PixelFormat.Unknown ? pixelFormat: format);

            stream.WriteUInt32(pixfmt.flags);
            stream.WriteUInt32(pixfmt.fourCC);
            stream.WriteUInt32(pixfmt.bits);
            stream.WriteUInt32(pixfmt.Rmask);
            stream.WriteUInt32(pixfmt.Gmask);
            stream.WriteUInt32(pixfmt.Bmask);
            stream.WriteUInt32(pixfmt.Amask);

            stream.WriteInt32(DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE);
            stream.WriteUInt32(0); // dwCaps2
            stream.WriteUInt32(0); // dwCaps3
            stream.WriteUInt32(0); // dwCaps4
            stream.WriteUInt32(0); // dwReserved2
            for (int i = 0; i < mipMaps.Count; i++)
            {
                stream.WriteFromBuffer(mipMaps[i].data);
            }
        }
Пример #8
0
        private void LoadImageTGA(MemoryStream stream, ImageFormat format)
        {
            int idLength = stream.ReadByte();

            int colorMapType = stream.ReadByte();

            if (colorMapType != 0)
            {
                throw new Exception("indexed TGA not supported!");
            }

            int imageType = stream.ReadByte();

            if (imageType != 2 && imageType != 10)
            {
                throw new Exception("only RGB TGA supported!");
            }

            bool compressed = false;

            if (imageType == 10)
            {
                compressed = true;
            }

            stream.SkipInt16(); // color map first entry index
            stream.SkipInt16(); // color map length
            stream.Skip(1);     // color map entry size
            stream.SkipInt16(); // x origin
            stream.SkipInt16(); // y origin

            int imageWidth  = stream.ReadInt16();
            int imageHeight = stream.ReadInt16();

            if (!checkPowerOfTwo(imageWidth) ||
                !checkPowerOfTwo(imageHeight))
            {
                throw new Exception("dimensions not power of two");
            }

            int imageDepth = stream.ReadByte();

            if (imageDepth != 32 && imageDepth != 24)
            {
                throw new Exception("only 24 and 32 bits TGA supported!");
            }

            int imageDesc = stream.ReadByte();

            if ((imageDesc & 0x10) != 0)
            {
                throw new Exception("origin right not supported in TGA!");
            }

            bool downToTop = true;

            if ((imageDesc & 0x20) != 0)
            {
                downToTop = false;
            }

            stream.Skip(idLength);

            byte[] buffer = new byte[imageWidth * imageHeight * 4];
            int    pos    = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0;
            int    delta  = downToTop ? -imageWidth * 4 * 2 : 0;

            if (compressed)
            {
                int count = 0, repeat = 0, w = 0, h = 0;
                for (;;)
                {
                    if (count == 0 && repeat == 0)
                    {
                        byte code = (byte)stream.ReadByte();
                        if ((code & 0x80) != 0)
                        {
                            repeat = (code & 0x7F) + 1;
                        }
                        else
                        {
                            count = code + 1;
                        }
                    }
                    else
                    {
                        byte pixelR, pixelG, pixelB, pixelA;
                        if (repeat != 0)
                        {
                            pixelR = (byte)stream.ReadByte();
                            pixelG = (byte)stream.ReadByte();
                            pixelB = (byte)stream.ReadByte();
                            if (imageDepth == 32)
                            {
                                pixelA = (byte)stream.ReadByte();
                            }
                            else
                            {
                                pixelA = 0xFF;
                            }
                            for (; w < imageWidth && repeat > 0; w++, repeat--)
                            {
                                buffer[pos++] = pixelR;
                                buffer[pos++] = pixelG;
                                buffer[pos++] = pixelB;
                                buffer[pos++] = pixelA;
                            }
                        }
                        else
                        {
                            for (; w < imageWidth && count > 0; w++, count--)
                            {
                                buffer[pos++] = (byte)stream.ReadByte();
                                buffer[pos++] = (byte)stream.ReadByte();
                                buffer[pos++] = (byte)stream.ReadByte();
                                if (imageDepth == 32)
                                {
                                    buffer[pos++] = (byte)stream.ReadByte();
                                }
                                else
                                {
                                    buffer[pos++] = 0xFF;
                                }
                            }
                        }
                    }

                    if (w == imageWidth)
                    {
                        w    = 0;
                        pos += delta;
                        if (++h == imageHeight)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                for (int h = 0; h < imageHeight; h++, pos += delta)
                {
                    for (int w = 0; w < imageWidth; w++)
                    {
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        if (imageDepth == 32)
                        {
                            buffer[pos++] = (byte)stream.ReadByte();
                        }
                        else
                        {
                            buffer[pos++] = 0xFF;
                        }
                    }
                }
            }

            pixelFormat = PixelFormat.ARGB;
            MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB);

            mipMaps.Add(mipmap);
        }
Пример #9
0
        private void LoadImage(MemoryStream stream, ImageFormat format)
        {
            mipMaps = new List <MipMap>();
            switch (format)
            {
            case ImageFormat.DDS:
            {
                LoadImageDDS(stream, format);
                break;
            }

            case ImageFormat.TGA:
            {
                LoadImageTGA(stream, format);
                break;
            }

            case ImageFormat.BMP:
            {
                LoadImageBMP(stream, format);
                break;
            }

            case ImageFormat.PNG:
            case ImageFormat.JPEG:
            {
                BitmapSource frame = null;
                if (format == ImageFormat.PNG)
                {
                    frame = new PngBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];
                }
                else if (format == ImageFormat.JPEG)
                {
                    frame = new JpegBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];
                }

                if (!checkPowerOfTwo(frame.PixelWidth) ||
                    !checkPowerOfTwo(frame.PixelHeight))
                {
                    throw new Exception("dimensions not power of two");
                }

                FormatConvertedBitmap srcBitmap = new FormatConvertedBitmap();
                srcBitmap.BeginInit();
                srcBitmap.Source            = frame;
                srcBitmap.DestinationFormat = PixelFormats.Bgra32;
                srcBitmap.EndInit();

                byte[] pixels = new byte[srcBitmap.PixelWidth * srcBitmap.PixelHeight * 4];
                frame.CopyPixels(pixels, srcBitmap.PixelWidth * 4, 0);

                pixelFormat = PixelFormat.ARGB;
                MipMap mipmap = new MipMap(pixels, srcBitmap.PixelWidth, srcBitmap.PixelHeight, PixelFormat.ARGB);
                mipMaps.Add(mipmap);
                break;
            }

            default:
                throw new Exception();
            }
        }
Пример #10
0
        public Texture(Package package, int exportId, byte[] data, bool fixDim = true)
        {
            properties = new TexProperty(package, data);
            if (data.Length == properties.propertyEndOffset)
            {
                return;
            }

            packagePath = package.packageFile.Name;
            packageName = Path.GetFileNameWithoutExtension(package.packageFile.Name).ToUpper();
            if (GameData.gameType == MeType.ME1_TYPE && package.compressed)
            {
                string basePkg = package.resolvePackagePath(package.exportsTable[exportId].linkId).Split('.')[0].ToUpper();
                if (basePkg != "")
                {
                    packageName = basePkg;
                }
            }

            textureData = new MemoryStream(data, properties.propertyEndOffset, data.Length - properties.propertyEndOffset);
            if (GameData.gameType != MeType.ME3_TYPE)
            {
                textureData.Skip(12);    // 12 zeros
                textureData.SkipInt32(); // position in the package
            }

            mipMapsList = new List <MipMap>();
            int numMipMaps = textureData.ReadInt32();

            for (int l = 0; l < numMipMaps; l++)
            {
                MipMap mipmap = new MipMap();
                mipmap.storageType      = (StorageTypes)textureData.ReadInt32();
                mipmap.uncompressedSize = textureData.ReadInt32();
                mipmap.compressedSize   = textureData.ReadInt32();
                mipmap.dataOffset       = textureData.ReadUInt32();
                if (mipmap.storageType == StorageTypes.pccUnc)
                {
                    mipmap.internalOffset = (uint)textureData.Position;
                    textureData.Skip(mipmap.uncompressedSize);
                }
                if (mipmap.storageType == StorageTypes.pccLZO ||
                    mipmap.storageType == StorageTypes.pccZlib)
                {
                    mipmap.internalOffset = (uint)textureData.Position;
                    textureData.Skip(mipmap.compressedSize);
                }

                mipmap.width  = textureData.ReadInt32();
                mipmap.height = textureData.ReadInt32();

                if (fixDim)
                {
                    if (mipmap.width == 4 && mipMapsList.Exists(mip => mip.width == mipmap.width))
                    {
                        mipmap.width = mipMapsList.Last().width / 2;
                    }
                    if (mipmap.height == 4 && mipMapsList.Exists(mip => mip.height == mipmap.height))
                    {
                        mipmap.height = mipMapsList.Last().height / 2;
                    }

                    if (mipmap.width == 0)
                    {
                        mipmap.width = 1;
                    }
                    if (mipmap.height == 0)
                    {
                        mipmap.height = 1;
                    }
                }

                mipMapsList.Add(mipmap);
            }

            restOfData = textureData.ReadToBuffer(textureData.Length - textureData.Position);
        }
Пример #11
0
        public byte[] getMipMapData(MipMap mipmap)
        {
            switch (mipmap.storageType)
            {
            case StorageTypes.pccUnc:
            {
                textureData.JumpTo(mipmap.internalOffset);
                mipMapData = textureData.ReadToBuffer(mipmap.uncompressedSize);
                break;
            }

            case StorageTypes.pccLZO:
            case StorageTypes.pccZlib:
            {
                textureData.JumpTo(mipmap.internalOffset);
                mipMapData = decompressTexture(textureData, mipmap.storageType, mipmap.uncompressedSize, mipmap.compressedSize);
                break;
            }

            case StorageTypes.extUnc:
            case StorageTypes.extLZO:
            case StorageTypes.extZlib:
            {
                string filename;
                if (GameData.gameType == MeType.ME1_TYPE)
                {
                    filename = GameData.packageFiles.Find(s => Path.GetFileNameWithoutExtension(s).Equals(packageName, StringComparison.OrdinalIgnoreCase));
                }
                else
                {
                    string archive = properties.getProperty("TextureFileCacheName").valueName;
                    filename = Path.Combine(GameData.MainData, archive + ".tfc");
                    if (packagePath.ToLowerInvariant().Contains("\\dlc"))
                    {
                        string DLCArchiveFile = Path.Combine(Path.GetDirectoryName(packagePath), archive + ".tfc");
                        if (File.Exists(DLCArchiveFile))
                        {
                            filename = DLCArchiveFile;
                        }
                        else if (!File.Exists(filename))
                        {
                            List <string> files = Directory.GetFiles(GameData.bioGamePath, archive + ".tfc",
                                                                     SearchOption.AllDirectories).Where(item => item.EndsWith(".tfc", StringComparison.OrdinalIgnoreCase)).ToList();
                            if (files.Count == 0)
                            {
                                filename = Path.Combine(GameData.MainData, "Textures.tfc");
                            }
                            else if (files.Count == 1)
                            {
                                filename = files[0];
                            }
                            else
                            {
                                throw new Exception("");
                            }
                        }
                    }
                }

                try
                {
                    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
                    {
                        try
                        {
                            fs.JumpTo(mipmap.dataOffset);
                            if (mipmap.storageType == StorageTypes.extLZO || mipmap.storageType == StorageTypes.extZlib)
                            {
                                using (MemoryStream tmpStream = new MemoryStream(fs.ReadToBuffer(mipmap.compressedSize)))
                                {
                                    mipMapData = decompressTexture(tmpStream, mipmap.storageType, mipmap.uncompressedSize, mipmap.compressedSize);
                                }
                            }
                            else
                            {
                                mipMapData = fs.ReadToBuffer(mipmap.uncompressedSize);
                            }
                        }
                        catch
                        {
                            return(null);
                        }
                    }
                }
                catch
                {
                    throw new Exception("Problem with access to file: " + filename);
                }
                break;
            }
            }
            return(mipMapData);
        }
        private void LoadImageBMP(MemoryStream stream, ImageFormat format)
        {
            ushort tag = stream.ReadUInt16();

            if (tag != BMP_TAG)
            {
                throw new Exception("not BMP header");
            }

            stream.Skip(8);

            uint offsetData = stream.ReadUInt32();
            int  headerSize = stream.ReadInt32();

            int  imageWidth  = stream.ReadInt32();
            int  imageHeight = stream.ReadInt32();
            bool downToTop   = true;

            if (imageHeight < 0)
            {
                imageHeight = -imageHeight;
                downToTop   = false;
            }
            if (!checkPowerOfTwo(imageWidth) ||
                !checkPowerOfTwo(imageHeight))
            {
                throw new Exception("dimensions not power of two");
            }

            stream.Skip(2);

            int bits = stream.ReadUInt16();

            if (bits != 32 && bits != 24)
            {
                throw new Exception("only 24 and 32 bits BMP supported!");
            }

            bool hasAlphaMask = false;
            uint Rmask = 0xFF0000, Gmask = 0xFF00, Bmask = 0xFF, Amask = 0xFF000000;
            int  Rshift, Gshift, Bshift, Ashift;

            if (headerSize >= 40)
            {
                int compression = stream.ReadInt32();
                if (compression == 1 || compression == 2)
                {
                    throw new Exception("compression not supported in BMP!");
                }

                if (compression == 3)
                {
                    stream.Skip(20);
                    Rmask = stream.ReadUInt32();
                    Gmask = stream.ReadUInt32();
                    Bmask = stream.ReadUInt32();
                    if (headerSize >= 56)
                    {
                        Amask        = stream.ReadUInt32();
                        hasAlphaMask = true;
                    }
                }

                stream.JumpTo(headerSize + 14);
            }

            Rshift = getShiftFromMask(Rmask);
            Gshift = getShiftFromMask(Gmask);
            Bshift = getShiftFromMask(Bmask);
            Ashift = getShiftFromMask(Amask);

            byte[] buffer = new byte[imageWidth * imageHeight * 4];
            int    pos    = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0;
            int    delta  = downToTop ? -imageWidth * 4 * 2 : 0;

            for (int h = 0; h < imageHeight; h++)
            {
                for (int i = 0; i < imageWidth; i++)
                {
                    if (bits == 24)
                    {
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = (byte)stream.ReadByte();
                        buffer[pos++] = 255;
                    }
                    else if (bits == 32)
                    {
                        uint p1    = (uint)stream.ReadByte();
                        uint p2    = (uint)stream.ReadByte();
                        uint p3    = (uint)stream.ReadByte();
                        uint p4    = (uint)stream.ReadByte();
                        uint pixel = p4 << 24 | p3 << 16 | p2 << 8 | p1;
                        buffer[pos++] = (byte)((pixel & Bmask) >> Bshift);
                        buffer[pos++] = (byte)((pixel & Gmask) >> Gshift);
                        buffer[pos++] = (byte)((pixel & Rmask) >> Rshift);
                        buffer[pos++] = (byte)((pixel & Amask) >> Ashift);
                    }
                }
                if (imageWidth % 4 != 0)
                {
                    stream.Skip(4 - (imageWidth % 4));
                }
                pos += delta;
            }

            if (bits == 32 && !hasAlphaMask)
            {
                bool hasAlpha = false;
                for (int i = 0; i < imageWidth * imageHeight; i++)
                {
                    if (buffer[4 * i + 3] != 0)
                    {
                        hasAlpha = true;
                        break;
                    }
                }

                if (!hasAlpha)
                {
                    for (int i = 0; i < imageWidth * imageHeight; i++)
                    {
                        buffer[4 * i + 3] = 255;
                    }
                }
            }

            pixelFormat = PixelFormat.ARGB;
            MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB);

            mipMaps.Add(mipmap);
        }
Пример #13
0
        public void correctMips(PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128)
        {
            byte[] tempData;

            if (pixelFormat != PixelFormat.ARGB)
            {
                tempData = convertRawToARGB(mipMaps[0].data, mipMaps[0].width, mipMaps[0].height, pixelFormat);
            }
            else
            {
                tempData = mipMaps[0].data;
            }

            int width  = mipMaps[0].origWidth;
            int height = mipMaps[0].origHeight;

            if (mipMaps.Count > 1)
            {
                mipMaps.RemoveRange(1, mipMaps.Count - 1);
            }

            if (dstFormat != pixelFormat || (dstFormat == PixelFormat.DXT1 && !dxt1HasAlpha))
            {
                byte[] top = convertToFormat(PixelFormat.ARGB, tempData, width, height, dstFormat, dxt1HasAlpha, dxt1Threshold);
                mipMaps.RemoveAt(0);
                mipMaps.Add(new MipMap(top, width, height, dstFormat));
                pixelFormat = dstFormat;
            }

            int prevW, prevH;
            int origW = width;
            int origH = height;

            for (;;)
            {
                prevW   = width;
                prevH   = height;
                origW >>= 1;
                origH >>= 1;
                if (origW == 0 && origH == 0)
                {
                    break;
                }
                if (origW == 0)
                {
                    origW = 1;
                }
                if (origH == 0)
                {
                    origH = 1;
                }
                width  = origW;
                height = origH;

                if (pixelFormat == PixelFormat.ATI2 && (width < 4 || height < 4))
                {
                    tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)];
                    mipMaps.Add(new MipMap(tempData, width, height, pixelFormat));
                    continue;
                }

                if (pixelFormat == PixelFormat.DXT1 ||
                    pixelFormat == PixelFormat.DXT3 ||
                    pixelFormat == PixelFormat.DXT5)
                {
                    if (width < 4 || height < 4)
                    {
                        if (width < 4)
                        {
                            width = 4;
                        }
                        if (height < 4)
                        {
                            height = 4;
                        }
                        tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)];
                        mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
                        continue;
                    }
                }

                tempData = downscaleARGB(tempData, prevW, prevH);
                if (pixelFormat != PixelFormat.ARGB)
                {
                    byte[] converted = convertToFormat(PixelFormat.ARGB, tempData, origW, origH, pixelFormat, dxt1HasAlpha, dxt1Threshold);
                    mipMaps.Add(new MipMap(converted, origW, origH, pixelFormat));
                }
                else
                {
                    mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
                }
            }
        }
Пример #14
0
        private void LoadImageDDS(MemoryStream stream, ImageFormat format)
        {
            if (stream.ReadUInt32() != DDS_TAG)
            {
                throw new Exception("not DDS tag");
            }

            if (stream.ReadInt32() != DDS_HEADER_dwSize)
            {
                throw new Exception("wrong DDS header dwSize");
            }

            DDSflags = stream.ReadUInt32();

            int dwHeight = stream.ReadInt32();
            int dwWidth  = stream.ReadInt32();

            if (!checkPowerOfTwo(dwWidth) ||
                !checkPowerOfTwo(dwHeight))
            {
                throw new Exception("dimensions not power of two");
            }

            stream.Skip(8); // dwPitchOrLinearSize, dwDepth

            int dwMipMapCount = stream.ReadInt32();

            if (dwMipMapCount == 0)
            {
                dwMipMapCount = 1;
            }

            stream.Skip(11 * 4); // dwReserved1
            stream.SkipInt32();  // ppf.dwSize

            ddsPixelFormat.flags  = stream.ReadUInt32();
            ddsPixelFormat.fourCC = stream.ReadUInt32();
            if ((ddsPixelFormat.flags & DDPF_FOURCC) != 0 && ddsPixelFormat.fourCC == FOURCC_DX10_TAG)
            {
                throw new Exception("DX10 DDS format not supported");
            }

            ddsPixelFormat.bits  = stream.ReadUInt32();
            ddsPixelFormat.Rmask = stream.ReadUInt32();
            ddsPixelFormat.Gmask = stream.ReadUInt32();
            ddsPixelFormat.Bmask = stream.ReadUInt32();
            ddsPixelFormat.Amask = stream.ReadUInt32();

            switch (ddsPixelFormat.fourCC)
            {
            case 0:
                if (ddsPixelFormat.bits == 32 &&
                    (ddsPixelFormat.flags & DDPF_ALPHAPIXELS) != 0 &&
                    ddsPixelFormat.Rmask == 0xFF0000 &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0xFF &&
                    ddsPixelFormat.Amask == 0xFF000000)
                {
                    pixelFormat = PixelFormat.ARGB;
                    break;
                }
                if (ddsPixelFormat.bits == 24 &&
                    ddsPixelFormat.Rmask == 0xFF0000 &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0xFF)
                {
                    pixelFormat = PixelFormat.RGB;
                    break;
                }
                if (ddsPixelFormat.bits == 16 &&
                    ddsPixelFormat.Rmask == 0xFF &&
                    ddsPixelFormat.Gmask == 0xFF00 &&
                    ddsPixelFormat.Bmask == 0x00)
                {
                    pixelFormat = PixelFormat.V8U8;
                    break;
                }
                if (ddsPixelFormat.bits == 8 &&
                    ddsPixelFormat.Rmask == 0xFF &&
                    ddsPixelFormat.Gmask == 0x00 &&
                    ddsPixelFormat.Bmask == 0x00)
                {
                    pixelFormat = PixelFormat.G8;
                    break;
                }
                throw new Exception("Not supported DDS format");

            case 21:
                pixelFormat = PixelFormat.ARGB;
                break;

            case 20:
                pixelFormat = PixelFormat.RGB;
                break;

            case 60:
                pixelFormat = PixelFormat.V8U8;
                break;

            case 50:
                pixelFormat = PixelFormat.G8;
                break;

            case FOURCC_DXT1_TAG:
                pixelFormat = PixelFormat.DXT1;
                break;

            case FOURCC_DXT3_TAG:
                pixelFormat = PixelFormat.DXT3;
                break;

            case FOURCC_DXT5_TAG:
                pixelFormat = PixelFormat.DXT5;
                break;

            case FOURCC_ATI2_TAG:
                pixelFormat = PixelFormat.ATI2;
                break;

            default:
                throw new Exception("Not supported DDS format");
            }
            stream.Skip(5 * 4); // dwCaps, dwCaps2, dwCaps3, dwCaps4, dwReserved2

            byte[] tempData;
            for (int i = 0; i < dwMipMapCount; i++)
            {
                int w     = dwWidth >> i;
                int h     = dwHeight >> i;
                int origW = w;
                int origH = h;
                if (origW == 0 && origH != 0)
                {
                    origW = 1;
                }
                if (origH == 0 && origW != 0)
                {
                    origH = 1;
                }
                w = origW;
                h = origH;

                if (pixelFormat == PixelFormat.DXT1 ||
                    pixelFormat == PixelFormat.DXT3 ||
                    pixelFormat == PixelFormat.DXT5)
                {
                    if (w < 4)
                    {
                        w = 4;
                    }
                    if (h < 4)
                    {
                        h = 4;
                    }
                }

                try
                {
                    tempData = stream.ReadToBuffer(MipMap.getBufferSize(w, h, pixelFormat));
                }
                catch
                {
                    throw new Exception("not enough data in stream");
                }

                mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat));
            }
        }
Пример #15
0
        public Texture(Package package, int exportId, byte[] data, bool fixDim = true)
        {
            properties = new TexProperty(package, data);
            if (data.Length == properties.propertyEndOffset)
            {
                return;
            }

            textureData = new MemoryStream(data, properties.propertyEndOffset, data.Length - properties.propertyEndOffset);
            if (GameData.gameType != MeType.ME3_TYPE)
            {
                textureData.Skip(12);    // 12 zeros
                textureData.SkipInt32(); // position in the package
            }

            mipMapsList = new List <MipMap>();
            int numMipMaps = textureData.ReadInt32();

            for (int l = 0; l < numMipMaps; l++)
            {
                MipMap mipmap = new MipMap();
                mipmap.storageType      = (StorageTypes)textureData.ReadInt32();
                mipmap.uncompressedSize = textureData.ReadInt32();
                mipmap.compressedSize   = textureData.ReadInt32();
                mipmap.dataOffset       = textureData.ReadUInt32();
                if (mipmap.storageType == StorageTypes.pccUnc)
                {
                    mipmap.internalOffset = (uint)textureData.Position;
                    textureData.Skip(mipmap.uncompressedSize);
                }
                if (mipmap.storageType == StorageTypes.pccLZO ||
                    mipmap.storageType == StorageTypes.pccZlib)
                {
                    mipmap.internalOffset = (uint)textureData.Position;
                    textureData.Skip(mipmap.compressedSize);
                }

                mipmap.width  = textureData.ReadInt32();
                mipmap.height = textureData.ReadInt32();

                if (fixDim)
                {
                    if (mipmap.width == 4 && mipMapsList.Exists(mip => mip.width == mipmap.width))
                    {
                        mipmap.width = mipMapsList.Last().width / 2;
                    }
                    if (mipmap.height == 4 && mipMapsList.Exists(mip => mip.height == mipmap.height))
                    {
                        mipmap.height = mipMapsList.Last().height / 2;
                    }

                    if (mipmap.width == 0)
                    {
                        mipmap.width = 1;
                    }
                    if (mipmap.height == 0)
                    {
                        mipmap.height = 1;
                    }
                }

                mipMapsList.Add(mipmap);
            }

            restOfData = textureData.ReadToBuffer(textureData.Length - textureData.Position);

            packagePath = package.packagePath;
            packageName = Path.GetFileNameWithoutExtension(packagePath).ToUpper();
            if (GameData.gameType == MeType.ME1_TYPE)
            {
                string baseName = package.resolvePackagePath(package.exportsTable[exportId].linkId).Split('.')[0].ToUpper();
                if (mipMapsList.Exists(s => s.storageType == StorageTypes.extLZO) ||
                    mipMapsList.Exists(s => s.storageType == StorageTypes.extZlib) ||
                    mipMapsList.Exists(s => s.storageType == StorageTypes.extUnc))
                {
                    basePackageName = baseName;
                    if (basePackageName == "")
                    {
                        throw new Exception("");
                    }
                    slave = true;
                }
                else
                {
                    if (baseName != "" && !properties.exists("NeverStream") &&
                        GameData.packageFiles.Exists(s => Path.GetFileNameWithoutExtension(s).Equals(baseName, StringComparison.OrdinalIgnoreCase)))
                    {
                        basePackageName = baseName;
                        weakSlave       = true;
                    }
                }
            }
        }