using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using OMI.Workers; using OMI; namespace PckStudio.Core.IO._3DST { public class _3DSTextureReader : IDataFormatReader, IDataFormatReader { public Image FromFile(string filename) { if (File.Exists(filename)) { Image img = null; using (FileStream fs = File.OpenRead(filename)) { img = FromStream(fs); } return img; } throw new FileNotFoundException(filename); } public Image FromStream(Stream stream) { Image img = null; using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, ByteOrder.LittleEndian)) { if (reader.ReadString(4) == "3DST") { const int offset = 32; reader.ReadInt32(); // unknown value _3DSTextureFormat format = reader.ReadInt32() switch { 0 => _3DSTextureFormat.argb8, 1 => _3DSTextureFormat.rgb8, 2 => _3DSTextureFormat.rgba5551, 3 => _3DSTextureFormat.rgb8, 4 => _3DSTextureFormat.rgba4, 9 => _3DSTextureFormat.la4, _ => _3DSTextureFormat.dontCare, }; int width = reader.ReadInt32(); int height = reader.ReadInt32(); int bufferSize = CalcBufferSize(format, width, height); stream.Seek(offset, SeekOrigin.Begin); byte[] buffer = new byte[bufferSize]; reader.Read(buffer, 0, bufferSize); img = TextureCodec.Decode(buffer, width, height, format); img.RotateFlip(RotateFlipType.RotateNoneFlipY); } } return img; } private static int CalcBufferSize(_3DSTextureFormat textureFormat, int width, int height) { switch (textureFormat) { case _3DSTextureFormat.argb8: return width * height * 4; case _3DSTextureFormat.rgb8: return width * height * 3; case _3DSTextureFormat.rgba5551: case _3DSTextureFormat.rgb565: case _3DSTextureFormat.rgba4: case _3DSTextureFormat.la8: case _3DSTextureFormat.hilo8: return width * height * 2; case _3DSTextureFormat.l8: case _3DSTextureFormat.a8: case _3DSTextureFormat.la4: case _3DSTextureFormat.etc1a4: return width * height; case _3DSTextureFormat.l4: case _3DSTextureFormat.a4: case _3DSTextureFormat.etc1: return width * height >> 1; default: throw new InvalidDataException("Invalid texture format on BCH!"); } } object IDataFormatReader.FromFile(string filename) => FromFile(filename); object IDataFormatReader.FromStream(Stream stream) => FromStream(stream); } }