source: OniSplit/Imaging/TgaHeader.cs@ 1147

Last change on this file since 1147 was 1114, checked in by iritscen, 5 years ago

Adding OniSplit source code (v0.9.99.0). Many thanks to Neo for all his work over the years.

File size: 5.7 KB
Line 
1using System;
2using System.IO;
3
4namespace Oni.Imaging
5{
6 internal class TgaHeader
7 {
8 #region Private data
9 private bool hasColorMap;
10 private TgaImageType imageType;
11 private int colorMapIndex;
12 private int colorMapLength;
13 private int colorMapEntrySize;
14 private int width;
15 private int height;
16 private int pixelDepth;
17 private int imageDescriptor;
18 private bool xFlip;
19 private bool yFlip;
20 private bool hasAlpha;
21 #endregion
22
23 public TgaImageType ImageType => imageType;
24 public int Width => width;
25 public int Height => height;
26 public int PixelSize => pixelDepth / 8;
27 public bool XFlip => xFlip;
28 public bool YFlip => yFlip;
29
30 public static TgaHeader Read(BinaryReader reader)
31 {
32 int idLength = reader.ReadByte();
33
34 var header = new TgaHeader();
35 header.hasColorMap = (reader.ReadByte() != 0);
36 header.imageType = (TgaImageType)reader.ReadByte();
37 header.colorMapIndex = reader.ReadUInt16();
38 header.colorMapLength = reader.ReadUInt16();
39 header.colorMapEntrySize = reader.ReadByte();
40 reader.ReadUInt16(); // x origin
41 reader.ReadUInt16(); // y origin
42 header.width = reader.ReadUInt16();
43 header.height = reader.ReadUInt16();
44 header.pixelDepth = reader.ReadByte();
45 header.imageDescriptor = reader.ReadByte();
46
47 if (!Enum.IsDefined(typeof(TgaImageType), header.ImageType) || header.ImageType == TgaImageType.None)
48 throw new NotSupportedException(string.Format("Unsupported TGA image type {0}", header.ImageType));
49
50 if (header.Width == 0 || header.Height == 0)
51 throw new InvalidDataException("Invalid TGA file");
52
53 if (header.ImageType == TgaImageType.TrueColor
54 && (header.pixelDepth != 16
55 && header.pixelDepth != 24
56 && header.pixelDepth != 32))
57 {
58 throw new InvalidDataException(string.Format("Invalid true color pixel depth {0}", header.pixelDepth));
59 }
60
61 if (header.hasColorMap)
62 {
63 if (header.colorMapEntrySize != 16
64 && header.colorMapEntrySize != 24
65 && header.colorMapEntrySize != 32)
66 {
67 throw new InvalidDataException(string.Format("Invalid color map entry size {0}", header.colorMapEntrySize));
68 }
69
70 if (header.ImageType != TgaImageType.ColorMapped
71 && header.ImageType != TgaImageType.RleColorMapped)
72 {
73 //
74 // We have a color map but the image type does not use it so we'll just skip it.
75 //
76
77 reader.Position += header.colorMapLength * header.colorMapEntrySize / 8;
78 }
79 }
80
81 //
82 // Skip the identification field because we don't need it.
83 //
84
85 reader.Position += idLength;
86
87 if (header.pixelDepth == 32)
88 header.hasAlpha = ((header.imageDescriptor & 0x0f) == 8);
89 else if (header.pixelDepth == 16)
90 header.hasAlpha = ((header.imageDescriptor & 0x0f) == 1);
91 else
92 header.hasAlpha = false;
93
94 header.xFlip = ((header.imageDescriptor & 16) == 16);
95 header.yFlip = ((header.imageDescriptor & 32) == 32);
96
97 return header;
98 }
99
100 public static TgaHeader Create(int width, int height, TgaImageType imageType)
101 {
102 return new TgaHeader {
103 imageType = imageType,
104 width = width,
105 height = height,
106 pixelDepth = 32,
107 imageDescriptor = 8
108 };
109 }
110
111 public void Write(BinaryWriter writer)
112 {
113 writer.Write((byte)0);
114 writer.Write((byte)(hasColorMap ? 1 : 0));
115 writer.Write((byte)imageType);
116 writer.Write((ushort)colorMapIndex);
117 writer.Write((ushort)colorMapLength);
118 writer.Write((byte)colorMapEntrySize);
119 writer.Write((ushort)0);
120 writer.Write((ushort)0);
121 writer.Write((ushort)width);
122 writer.Write((ushort)height);
123 writer.Write((byte)pixelDepth);
124 writer.Write((byte)imageDescriptor);
125 }
126
127 public SurfaceFormat GetSurfaceFormat()
128 {
129 switch (pixelDepth)
130 {
131 case 16:
132 return hasAlpha ? SurfaceFormat.BGRA5551 : SurfaceFormat.BGRX5551;
133 case 24:
134 return SurfaceFormat.BGRX;
135 default:
136 case 32:
137 return hasAlpha ? SurfaceFormat.BGRA : SurfaceFormat.BGRX;
138 }
139 }
140
141 public Color GetPixel(byte[] src, int srcOffset)
142 {
143 switch (pixelDepth)
144 {
145 case 16:
146 if (hasAlpha)
147 return Color.ReadBgra5551(src, srcOffset);
148 else
149 return Color.ReadBgrx5551(src, srcOffset);
150
151 case 24:
152 return Color.ReadBgrx(src, srcOffset);
153
154 default:
155 case 32:
156 if (hasAlpha)
157 return Color.ReadBgra(src, srcOffset);
158 else
159 return Color.ReadBgrx(src, srcOffset);
160 }
161 }
162 }
163}
Note: See TracBrowser for help on using the repository browser.