Skip to content

Commit

Permalink
Added mp4 video texture support
Browse files Browse the repository at this point in the history
  • Loading branch information
notscuffed committed Nov 22, 2024
1 parent c4c0c30 commit d7b367a
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 9 deletions.
38 changes: 31 additions & 7 deletions RePKG.Application/Texture/TexToImageConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Net.Mime;
using RePKG.Application.Texture.Helpers;
using RePKG.Core.Texture;
using SixLabors.ImageSharp;
Expand All @@ -15,11 +16,32 @@ public class TexToImageConverter
public ImageResult ConvertToImage(ITex tex)
{
if (tex == null) throw new ArgumentNullException(nameof(tex));

if (tex.IsGif)
return ConvertToGif(tex);

var sourceMipmap = tex.FirstImage.FirstMipmap;

if (tex.IsVideoTexture)
{
if (sourceMipmap.Bytes.Length < 4)
{
throw new InvalidOperationException("Expected mp4 magic header");
}

var bytes = sourceMipmap.Bytes;
if (bytes[0] != 0x00 || bytes[1] != 0x00 || bytes[2] != 0x00 || bytes[3] != 0x20)
{
throw new InvalidOperationException("Expected mp4 magic header");
}

return new ImageResult
{
Bytes = sourceMipmap.Bytes,
Format = MipmapFormat.VideoMp4
};
}

var format = sourceMipmap.Format;

if (format.IsCompressed())
Expand Down Expand Up @@ -55,9 +77,11 @@ public ImageResult ConvertToImage(ITex tex)
public MipmapFormat GetConvertedFormat(ITex tex)
{
if (tex == null) throw new ArgumentNullException(nameof(tex));

if (tex.IsGif)
return MipmapFormat.ImageGIF;

if (tex.IsVideoTexture)
{
return MipmapFormat.VideoMp4;
}

var format = tex.FirstImage.FirstMipmap.Format;

Expand Down Expand Up @@ -95,11 +119,11 @@ private static ImageResult ConvertToGif(ITex tex)
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,
Expand Down
5 changes: 5 additions & 0 deletions RePKG.Core/Texture/Enums/MipmapFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public enum MipmapFormat
/// Raw pixels compressed using DXT1
/// </summary>
CompressedDXT1,

/// <summary>
/// MP4 Video
/// </summary>
VideoMp4,

/// <summary>
/// Windows or OS/2 Bitmap File (*.BMP)
Expand Down
2 changes: 1 addition & 1 deletion RePKG.Core/Texture/Enums/TexFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public enum TexFlags
// Placeholders
Unk3 = 8,
Unk4 = 16,
Unk5 = 32,
IsVideoTexture = 32,
Unk6 = 64,
Unk7 = 128,
}
Expand Down
2 changes: 2 additions & 0 deletions RePKG.Core/Texture/Helpers/MipmapFormatExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ public static string GetFileExtension(this MipmapFormat format)
return "pict";
case MipmapFormat.ImageRAW:
return "raw";
case MipmapFormat.VideoMp4:
return "mp4";
default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
Expand Down
1 change: 1 addition & 0 deletions RePKG.Core/Texture/Interfaces/Data/ITex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public interface ITex
ITexFrameInfoContainer FrameInfoContainer { get; set; }

bool IsGif { get; }
bool IsVideoTexture { get; }
ITexImage FirstImage { get; }

bool HasFlag(TexFlags flag);
Expand Down
1 change: 1 addition & 0 deletions RePKG.Core/Texture/Tex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class Tex : ITex
public ITexFrameInfoContainer FrameInfoContainer { get; set; }

public bool IsGif => HasFlag(TexFlags.IsGif);
public bool IsVideoTexture => HasFlag(TexFlags.IsVideoTexture);
public ITexImage FirstImage => ImagesContainer?.Images.FirstOrDefault();

public bool HasFlag(TexFlags flag)
Expand Down
1 change: 1 addition & 0 deletions RePKG.Tests/TexDecompressingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public void SetUp()
[TestCase("V3_DXT3", true, null)]
[TestCase("V3_DXT5", true, null)]
[TestCase("V3_RGBA8888_GIF_TEXS0003", true, TexFlags.IsGif)]
[TestCase("V3_VIDEOTEXTURE_MP4", true, TexFlags.IsVideoTexture)]
public void TestTexDecompressing(
string name,
bool validateBytes = true,
Expand Down
1 change: 1 addition & 0 deletions RePKG.Tests/TexWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public void Setup()
[TestCase("V3_DXT3")]
[TestCase("V3_DXT5")]
[TestCase("V3_RGBA8888_GIF_TEXS0003")]
[TestCase("V3_VIDEOTEXTURE_MP4")]
public void TestWriteAndRead(string name)
{
// Load file
Expand Down
1 change: 0 additions & 1 deletion RePKG/Command/Extract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ private static void ConvertToImageAndSave(ITex tex, string path, bool overwrite)
}
}


[Verb("extract", HelpText = "Extract PKG/Convert TEX into image.")]
public class ExtractOptions
{
Expand Down

0 comments on commit d7b367a

Please sign in to comment.