using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace BrainFailProductions.PolyFew.AsImpL
{
///
/// Class for loading textures files into Unity scene at run-time and in editor mode.
///
///
/// Derived from "Runtime OBJ Loader"
/// (http://forum.unity3d.com/threads/free-runtime-obj-loader.365884/)
/// and from "runtime .OBJ file loader for Unity3D"
/// (https://github.com/hammmm/unity-obj-loader) and
/// (https://github.com/cmdr2/unity-remote-obj-loader)
///
///
public class TextureLoader : MonoBehaviour
{
///
/// Load an image from a file into a Texture2D.
///
/// URL of the texture image.
/// The loaded texture or null on error.
public static Texture2D LoadTextureFromUrl(string url)
{
const string prefix = "file:///";
if (url.StartsWith(prefix))
{
url = url.Substring(prefix.Length);
}
else
{
url = Path.GetFullPath(url);
}
return LoadTexture(url);
}
///
/// Load an image from a file into a Texture2D.
///
/// file name of the image to load
/// The loaded texture or null on error.
public static Texture2D LoadTexture(string fileName)
{
string ext = Path.GetExtension(fileName).ToLower();
if (ext == ".png" || ext == ".jpg")
{
Texture2D t2d = new Texture2D(1, 1);
t2d.LoadImage(File.ReadAllBytes(fileName));
return t2d;
}
else if (ext == ".dds")
{
Texture2D returnTex = LoadDDSManual(fileName);
return returnTex;
}
else if (ext == ".tga")
{
Texture2D returnTex = LoadTGA(fileName);
return returnTex;
}
else
{
Debug.Log("texture not supported : " + fileName);
}
return null;
}
///
/// Load a TGA image from a file into a Texture2D.
///
/// file name of the image to load
/// The loaded texture or null on error.
public static Texture2D LoadTGA(string fileName)
{
using (var imageFile = File.OpenRead(fileName))
{
return LoadTGA(imageFile);
}
}
///
/// Load a DDS image from a file into a Texture2D.
///
/// file name of the image to load
/// The loaded texture or null on error.
public static Texture2D LoadDDSManual(string ddsPath)
{
try
{
byte[] ddsBytes = File.ReadAllBytes(ddsPath);
byte ddsSizeCheck = ddsBytes[4];
if (ddsSizeCheck != 124)
throw new System.Exception("Invalid DDS DXTn texture. Unable to read"); //this header byte should be 124 for DDS image files
int height = ddsBytes[13] * 256 + ddsBytes[12];
int width = ddsBytes[17] * 256 + ddsBytes[16];
byte DXTType = ddsBytes[87];
TextureFormat textureFormat = TextureFormat.DXT5;
if (DXTType == 49)
{
textureFormat = TextureFormat.DXT1;
// Debug.Log ("DXT1");
}
if (DXTType == 53)
{
textureFormat = TextureFormat.DXT5;
// Debug.Log ("DXT5");
}
int DDS_HEADER_SIZE = 128;
byte[] dxtBytes = new byte[ddsBytes.Length - DDS_HEADER_SIZE];
Buffer.BlockCopy(ddsBytes, DDS_HEADER_SIZE, dxtBytes, 0, ddsBytes.Length - DDS_HEADER_SIZE);
System.IO.FileInfo finf = new System.IO.FileInfo(ddsPath);
Texture2D texture = new Texture2D(width, height, textureFormat, false);
texture.LoadRawTextureData(dxtBytes);
texture.Apply();
texture.name = finf.Name;
return (texture);
}
catch (System.Exception ex)
{
Debug.LogError("Could not load DDS: " + ex);
return new Texture2D(8, 8);
}
}
///
/// Load a TGA image from a stram into a Texture2D.
///
/// input stream
/// The loaded Texture2D
///
/// This directly comes from the code submitted by aaro4130 and edited by ALLCAPS on the Unity forums (thanks to all!).
/// https://forum.unity3d.com/threads/tga-loader-for-unity3d.172291/
///
public static Texture2D LoadTGA(Stream TGAStream)
{
try
{
using (BinaryReader r = new BinaryReader(TGAStream))
{
TgaHeader th = LoadTgaHeader(r);
// Skip some header info we don't care about.
// Even if we did care, we have to move the stream seek point to the beginning,
// as the previous method in the workflow left it at the end.
//r.BaseStream.Seek( 12, SeekOrigin.Begin );
short width = (short)th.width;
short height = (short)th.height;
int bitDepth = th.bits;
//bool hflip = (th.tiDescriptor & 16) == 16;
bool vflip = (th.descriptor & 32) == 32;
//// Skip a byte of header information we don't care about.
//r.BaseStream.Seek( 1, SeekOrigin.Current );
Texture2D tex = new Texture2D(width, height);
Color32[] pulledColors = new Color32[width * height];
int length = width * height;
if (bitDepth == 32)
{
for (int row = 1; row <= height; row++)
{
for (int col = 0; col < width; col++)
{
byte red = r.ReadByte();
byte green = r.ReadByte();
byte blue = r.ReadByte();
byte alpha = r.ReadByte();
// pulledColors [i] = new Color32(blue, green, red, alpha);
int idx;
if (vflip) idx = length - row * width + col;
else idx = length - ((height - row + 1) * width) + col;
pulledColors[idx] = new Color32(blue, green, red, alpha);
}
}
}
else if (bitDepth == 24)
{
for (int row = 1; row <= height; row++)
{
for (int col = 0; col < width; col++)
{
byte red = r.ReadByte();
byte green = r.ReadByte();
byte blue = r.ReadByte();
int idx;
if (vflip) idx = length - row * width + col;
else idx = length - ((height - row + 1) * width) + col;
pulledColors[idx] = new Color32(blue, green, red, 255);
}
}
}
else
{
throw new Exception("TGA texture had non 32/24 bit depth.");
}
tex.SetPixels32(pulledColors);
tex.Apply();
return tex;
}
}
catch (Exception e)
{
// let everything else load even if this TGA loading failed
Debug.LogWarning(e);
return null;
}
}
private static TgaHeader LoadTgaHeader(BinaryReader r)
{
TgaHeader th = new TgaHeader();
r.BaseStream.Seek(0, SeekOrigin.Current);
// fread(&th, sizeof(gvImgTGAHeader), 1, fp);
// due to byte alignment read the components one at a time
th.identSize = r.ReadByte();
th.colorMapType = r.ReadByte();
th.imageType = r.ReadByte();
th.colorMapStart = r.ReadUInt16();
th.colorMapLength = r.ReadUInt16();
th.colorMapBits = r.ReadByte();
th.xStart = r.ReadUInt16();
th.ySstart = r.ReadUInt16();
th.width = r.ReadUInt16();
th.height = r.ReadUInt16();
th.bits = r.ReadByte();
th.descriptor = r.ReadByte();
Debug.LogFormat("TGA descriptor = {0}", th.descriptor);
// check if the image contains no data
if (th.imageType == 0) new Exception("TGA image contains no data."); // GV_IMG_ERROR_NO_DATA;
// check for other types (compressed images)
if (th.imageType > 10) new Exception("compressed TGA not supported."); //GV_IMG_ERROR_COMPRESSED_FILE;
// check if the image is color indexed
if (th.imageType == 1 || th.imageType == 9) new Exception("color indexed TGA not supported."); //GV_IMG_ERROR_INDEXED_COLOR;
// for now we only consider 24bit rgb or rle images
if (th.bits != 24 && th.bits != 32) throw new Exception("only 24/32 bits TGA supported."); //GV_IMG_ERROR_BITS;
// width and height must be valid ones
if (th.width <= 0 || th.height <= 0) throw new Exception("TGA texture has invalid size.");// GV_IMG_ERROR_SIZE;
// skips id header
r.BaseStream.Seek(th.identSize, SeekOrigin.Current);
return th;
}
private class TgaHeader
{
public byte identSize;
public byte colorMapType;
public byte imageType;
public ushort colorMapStart;
public ushort colorMapLength;
public byte colorMapBits;
public ushort xStart;
public ushort ySstart;
public ushort width;
public ushort height;
public byte bits;
public byte descriptor;
}
}
}