public static Bitmap DecompressBC1(ReadOnlySpan <byte> data, int width, int height, bool IsSRGB) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 8; byte[] Tile = BCnDecodeTile(data, IOffs, true); int TOffset = 0; for (int TY = 0; TY < 4; TY++) { for (int TX = 0; TX < 4; TX++) { int OOffset = (X * 4 + TX + (Y * 4 + TY) * W * 4) * 4; Output[OOffset + 0] = Tile[TOffset + 0]; Output[OOffset + 1] = Tile[TOffset + 1]; Output[OOffset + 2] = Tile[TOffset + 2]; Output[OOffset + 3] = Tile[TOffset + 3]; TOffset += 4; } } } } return(BitmapExporter.GetBitmapFromBytes(Output, W * 4, H * 4)); }
static void SaveTextures(CommandLineOptions options) { var files = options.InputPaths.SelectMany(path => { if (File.Exists(path)) { return new[] { path } } ; if (Directory.Exists(path)) { return(DirectoryHelper.EnumerateFilesWithRegex(path, options.Regex, SearchOption.AllDirectories)); } return(new string[] { }); }); var textureCount = 0; var timer = new Stopwatch(); timer.Start(); Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = options.Threads }, f => { var texture = TextureLoader.DecompressAndLoadFile(f); var basename = Path.GetFileName(f); if (texture == null) { return; } try { string path = GenerateFileName(f, texture.Name, options); string name = Path.GetFileName(path); if (!File.Exists(path) || options.ForceOverwrite) { BitmapExporter.SaveBitmap(texture, path, options.CropTextures); Console.WriteLine($"[OUT] {basename} -> {name} ({texture.Format})"); } else { Console.WriteLine($"[DUPE] {basename} -> {name} ({texture.Format})"); } Interlocked.Increment(ref textureCount); } catch (Exception e) { Console.WriteLine($"[ERR] {basename} - texture ({texture.Format} failed to load ({e.Message})"); } }); timer.Stop(); Console.WriteLine($"Saved {textureCount} textures"); Console.WriteLine($"Took {timer.ElapsedMilliseconds}ms"); }
public static Bitmap DecompressBC3(ReadOnlySpan <byte> data, int width, int height, bool IsSRGB) { int W = (width + 3) / 4; int H = (height + 3) / 4; byte[] Output = new byte[W * H * 64]; for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { int IOffs = (Y * W + X) * 16; byte[] Tile = BCnDecodeTile(data, IOffs + 8, false); byte[] Alpha = new byte[8]; Alpha[0] = data[IOffs + 0]; Alpha[1] = data[IOffs + 1]; CalculateBC3Alpha(Alpha); int AlphaLow = data.GetInt32(IOffs + 2); int AlphaHigh = data.GetUInt16(IOffs + 6); ulong AlphaCh = (uint)AlphaLow | (ulong)AlphaHigh << 32; int TOffset = 0; for (int TY = 0; TY < 4; TY++) { for (int TX = 0; TX < 4; TX++) { int OOffset = (X * 4 + TX + (Y * 4 + TY) * W * 4) * 4; byte AlphaPx = Alpha[(AlphaCh >> (TY * 12 + TX * 3)) & 7]; Output[OOffset + 0] = Tile[TOffset + 0]; Output[OOffset + 1] = Tile[TOffset + 1]; Output[OOffset + 2] = Tile[TOffset + 2]; Output[OOffset + 3] = AlphaPx; TOffset += 4; } } } } return(BitmapExporter.GetBitmapFromBytes(Output, W * 4, H * 4)); }