Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice

TGA Loader for Unity3D

Discussion in 'Assets and Asset Store' started by aaro4130, Mar 1, 2013.

  1. aaro4130

    aaro4130

    Joined:
    Jul 15, 2010
    Posts:
    447
    Hey guys! This is my TGA Loader, It supports uncompressed 32-bit or 24-bit True Color images

    Here is the code :)
    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using UnityEngine;
    5. using System.IO;
    6. using System.Collections.Generic;
    7. public Texture2D LoadTGA(string TGAFile){
    8.     using (BinaryReader r = new BinaryReader(File.Open(TGAFile, FileMode.Open))) {
    9.             byte IDLength = r.ReadByte();
    10. byte ColorMapType = r.ReadByte();
    11. byte ImageType = r.ReadByte();
    12. Int16 CMapStart = r.ReadInt16();
    13. Int16 CMapLength = r.ReadInt16();
    14. byte CMapDepth = r.ReadByte();
    15. Int16 XOffset = r.ReadInt16();
    16. Int16 YOffset = r.ReadInt16();
    17. Int16 Width = r.ReadInt16();
    18. Int16 Height = r.ReadInt16();
    19. byte PixelDepth = r.ReadByte();
    20. byte ImageDescriptor = r.ReadByte();
    21. if (ImageType == 0) {
    22. Debug.Log("Unsupported TGA file! No image data");
    23. } else if (ImageType == 3 | ImageType == 11) {
    24. Debug.Log("Unsupported TGA file! Not truecolor");
    25. } else if (ImageType == 9 | ImageType == 10) {
    26. Debug.Log("Unsupported TGA file! Colormapped");
    27.  
    28. }
    29. //     MsgBox("Dimensions are "  Width  ","  Height)
    30. Texture2D b = new Texture2D(Width, Height);
    31. for (int y = 0; y <= b.height - 1; y++) {
    32.     for (int x = 0; x <= b.width - 1; x++) {
    33.  
    34.         if (PixelDepth == 32) {
    35.          
    36.          float red = Convert.ToSingle(r.ReadByte());
    37.          float green = Convert.ToSingle(r.ReadByte());
    38.          float blue = Convert.ToSingle(r.ReadByte());
    39.          float alpha = Convert.ToSingle(r.ReadByte());
    40.          alpha /=255;
    41.          green /= 255;
    42.          blue /= 255;
    43.          red /= 255;
    44.         Color cl = new Color(blue ,green ,red ,alpha );
    45.             b.SetPixel(x, y, cl);
    46.                        
    47.                        
    48.         } else {
    49.          
    50.          float red = Convert.ToSingle(r.ReadByte());
    51.          float green = Convert.ToSingle(r.ReadByte());
    52.          float blue = Convert.ToSingle(r.ReadByte());
    53.          
    54.          
    55.          green /= 255;
    56.          blue /= 255;
    57.          red /= 255;
    58.         Color cl = new Color(blue ,green ,red ,1 );
    59.             b.SetPixel(x, y, cl);
    60.                        
    61.            
    62.         }
    63.  
    64.     }
    65. }
    66.             b.Apply();
    67.  
    68. return b;
    69.         }
    70.     }
    71.    
    72.  

    Remember to give credit if you use it :)
     
    Last edited: Mar 1, 2013
  2. SevenBits

    SevenBits

    Joined:
    Dec 26, 2011
    Posts:
    1,953
    Cool. Code looks okay on first glance, though formatting appears to be an issue...
     
  3. aaro4130

    aaro4130

    Joined:
    Jul 15, 2010
    Posts:
    447
    Yeah, I made this quickly for a project I am doing.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,313
    I would advise using Color32 instead of Color. Also SetPixels32 instead of SetPixel.

    --Eric
     
  5. aaro4130

    aaro4130

    Joined:
    Jul 15, 2010
    Posts:
    447
    What's the difference?
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,313
    Using SetPixels is faster than calling SetPixel repeatedly, and Color32 is faster than Color (since there's no need to convert ints to normalized floats) and uses 4X less RAM.

    --Eric
     
  7. aaro4130

    aaro4130

    Joined:
    Jul 15, 2010
    Posts:
    447
    Ah alright, I'll use this in my BMP loader which I am working on
     
  8. kenshin

    kenshin

    Joined:
    Apr 21, 2010
    Posts:
    931
    Thanks for sharing aaro4130! :)
     
  9. ALLCAPS

    ALLCAPS

    Joined:
    Jul 17, 2013
    Posts:
    19
    I slimmed this down and optimized it a bit. I use it for loading TGA Quake 3 textures, but you made it, so I feel I should share my alterations.

    I use an array to store Color32 objects (instead of Color) and work with plain bytes, which avoids all the bitwise and Convert. stuff. I also use SetPixels32 instead of hitting each pixel one by one. It's a bit faster. It is also a complete static class that can be passed either a file name as a string, or a raw stream. I'm using it with SharpZipLib to pull Quake 3 textures directly from .pk3 files, and it works perfectly. The previous design also checked the bitdepth in between every pixel, which is kind of crazy.

    Code (csharp):
    1. // This was made by aaro4130 on the Unity forums.  Thanks boss!
    2. // It's been optimized and slimmed down for the purpose of loading Quake 3 TGA textures from memory streams.
    3.  
    4. using System;
    5. using System.IO;
    6. using UnityEngine;
    7.  
    8. public static class TGALoader
    9. {
    10.  
    11.     public static Texture2D LoadTGA(string fileName)
    12.     {
    13.         using (var imageFile = File.OpenRead(fileName))
    14.         {
    15.             return LoadTGA(imageFile);
    16.         }
    17.     }
    18.  
    19.     public static Texture2D LoadTGA(Stream TGAStream)
    20.     {
    21.    
    22.         using (BinaryReader r = new BinaryReader(TGAStream))
    23.         {
    24.             // Skip some header info we don't care about.
    25.             // Even if we did care, we have to move the stream seek point to the beginning,
    26.             // as the previous method in the workflow left it at the end.
    27.             r.BaseStream.Seek(12, SeekOrigin.Begin);
    28.  
    29.             short width = r.ReadInt16();
    30.             short height = r.ReadInt16();
    31.             int bitDepth = r.ReadByte();
    32.  
    33.             // Skip a byte of header information we don't care about.
    34.             r.BaseStream.Seek(1, SeekOrigin.Current);
    35.  
    36.             Texture2D tex = new Texture2D(width, height);
    37.             Color32[] pulledColors = new Color32[width * height];
    38.  
    39.             if (bitDepth == 32)
    40.             {
    41.                 for (int i = 0; i < width * height; i++)
    42.                 {
    43.                     byte red = r.ReadByte();
    44.                     byte green = r.ReadByte();
    45.                     byte blue = r.ReadByte();
    46.                     byte alpha = r.ReadByte();
    47.  
    48.                     pulledColors [i] = new Color32(blue, green, red, alpha);
    49.                 }
    50.             } else if (bitDepth == 24)
    51.             {
    52.                 for (int i = 0; i < width * height; i++)
    53.                 {
    54.                     byte red = r.ReadByte();
    55.                     byte green = r.ReadByte();
    56.                     byte blue = r.ReadByte();
    57.                    
    58.                     pulledColors [i] = new Color32(blue, green, red, 1);
    59.                 }
    60.             } else
    61.             {
    62.                 throw new Exception("TGA texture had non 32/24 bit depth.");
    63.             }
    64.  
    65.             tex.SetPixels32(pulledColors);
    66.             tex.Apply();
    67.             return tex;
    68.  
    69.         }
    70.     }
    71. }
     
    Last edited: Apr 9, 2014
    aaro4130 likes this.
  10. aaro4130

    aaro4130

    Joined:
    Jul 15, 2010
    Posts:
    447
    Wow. Thanks !

    Glad people are using it.
     
    Last edited: May 31, 2018
  11. liaojiangzheng

    liaojiangzheng

    Joined:
    Dec 25, 2017
    Posts:
    2
    at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean anonymous, FileOptions options) [0x00000] in <filename unknown>:0
    at System.IO.FileStream..ctor (System.String path, FileMode mode, FileAccess access, FileShare share) [0x00000] in <filename unknown>:0
    at System.IO.File.OpenRead (System.String path) [0x00000] in <filename unknown>:0
    at TGALoader.LoadTGA (System.String fileName) [0x00000] in <filename unknown>:0
    at XLua.CSObjectWrap.TGALoaderWrap._m_LoadTGA_xlua_st_ (IntPtr L) [0x00000] in <filename unknown>:0
    stack traceback:
    [C]: in field 'LoadTGA'
     
  12. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    235
    Fast loader for 32-bit uncompressed TGA files:

    Code (CSharp):
    1. using System;
    2. using System.IO;
    3. using UnityEngine;
    4. public static class TGALoader
    5. {
    6.     // Loads 32-bit (RGBA) uncompressed TGA. Actually, due to TARGA file structure, BGRA32 is good option...
    7.     // Disabled mipmaps. Disabled read/write option, to release texture memory copy.
    8.     public static Texture2D LoadTGA(string fileName)
    9.     {
    10.         try
    11.         {
    12.             BinaryReader reader = new BinaryReader(File.OpenRead(fileName));
    13.             reader.BaseStream.Seek(12, SeekOrigin.Begin);    
    14.             short width = reader.ReadInt16();
    15.             short height = reader.ReadInt16();
    16.             reader.BaseStream.Seek(2, SeekOrigin.Current);
    17.             byte[] source = reader.ReadBytes(width * height * 4);
    18.             reader.Close();
    19.             Texture2D texture = new Texture2D(width, height, TextureFormat.BGRA32, false);
    20.             texture.LoadRawTextureData(source);
    21.             texture.name = Path.GetFileName(fileName);
    22.             texture.Apply(false, true);
    23.             return texture;
    24.         }
    25.         catch (Exception)
    26.         {
    27.             return Texture2D.blackTexture;
    28.         }
    29.     }
    30. }
     
    ktagawa likes this.
  13. ktagawa

    ktagawa

    Joined:
    Dec 20, 2015
    Posts:
    1
unityunity