public DDS(D3DFormat Format, Bitmap bitmap) { SquishFlags flags = SquishFlags.kDxt1; bool bCompressed = true; switch (Format) { case D3DFormat.DXT1: flags = SquishFlags.kDxt1; break; case D3DFormat.DXT3: flags = SquishFlags.kDxt3; break; case D3DFormat.DXT5: flags = SquishFlags.kDxt5; break; default: bCompressed = false; break; } format = Format; width = bitmap.Width; height = bitmap.Height; var mip = new MipMap(); mip.Width = width; mip.Height = height; byte[] data = new byte[mip.Width * mip.Height * 4]; BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, mip.Width, mip.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); Marshal.Copy(bmpdata.Scan0, data, 0, bmpdata.Stride * bmpdata.Height); bitmap.UnlockBits(bmpdata); if (bCompressed) { for (uint i = 0; i < data.Length - 4; i += 4) { byte r = data[i + 0]; data[i + 0] = data[i + 2]; data[i + 2] = r; } byte[] dest = new byte[Squish.Squish.GetStorageRequirements(mip.Width, mip.Height, flags | SquishFlags.kColourIterativeClusterFit)]; Squish.Squish.CompressImage(data, mip.Width, mip.Height, ref dest, flags | SquishFlags.kColourIterativeClusterFit); mip.Data = dest; } else { mip.Data = data; } mipMaps.Add(mip); }
public static DDS Load(byte[] data) { DDS dds = new DDS(); using (MemoryStream ms = new MemoryStream(data)) using (BinaryReader br = new BinaryReader(ms)) { if (!IsDDS(br)) { return null; } dds.pixelFormat = new DDSPixelFormat(); br.ReadUInt32(); // header length dds.flags = (Flags)br.ReadUInt32(); dds.height = (int)br.ReadUInt32(); dds.width = (int)br.ReadUInt32(); dds.pitch = (int)br.ReadUInt32(); dds.depth = (int)br.ReadUInt32(); int mipCount = (int)br.ReadUInt32(); for (int i = 0; i < 11; i++) { br.ReadUInt32(); } br.ReadUInt32(); // pixel format length dds.pixelFormat.Flags = (PixelFormatFlags)br.ReadUInt32(); dds.pixelFormat.FourCC = (PixelFormatFourCC)br.ReadUInt32(); dds.pixelFormat.RGBBitCount = (int)br.ReadUInt32(); dds.pixelFormat.RBitMask = br.ReadUInt32(); dds.pixelFormat.GBitMask = br.ReadUInt32(); dds.pixelFormat.BBitMask = br.ReadUInt32(); dds.pixelFormat.ABitMask = br.ReadUInt32(); dds.caps = (DDSCaps)br.ReadUInt32(); dds.caps2 = (DDSCaps2)br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); br.ReadUInt32(); if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_FOURCC)) { dds.format = (D3DFormat)dds.pixelFormat.FourCC; } else if (dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_RGB) & dds.pixelFormat.Flags.HasFlag(PixelFormatFlags.DDPF_ALPHAPIXELS)) { dds.format = D3DFormat.A8R8G8B8; } for (int i = 0; i < Math.Max(1, mipCount); i++) { var mip = new MipMap { Width = dds.width >> i, Height = dds.height >> i }; switch (dds.format) { case D3DFormat.A8R8G8B8: mip.Data = br.ReadBytes(mip.Width * mip.Height * 4); break; case D3DFormat.DXT1: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 8); break; case D3DFormat.DXT3: case D3DFormat.DXT5: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 16); break; } dds.mipMaps.Add(mip); } } return dds; }
public static XT2 Load(string Path) { FileInfo fi = new FileInfo(Path); Console.WriteLine("{0}", Path); XT2 xt2 = new XT2(); xt2.Name = fi.Name.Replace(fi.Extension, ""); using (BEBinaryReader br = new BEBinaryReader(fi.OpenRead())) { Console.WriteLine("Always 0 : {0}", br.ReadUInt32()); int magic = (int)br.ReadUInt32(); xt2.dataSize = (int)br.ReadUInt32(); Console.WriteLine("Always 52 : {0}", br.ReadUInt32()); Console.WriteLine("Always 0 : {0}", br.ReadUInt16()); xt2.width = br.ReadUInt16(); xt2.height = br.ReadUInt16(); Console.WriteLine("{0} {1}", br.ReadUInt16(), br.ReadUInt16()); xt2.header = new D3DBaseTexture(br); Console.WriteLine("{0}x{1} :: {2} :: {3} :: {4} :: {5}", xt2.width, xt2.height, xt2.header.DataFormat, xt2.header.Endian, xt2.dataSize, magic); int W = 0; int H = 0; int TexelPitch = 0; int DataSize = 0; int OutSize = 0; int w = xt2.width; int h = xt2.height; switch (xt2.header.DataFormat) { case D3DFormat.X360_A8R8G8B8: W = w; H = h; TexelPitch = 4; DataSize = w * h * 4; break; case D3DFormat.X360_DXT1: W = w / 4; H = h / 4; TexelPitch = 8; DataSize = w * h / 2; break; case D3DFormat.X360_DXT2: W = w / 4; H = h / 4; TexelPitch = 16; DataSize = W * H; break; } if (H % 128 != 0) { H = H + (128 - H % 128); } switch (xt2.header.DataFormat) { case D3DFormat.X360_A8R8G8B8: OutSize = W * H * TexelPitch; break; case D3DFormat.X360_DXT1: OutSize = W * H * TexelPitch; break; case D3DFormat.X360_DXT2: DataSize = w * H * 2; OutSize = W * H * TexelPitch; break; } byte[] data = new byte[DataSize]; byte[] outdata = new byte[OutSize]; Array.Copy(br.ReadBytes(DataSize), data, DataSize); int step = (xt2.header.Endian == 1 ? 2 : 4); for (int i = 0; i < data.Length; i += step) { for (int j = 0; j < step / 2; j++) { byte tmp = data[i + j]; data[i + j] = data[i + step - j - 1]; data[i + step - j - 1] = tmp; } } for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { int offset = Xbox360ConvertTextureAddress(x, y, W, TexelPitch); if (offset * TexelPitch < data.Length) { Array.Copy(data, offset * TexelPitch, outdata, (x + y * W) * TexelPitch, TexelPitch); } } } var mip = new MipMap(); mip.Width = xt2.width; mip.Height = xt2.height; mip.Data = data; xt2.MipMaps.Add(mip); } return xt2; }
public byte[] Decompress(MipMap mip, bool bSuppressAlpha = false) { SquishFlags flags = 0; bool bNotCompressed = false; bool ATI2 = false; switch (this.Format) { case D3DFormat.DXT1: flags = SquishFlags.kDxt1; break; case D3DFormat.DXT5: flags = SquishFlags.kDxt5; break; case D3DFormat.A8R8G8B8: bNotCompressed = true; break; case D3DFormat.ATI2: ATI2 = true; break; default: throw new NotImplementedException(string.Format("Can't decompress: {0}", this.Format)); } byte[] dest = new byte[mip.Width * mip.Height * 4]; byte[] data = mip.Data; if (bNotCompressed) { for (uint i = 0; i < data.Length - 4; i += 4) { dest[i + 0] = data[i + 2]; dest[i + 1] = data[i + 1]; dest[i + 2] = data[i + 0]; dest[i + 3] = data[i + 3]; } } else if (ATI2) { return DecompressATI2(data, (uint)mip.Width, (uint)mip.Height, !bSuppressAlpha); } else { Squish.Squish.DecompressImage(dest, mip.Width, mip.Height, ref data, flags); for (uint i = 0; i < dest.Length - 4; i += 4) { byte r = dest[i + 0]; dest[i + 0] = dest[i + 2]; dest[i + 2] = r; } } return dest; }
public static TDX LoadFromBitmap(Bitmap asset, string name, D3DFormat format) { TDX tdx = null; if (tdx == null) { tdx = new TDX(); var b = asset; var flags = Squish.SquishFlags.kDxt1; tdx.Name = name; tdx.Format = format; switch (tdx.Format) { case D3DFormat.DXT1: flags = Squish.SquishFlags.kDxt1; break; case D3DFormat.DXT5: flags = Squish.SquishFlags.kDxt5; break; } var mipBitmaps = GenerateMips(b, b.Width, b.Height); foreach (var mb in mipBitmaps) { var mip = new MipMap(); mip.Width = mb.Width; mip.Height = mb.Height; byte[] data = new byte[mb.Width * mb.Height * 4]; byte[] dest = new byte[Squish.Squish.GetStorageRequirements(mb.Width, mb.Height, flags | Squish.SquishFlags.kColourIterativeClusterFit | Squish.SquishFlags.kWeightColourByAlpha)]; int ii = 0; for (int y = 0; y < mb.Height; y++) { for (int x = 0; x < mb.Width; x++) { var p = mb.GetPixel(x, y); data[ii + 0] = p.R; data[ii + 1] = p.G; data[ii + 2] = p.B; data[ii + 3] = p.A; ii += 4; } } if (format == D3DFormat.ATI2) dest = BC5Unorm.Compress(data, (ushort)mb.Width, (ushort)mb.Height, GetMipSize(format, (ushort)mb.Width, (ushort)mb.Height)); else Squish.Squish.CompressImage(data, mb.Width, mb.Height, ref dest, flags | Squish.SquishFlags.kColourClusterFit); mip.Data = dest; tdx.MipMaps.Add(mip); } } return tdx; }
public static TDX Load(Stream stream, string name = null) { TDX tdx = new TDX { Name = name }; using (BinaryReader br = new BinaryReader(stream)) { if (br.ReadByte() != 0x00 || br.ReadByte() != 0x02) { Logger.LogToFile(Logger.LogLevel.Error, "This isn't a valid TDX"); return null; } tdx.width = br.ReadUInt16(); tdx.height = br.ReadUInt16(); int mipCount = br.ReadUInt16(); tdx.flags = (Flags)br.ReadUInt32(); tdx.Format = (D3DFormat)br.ReadUInt32(); if (tdx.flags.HasFlag(Flags.ExtraData)) { int extraDataLength = (int)br.ReadUInt32(); int extraDataType = br.ReadUInt16(); switch (extraDataType) { case 0: tdx.extraDataType = ExtraDataTypes.Font; tdx.extraData = new FontDefinition(br.ReadBytes(extraDataLength - 2)); break; case 1: tdx.extraDataType = ExtraDataTypes.Animation; tdx.extraData = new AnimationDefinition(br.ReadBytes(extraDataLength - 2)); break; case 3: tdx.extraDataType = ExtraDataTypes.VTMap; tdx.extraData = new VTMap(br.ReadBytes(extraDataLength - 2)); break; default: throw new NotImplementedException(string.Format("Unknown Extra Data flag: {0}", extraDataType)); } } for (int i = 0; i < mipCount; i++) { var mip = new MipMap(); mip.Width = tdx.width >> i; mip.Height = tdx.height >> i; switch (tdx.Format) { case D3DFormat.A8R8G8B8: mip.Data = br.ReadBytes(mip.Width * mip.Height * 4); break; case D3DFormat.A8: mip.Data = br.ReadBytes(mip.Width * mip.Height); break; case D3DFormat.DXT1: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 8); break; case D3DFormat.ATI2: case D3DFormat.DXT5: mip.Data = br.ReadBytes((((mip.Width + 3) / 4) * ((mip.Height + 3) / 4)) * 16); break; default: Logger.LogToFile(Logger.LogLevel.Error, "Unknown format: {0}", tdx.Format); return null; } tdx.MipMaps.Add(mip); } } return tdx; }