public void Save(Stream file) { int width = (Image.Width + 0x7) & ~0x7; int height = (Image.Height + 0x7) & ~0x7; var settings = new ImageSettings(Support.Format[header.imageFormat], width, height) { Swizzle = new ImgcSwizzle(width, height) }; byte[] pic = Kolors.Save(Image, settings); using (var bw = new BinaryWriterX(file, true)) { //Header header.width = (short)Image.Width; header.height = (short)Image.Height; //tile table var table = new MemoryStream(); byte[] importPic = Deflate(pic, Support.Format[header.imageFormat].BitDepth, out table); //Table bw.BaseStream.Position = 0x48; var comp = Compressor.Compress(table, tableComp); bw.Write(comp); header.tableSize1 = comp.Length; header.tableSize2 = (header.tableSize1 + 3) & ~3; //Image bw.BaseStream.Position = 0x48 + header.tableSize2; header.imageFormat = (editMode) ? (byte)28 : header.imageFormat; comp = Compressor.Compress(new MemoryStream(importPic), picComp); bw.Write(comp); bw.WriteAlignment(4); header.imgDataSize = comp.Length; //Header bw.BaseStream.Position = 0; bw.WriteType(header); } }
/// <summary> /// /// </summary> /// <param name="output"></param> public void Save(Stream output) { using (var bw = new BinaryWriterX(output, true)) { // Updates Header.Width = (short)Texture.Width; Header.Height = (short)Texture.Height; // Header bw.WriteType(Header); bw.WriteAlignment(); bw.WriteString(FileName, Encoding.ASCII, false); bw.WriteAlignment(); // Setup if (Header.Format == ImageFormat.Palette_8) { var settings = new IndexedImageSettings(IndexEncodings[(int)Header.Format], PaletteEncodings[(int)Header.Format], Header.Width, Header.Height) { QuantizationSettings = new QuantizationSettings(new WuColorQuantizer(6, 3), Header.Width, Header.Height) { ColorCount = 256, ParallelCount = 8 } }; var data = Kolors.Save(Texture, settings); bw.Write(data.indexData); bw.Write(data.paletteData); } else { var settings = new ImageSettings(Encodings[(int)Header.Format], Header.Width, Header.Height); var data = Kolors.Save(Texture, settings); bw.Write(data); } } }
public void Save(Stream output) { using (var bw = new BinaryWriterX(output, ByteOrder)) { if (SwitchUnknownData != null) { HeaderInfo.MipMapCount--; } Header.Block1 = (uint)((int)HeaderInfo.Version | (HeaderInfo.Unknown1 << 12) | (HeaderInfo.Unused1 << 24) | ((int)HeaderInfo.AlphaChannelFlags << 28)); Header.Block2 = (uint)(HeaderInfo.MipMapCount | (HeaderInfo.Width << 6) | (HeaderInfo.Height << 19)); Header.Block3 = (uint)(HeaderInfo.Unknown2 | ((int)HeaderInfo.Format << 8) | (HeaderInfo.Unknown3 << 16)); bw.WriteType(Header); if (HeaderInfo.Version == Version._Switchv1 && SwitchUnknownData != null) { bw.Write(SwitchUnknownData); } //var format = HeaderInfo.Format.ToString().StartsWith("DXT1") ? Format.DXT1 : HeaderInfo.Format.ToString().StartsWith("DXT5") ? Format.DXT5 : HeaderInfo.Format; var encoding = (HeaderInfo.Version == Version._Switchv1) ? SwitchFormats[HeaderInfo.Format] : Formats[HeaderInfo.Format]; // Mipmap Downsampling if (Bitmaps.Count > 1 && HeaderInfo.MipMapCount > 1) { var firstBitmap = Bitmaps[0].Image; var width = firstBitmap.Width; var height = firstBitmap.Height; for (var i = 0; i < HeaderInfo.MipMapCount - 1; i++) { var bmp = new Bitmap(width / 2, height / 2); var gfx = Graphics.FromImage(bmp); gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; gfx.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; gfx.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; gfx.DrawImage(firstBitmap, new Rectangle(0, 0, bmp.Width, bmp.Height)); Bitmaps[0].MipMaps[i] = bmp; width = bmp.Width; height = bmp.Height; } } var bitmaps = new List <byte[]>(); Settings = new ImageSettings(encoding, Bitmaps[0].Image.Width, Bitmaps[0].Image.Height); //Set possible Swizzles if (HeaderInfo.Version == Version._3DSv1 || HeaderInfo.Version == Version._3DSv2 || HeaderInfo.Version == Version._3DSv3) { Settings.Swizzle = new CTRSwizzle(Bitmaps[0].Image.Width, Bitmaps[0].Image.Height, CtrTransformation.None, true); } else if (HeaderInfo.Version == Version._Switchv1) { Settings.Swizzle = new SwitchSwizzle(Bitmaps[0].Image.Width, Bitmaps[0].Image.Height, Settings.Encoding.BitDepth, GetSwitchSwizzleFormat(Settings.Encoding.FormatName), true); //Switch Swizzle } else if (Settings.Encoding.FormatName.Contains("DXT")) { Settings.Swizzle = new BCSwizzle(Bitmaps[0].Image.Width, Bitmaps[0].Image.Height); } if ((Format)HeaderInfo.Format == Format.DXT5_B) { Settings.PixelShader = ToNoAlpha; } else if ((Format)HeaderInfo.Format == Format.DXT5_YCbCr) { Settings.PixelShader = ToOptimisedColors; } bitmaps.Add(Kolors.Save(Bitmaps[0].Image, Settings)); foreach (var mipmap in Bitmaps[0].MipMaps) { Settings = new ImageSettings(encoding, Bitmaps[0].Image.Width, Bitmaps[0].Image.Height); //Set possible Swizzles if (HeaderInfo.Version == Version._3DSv1 || HeaderInfo.Version == Version._3DSv2 || HeaderInfo.Version == Version._3DSv3) { Settings.Swizzle = new CTRSwizzle(mipmap.Width, mipmap.Height, CtrTransformation.None, true); } else if (HeaderInfo.Version == Version._Switchv1) { Settings.Swizzle = new SwitchSwizzle(mipmap.Width, mipmap.Height, Settings.Encoding.BitDepth, GetSwitchSwizzleFormat(Settings.Encoding.FormatName), true); //Switch Swizzle } else if (Settings.Encoding.FormatName.Contains("DXT")) { Settings.Swizzle = new BCSwizzle(mipmap.Width, mipmap.Height); } if ((Format)HeaderInfo.Format == Format.DXT5_B) { Settings.PixelShader = ToNoAlpha; } else if ((Format)HeaderInfo.Format == Format.DXT5_YCbCr) { Settings.PixelShader = ToOptimisedColors; } bitmaps.Add(Kolors.Save(mipmap, Settings)); } if (HeaderInfo.Version == Version._Switchv1) { if (SwitchUnknownData != null) { var listOffset = bw.BaseStream.Position; bw.BaseStream.Position += 8 + HeaderInfo.MipMapCount * sizeof(int); var offsets = new List <int>(); var relOffset = bw.BaseStream.Position; foreach (var bitmap in bitmaps) { var data = new byte[(bitmap.Length + 0x1FF) & ~0x1FF]; Array.Copy(bitmap, data, bitmap.Length); bw.Write(data); offsets.Add((int)(bw.BaseStream.Position - relOffset)); } offsets[offsets.Count - 1] = (offsets.Last() + 0x7FF) & ~0x7FF; bw.BaseStream.Position = relOffset + offsets.Last(); bw.Write(SwitchOverflowingData); var totalSize = bw.BaseStream.Position - 0x84 - HeaderInfo.MipMapCount * sizeof(int); bw.BaseStream.Position = listOffset; bw.Write((int)totalSize); bw.BaseStream.Position += 4; foreach (var offset in offsets) { bw.Write(offset); } } else { bw.BaseStream.Position += 0x4 + HeaderInfo.MipMapCount * sizeof(int); var offsets = new List <int>(); var relOffset = bw.BaseStream.Position; foreach (var bitmap in bitmaps) { offsets.Add((int)(bw.BaseStream.Position - relOffset)); var data = new byte[(bitmap.Length + 0x1FF) & ~0x1FF]; Array.Copy(bitmap, data, bitmap.Length); bw.Write(data); } var totalSize = bw.BaseStream.Position - (0x10 + 0x4 + HeaderInfo.MipMapCount * sizeof(int)); bw.BaseStream.Position = 0x10; bw.Write((int)totalSize); foreach (var offset in offsets) { bw.Write(offset); } } } else // Mipmaps, but not for Version 3DS v1 if (HeaderInfo.Version != Version._3DSv1) { var offset = HeaderInfo.Version == Version._PS3v1 ? HeaderInfo.MipMapCount * sizeof(int) + HeaderLength : 0; foreach (var bitmap in bitmaps) { bw.Write(offset); offset += bitmap.Length; } } // Bitmaps if (SwitchUnknownData == null) { foreach (var bitmap in bitmaps) { bw.Write(bitmap); } } } }