Created
March 16, 2025 20:57
-
-
Save amoeba/425e709e8dc38a6a0c6ba991f822e728 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using ACE.DatLoader.FileTypes; | |
using ACE.Entity.Enum; | |
using SkiaSharp; | |
List<int> GetImageColorArray(Texture texture) | |
{ | |
List<int> colors = new List<int>(); | |
if (texture.Length == 0) return colors; | |
switch (texture.Format) | |
{ | |
case SurfacePixelFormat.PFID_R8G8B8: // RGB | |
using (BinaryReader reader = new BinaryReader(new MemoryStream(texture.SourceData))) | |
{ | |
for (uint i = 0; i < texture.Height; i++) | |
for (uint j = 0; j < texture.Width; j++) | |
{ | |
byte b = reader.ReadByte(); | |
byte g = reader.ReadByte(); | |
byte r = reader.ReadByte(); | |
int color = (r << 16) | (g << 8) | b; | |
colors.Add(color); | |
} | |
} | |
break; | |
case SurfacePixelFormat.PFID_A8R8G8B8: // ARGB format. Most UI textures fall into this category | |
using (BinaryReader reader = new BinaryReader(new MemoryStream(texture.SourceData))) | |
{ | |
for (uint i = 0; i < texture.Height; i++) | |
for (uint j = 0; j < texture.Width; j++) | |
colors.Add(reader.ReadInt32()); | |
} | |
break; | |
} | |
return colors; | |
} | |
SKBitmap GetBitmap(Texture texture, List<int> colorArray) | |
{ | |
SKBitmap image = new SKBitmap(texture.Width, texture.Height); | |
switch (texture.Format) | |
{ | |
case SurfacePixelFormat.PFID_R8G8B8: | |
case SurfacePixelFormat.PFID_CUSTOM_LSCAPE_R8G8B8: | |
for (int i = 0; i < texture.Height; i++) | |
for (int j = 0; j < texture.Width; j++) | |
{ | |
int idx = (i * texture.Width) + j; | |
byte r = (byte)((colorArray[idx] & 0xFF0000) >> 16); | |
byte g = (byte)((colorArray[idx] & 0xFF00) >> 8); | |
byte b = (byte)(colorArray[idx] & 0xFF); | |
image.SetPixel(j, i, new SKColor(r, g, b)); | |
} | |
break; | |
case SurfacePixelFormat.PFID_A8R8G8B8: | |
for (int i = 0; i < texture.Height; i++) | |
for (int j = 0; j < texture.Width; j++) | |
{ | |
int idx = (i * texture.Width) + j; | |
byte a = (byte)((int)((colorArray[idx] & 0xFF000000) >> 24)); | |
byte r = (byte)((colorArray[idx] & 0xFF0000) >> 16); | |
byte g = (byte)((colorArray[idx] & 0xFF00) >> 8); | |
byte b = (byte)(colorArray[idx] & 0xFF); | |
image.SetPixel(j, i, new SKColor(r, g, b, a)); | |
} | |
break; | |
} | |
return image; | |
} | |
string filePath = "../ACEmulator/ACE/Dats/client_portal.dat"; | |
long offset = 885193728 + 4; // Set your desired offset here | |
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) | |
using (BinaryReader reader = new BinaryReader(fs)) | |
{ | |
fs.Seek(offset, SeekOrigin.Begin); | |
// Texture | |
var texture = new Texture(); | |
texture.Unpack(reader); | |
Console.WriteLine($"Data at offset {offset}. Format is {texture.Format}; {texture.Width}x{texture.Height}; Length={texture.Length}"); | |
// Get image data | |
List<int> colors = GetImageColorArray(texture); | |
var bitmap = GetBitmap(texture, colors); | |
// Save the bitmap to a file | |
string outputPath = "texture_output.png"; | |
using (var image = SKImage.FromBitmap(bitmap)) | |
using (var data = image.Encode(SKEncodedImageFormat.Png, 100)) | |
using (var stream = File.OpenWrite(outputPath)) | |
{ | |
data.SaveTo(stream); | |
} | |
Console.WriteLine($"Image saved to {Path.GetFullPath(outputPath)}"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment