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; } }
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); }
public uint getCrcMipmap(MipMap mipmap) { byte[] data = getMipMapData(mipmap); if (data == null) { return(0); } return(getCrcData(data)); }
public MipMap getTopMipmap() { MipMap mipmap = mipMapsList.Find(b => b.storageType != StorageTypes.empty); if (mipmap.width == 0) { throw new Exception(); } return(mipmap); }
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); }
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()); } }
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); } }
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); }
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(); } }
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); }
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); }
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)); } } }
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)); } }
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; } } } }