public Texture2D ReadTexture(BinaryReader reader, TEXDescriptor desc, string saveFilePath, string textureName) { // Verify if index is valid (some entries can be nulled out) // We check for 0 specifically because garbage can be store in the // first few entries of the file. // TPL can have null entries so this is actually correct to the format if (desc.isNullEntry != 0) { return(null); } // We use Try as GxTextureFormatCodec.GetCodec() can return an error if the type is invalid try { GxTextureFormatCodec codec = GxTextureFormatCodec.GetCodec((GxTextureFormat)desc.format); reader.BaseStream.Position = desc.dataPtr; byte[] texRaw = reader.GetBytes(codec.CalcTextureSize(desc.width, desc.height)); byte[] texRGBA = new byte[4 * desc.width * desc.height]; // RGBA (4 bytes) * w * h codec.DecodeTexture(texRGBA, 0, desc.width, desc.height, desc.width * 4, texRaw, 0, null, 0); // Reconstruct Texture using Unity's format Texture2D texture = new Texture2D(desc.width, desc.height); for (int y = 0; y < desc.height; y++) { for (int x = 0; x < desc.width; x++) { // Invert Y because LibGXTexture returns array upside-down? // ei 'x, (desc.width - y)' instead of 'x, y' texture.SetPixel(x, (desc.width - y), new Color32( texRGBA[(y * desc.width + x) * 4 + 0], texRGBA[(y * desc.width + x) * 4 + 1], texRGBA[(y * desc.width + x) * 4 + 2], texRGBA[(y * desc.width + x) * 4 + 3])); } } string assetPath = string.Format("{0}/tex_{1}.png", saveFilePath, textureName).PathToUnityPath(); byte[] imageBytes = texture.EncodeToPNG(); DestroyImmediate(texture); using (BinaryWriter writer = new BinaryWriter(File.Create(assetPath, imageBytes.Length))) { writer.Write(imageBytes); } AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(ImportAssetOptions.Default); Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D)); return(tex); } catch { Debug.LogErrorFormat("GxTextureFormatCodec.GetCodec() failed to find format [0x{0}]", desc.format.ToString("X2")); return(null); } }
public bool ReadTextureFromTPL(BinaryReader reader, int index, out Texture2D texture, string name, bool saveToDisk) { // If index is invalid if (index > numDescriptors) { throw new System.IndexOutOfRangeException(string.Format("Index must be less than or equal to {0}!", numDescriptors)); } else if (index < 0) { throw new System.IndexOutOfRangeException("Index must be greater than 0!"); } // Load Texture Descriptor at index TEXDescriptor desc = descriptorArray[index]; // Verify if index is valid (some entries can be nulled out) // We check for 0 specifically because garbage can be store in the // first few entries of the file. if (desc.isNullEntry != 0) { texture = null; return(false); } // We use Try as GxTextureFormatCodec.GetCodec() can return an error if the type is invalid try { GxTextureFormatCodec codec = GxTextureFormatCodec.GetCodec((GxTextureFormat)desc.format); reader.BaseStream.Position = desc.dataPtr; byte[] texRaw = reader.GetBytes(codec.CalcTextureSize(desc.width, desc.height)); byte[] texRGBA = new byte[4 * desc.width * desc.height]; // RGBA (4 bytes) * w * h codec.DecodeTexture(texRGBA, 0, desc.width, desc.height, desc.width * 4, texRaw, 0, null, 0); // Reconstruct Texture using Unity's format texture = new Texture2D(desc.width, desc.height); for (int y = 0; y < desc.height; y++) { for (int x = 0; x < desc.width; x++) { // Invert Y because LibGXTexture return array upside-down // ei 'x, (desc.width - y)' instead of 'x, y' texture.SetPixel(x, (desc.width - y), new Color32( texRGBA[(y * desc.width + x) * 4 + 0], texRGBA[(y * desc.width + x) * 4 + 1], texRGBA[(y * desc.width + x) * 4 + 2], texRGBA[(y * desc.width + x) * 4 + 3])); } } if (saveToDisk) { Debug.LogFormat("Saved {0} to path {1}", name, PersistantDataPath("")); SaveBytes(string.Format("{0}.png", name), texture.EncodeToPNG()); } return(true); } catch { Debug.LogErrorFormat("GxTextureFormatCodec.GetCodec() failed to find format [{0}]", desc.format.ToString("X")); texture = null; return(false); } }