public void WriteTo(BinaryWriter writer, ITex tex) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (tex == null) { throw new ArgumentNullException(nameof(tex)); } if (tex.Magic1 != "TEXV0005") { throw new UnknownMagicException(nameof(TexWriter), nameof(tex.Magic1), tex.Magic1); } if (tex.Magic2 != "TEXI0001") { throw new UnknownMagicException(nameof(TexWriter), nameof(tex.Magic2), tex.Magic2); } writer.WriteNString(tex.Magic1); writer.WriteNString(tex.Magic2); _texHeaderWriter.WriteTo(writer, tex.Header); _texImageContainerWriter.WriteTo(writer, tex.ImagesContainer); if (tex.IsGif) { _texFrameInfoContainerWriter.WriteTo(writer, tex.FrameInfoContainer); } }
private void ConvertToImageAndSave(ITex tex, string name) { var resultImage = _texToImageConverter.ConvertToImage(tex); var path = $"{TestHelper.BasePath}\\{OutputDirectoryName}\\{name}.{resultImage.Format.GetFileExtension()}"; File.WriteAllBytes(path, resultImage.Bytes); }
private static ImageResult ConvertToGif(ITex tex) { var frameFormat = tex.FirstImage.FirstMipmap.Format; if (!frameFormat.IsRawFormat()) { throw new InvalidOperationException( "Only raw mipmap formats are supported right now while converting gif"); } var image = ImageFromRawFormat(frameFormat, null, tex.FrameInfoContainer.GifWidth, tex.FrameInfoContainer.GifHeight); var sequenceImages = new Image[tex.ImagesContainer.Images.Count]; for (var i = 0; i < sequenceImages.Length; i++) { var mipmap = tex.ImagesContainer.Images[i].FirstMipmap; sequenceImages[i] = ImageFromRawFormat(frameFormat, mipmap.Bytes, mipmap.Width, mipmap.Height); } foreach (var frameInfo in tex.FrameInfoContainer.Frames) { var frame = sequenceImages[frameInfo.ImageId].Clone( context => context.Crop(new Rectangle( (int)frameInfo.X, (int)frameInfo.Y, (int)frameInfo.Width, (int)frameInfo.Height) ) ); var metadata = frame.Frames.RootFrame.Metadata.GetFormatMetadata(GifFormat.Instance); metadata.FrameDelay = (int)Math.Round(frameInfo.Frametime * 100.0f); image.Frames.AddFrame(frame.Frames[0]); } // Remove first black frame image.Frames.RemoveFrame(0); using (var memoryStream = new MemoryStream()) { image.SaveAsGif(memoryStream, new GifEncoder { ColorTableMode = GifColorTableMode.Local }); return(new ImageResult { Bytes = memoryStream.ToArray(), Format = MipmapFormat.ImageGIF }); } }
internal void SaveTable(string path, ITex data, DataGrid grid) { using (var textTab = new StreamWriter(path)) { foreach (var item in grid.Items) { var obj = (ITex)item; textTab.WriteLine(obj.toTabular()); } } }
public string GenerateFullInfo(ITex tex) { //short helper class to ignore some properties from serialization var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Formatting = Formatting.Indented, ContractResolver = _ignorePropertiesResolver }; return(JsonConvert.SerializeObject(tex, typeof(Tex), settings)); }
private static void ConvertToImageAndSave(ITex tex, string path, bool overwrite) { var format = _texToImageConverter.GetConvertedFormat(tex); var outputPath = $"{path}.{format.GetFileExtension()}"; if (!overwrite && File.Exists(outputPath)) { return; } var resultImage = _texToImageConverter.ConvertToImage(tex); File.WriteAllBytes(outputPath, resultImage.Bytes); }
public ImageResult ConvertToImage(ITex tex) { if (tex == null) { throw new ArgumentNullException(nameof(tex)); } if (tex.IsGif) { return(ConvertToGif(tex)); } var sourceMipmap = tex.FirstImage.FirstMipmap; var format = sourceMipmap.Format; if (format.IsCompressed()) { throw new InvalidOperationException("Raw mipmap format must be uncompressed"); } if (format.IsRawFormat()) { var image = ImageFromRawFormat(format, sourceMipmap.Bytes, sourceMipmap.Width, sourceMipmap.Height); if (sourceMipmap.Width != tex.Header.ImageWidth || sourceMipmap.Height != tex.Header.ImageHeight) { image.Mutate(x => x.Crop(tex.Header.ImageWidth, tex.Header.ImageHeight)); } using (var memoryStream = new MemoryStream()) { image.SaveAsPng(memoryStream); return(new ImageResult { Bytes = memoryStream.ToArray(), Format = MipmapFormat.ImagePNG }); } } return(new ImageResult { Bytes = sourceMipmap.Bytes, Format = format }); }
private static void PackFile() { Directory.CreateDirectory(_options.OutputDirectory); var inputFileInfo = new FileInfo(_options.Input); ITex tex = _imageToTexConverter.LoadFileToTex(inputFileInfo); var outputFilePath = Path.Combine(_options.OutputDirectory, Path.GetFileNameWithoutExtension(inputFileInfo.Name)); using (var stream = File.OpenWrite($"{outputFilePath}.tex")) using (var writer = new BinaryWriter(stream)) { _texWriter.WriteTo(writer, tex); } }
public MipmapFormat GetConvertedFormat(ITex tex) { if (tex == null) { throw new ArgumentNullException(nameof(tex)); } if (tex.IsGif) { return(MipmapFormat.ImageGIF); } var format = tex.FirstImage.FirstMipmap.Format; if (format.IsCompressed()) { throw new InvalidOperationException("Raw mipmap format must be uncompressed"); } return(format.IsRawFormat() ? MipmapFormat.ImagePNG : format); }
public string GenerateInfo(ITex tex) { if (tex == null) { throw new ArgumentNullException(nameof(tex)); } var json = new JObject { ["bleedtransparentcolors"] = true, ["clampuvs"] = tex.HasFlag(TexFlags.ClampUVs), ["format"] = tex.Header.Format.ToString().ToLower(), ["nomip"] = (tex.FirstImage.Mipmaps.Count == 1).ToString().ToLower(), ["nointerpolation"] = tex.HasFlag(TexFlags.NoInterpolation).ToString().ToLower(), ["nonpoweroftwo"] = (!NumberIsPowerOfTwo(tex.Header.ImageWidth) || !NumberIsPowerOfTwo(tex.Header.ImageHeight)).ToString().ToLower() }; if (tex.IsGif) { if (tex.FrameInfoContainer == null) { throw new InvalidOperationException("TEX is animated but doesn't have frame info container"); } json["spritesheetsequences"] = new JArray { new JObject { ["duration"] = 1, // not sure what this value is used for ["frames"] = tex.FrameInfoContainer.Frames.Count, ["width"] = tex.FrameInfoContainer.GifWidth, ["height"] = tex.FrameInfoContainer.GifHeight } }; } return(JsonConvert.SerializeObject(json, Formatting.Indented)); }
private static void ConvertToImageAndSave(ITex tex, string path, bool overwrite) { var format = _texToImageConverter.GetConvertedFormat(tex); int i = 0; foreach (var image in tex.ImagesContainer.Images) { int j = 0; foreach (var mipmap in image.Mipmaps) { var outputPath = $"{path}-im{i}-mipmap{j}.{format.GetFileExtension()}"; if (i == 0 && j == 0) { outputPath = $"{path}.{format.GetFileExtension()}"; } if (!overwrite && File.Exists(outputPath)) { return; } var resultImage = _texToImageConverter.ConvertToImage(tex, mipmap); File.WriteAllBytes(outputPath, resultImage.Bytes); if (!_options.ExtractAllImages) { return; } j++; } i++; } }
public static CTex *ConvertToCTex( this NativeEnvironment e, ITex tex) { // tex var ctex = e.AllocateStruct <CTex>(); ctex->magic1 = e.ToCString(tex.Magic1); ctex->magic2 = e.ToCString(tex.Magic2); // header var header = tex.Header; ctex->header.format = header.Format; ctex->header.flags = header.Flags; ctex->header.texture_width = header.TextureWidth; ctex->header.texture_height = header.TextureHeight; ctex->header.image_width = header.ImageWidth; ctex->header.image_height = header.ImageHeight; ctex->header.unk_int0 = header.UnkInt0; // images container var imgContainer = tex.ImagesContainer; var images = imgContainer.Images; ctex->images_container.magic = e.ToCString(imgContainer.Magic); ctex->images_container.image_format = imgContainer.ImageFormat; ctex->images_container.image_count = images.Count; ctex->images_container.images_length = images.Count; ctex->images_container.container_version = imgContainer.ImageContainerVersion; if (images.Count == 0) { ctex->images_container.images = null; } else { var cimages = e.AllocateStructArray <CTexImage>(images.Count); ctex->images_container.images = cimages; for (var i = 0; i < images.Count; i++) { ConvertCTexImage(e, images[i], &cimages[i]); } } // frame info container var frameContainer = tex.FrameInfoContainer; if (frameContainer == null) { ctex->frameinfo_container = null; return(ctex); } var frames = frameContainer.Frames; ctex->frameinfo_container = e.AllocateStruct <CTexFrameInfoContainer>(); ctex->frameinfo_container->magic = e.ToCString(frameContainer.Magic); ctex->frameinfo_container->frame_count = frames.Count; ctex->frameinfo_container->frames_length = frames.Count; ctex->frameinfo_container->gif_width = frameContainer.GifWidth; ctex->frameinfo_container->gif_height = frameContainer.GifHeight; if (frames.Count == 0) { ctex->frameinfo_container->frames = null; return(ctex); } var cframes = e.AllocateStructArray <CTexFrameInfo>(frames.Count); ctex->frameinfo_container->frames = cframes; for (var i = 0; i < frames.Count; i++) { ConvertCTexFrameInfo(e, frames[i], &cframes[i]); } return(ctex); }
public ITex LoadFileToTex(FileInfo filePath) { switch (filePath.Extension) { case ".tex-full-json": { var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; ITex tex = JsonConvert.DeserializeObject <Tex>(File.ReadAllText(filePath.FullName), settings); return(tex); } default: { Image image = Image.FromFile(filePath.FullName); byte[] imageBytes; using (var ms = new MemoryStream()) { image.Save(ms, image.RawFormat); imageBytes = ms.ToArray(); } // var fullJsonInfo = Newtonsoft.Json.JsonConvert.SerializeObject(image); // File.WriteAllText($"{filePath}.test-json", fullJsonInfo); // var bytes = image.SavePixelData(); var tex = new Tex { }; tex.Magic1 = "TEXV0005"; tex.Magic2 = "TEXI0001"; tex.Header = new TexHeader { Format = (TexFormat)0, Flags = (TexFlags)2, TextureWidth = image.Width, TextureHeight = image.Height, ImageWidth = image.Width, ImageHeight = image.Height, UnkInt0 = 4278190080 }; tex.ImagesContainer = new TexImageContainer { }; tex.ImagesContainer.Magic = "TEXB0003"; switch (tex.ImagesContainer.Magic) { case "TEXB0001": case "TEXB0002": break; case "TEXB0003": tex.ImagesContainer.ImageFormat = FreeImageFormat.FIF_PNG; break; default: throw new UnknownMagicException(nameof(TexImageContainerReader), tex.ImagesContainer.Magic); } tex.ImagesContainer.ImageContainerVersion = (TexImageContainerVersion)Convert.ToInt32(tex.ImagesContainer.Magic.Substring(4)); // var mipmapCount = 1; // if (mipmapCount > Constants.MaximumMipmapCount) // throw new UnsafeTexException( // $"Mipmap count exceeds limit: {mipmapCount}/{Constants.MaximumMipmapCount}"); // var readFunction = PickMipmapReader(container.ImageContainerVersion); var format = TexMipmapFormatGetter.GetFormatForTex(tex.ImagesContainer.ImageFormat, tex.Header.Format); var teximage = new TexImage(); // var mipmap = readFunction(reader); // mipmap.Format = format; // if (DecompressMipmapBytes) // _texMipmapDecompressor.DecompressMipmap(mipmap); var mipmap = new TexMipmap { }; mipmap.Format = MipmapFormat.ImagePNG; mipmap.Width = image.Width; mipmap.Height = image.Height; mipmap.Bytes = imageBytes; teximage.Mipmaps.Add(mipmap); tex.ImagesContainer.Images.Add(teximage); return(tex); } } }
private static ImageResult ConvertToGif(ITex tex) { var frameFormat = tex.FirstImage.FirstMipmap.Format; if (!frameFormat.IsRawFormat()) { throw new InvalidOperationException( "Only raw mipmap formats are supported right now while converting gif"); } var image = ImageFromRawFormat(frameFormat, null, tex.FrameInfoContainer.GifWidth, tex.FrameInfoContainer.GifHeight); var sequenceImages = new Image[tex.ImagesContainer.Images.Count]; for (var i = 0; i < sequenceImages.Length; i++) { var mipmap = tex.ImagesContainer.Images[i].FirstMipmap; sequenceImages[i] = ImageFromRawFormat(frameFormat, mipmap.Bytes, mipmap.Width, mipmap.Height); } foreach (var frameInfo in tex.FrameInfoContainer.Frames) { // Frames can be turned to fit into the map so we need to compute cropping coordinates first // We're keeping width and height signed for the rotation angle calculation var width = frameInfo.Width != 0 ? frameInfo.Width : frameInfo.HeightX; var height = frameInfo.Height != 0 ? frameInfo.Height : frameInfo.WidthY; var x = Math.Min(frameInfo.X, frameInfo.X + width); var y = Math.Min(frameInfo.Y, frameInfo.Y + height); // This formula gives us the angle for which we need to turn the frame, // assuming that either Width or HeightX is 0 (same with Height and WidthY) var rotationAngle = -(Math.Atan2(Math.Sign(height), Math.Sign(width)) - Math.PI / 4); var frame = sequenceImages[frameInfo.ImageId].Clone( context => context.Crop(new Rectangle( (int)x, (int)y, (int)Math.Abs(width), (int)Math.Abs(height)) ).Rotate((float)Math.Round(rotationAngle * 180 / Math.PI))); var metadata = frame.Frames.RootFrame.Metadata.GetFormatMetadata(GifFormat.Instance); metadata.FrameDelay = (int)Math.Round(frameInfo.Frametime * 100.0f); image.Frames.AddFrame(frame.Frames[0]); } // Remove first black frame image.Frames.RemoveFrame(0); using (var memoryStream = new MemoryStream()) { image.SaveAsGif(memoryStream, new GifEncoder { ColorTableMode = GifColorTableMode.Local }); return(new ImageResult { Bytes = memoryStream.ToArray(), Format = MipmapFormat.ImageGIF }); } }