1 |
using System; |
2 |
|
3 |
namespace Oni.Imaging |
4 |
{ |
5 |
internal static class TgaReader |
6 |
{ |
7 |
public static Surface Read(string filePath) |
8 |
{ |
9 |
using (var reader = new BinaryReader(filePath)) |
10 |
{ |
11 |
var header = TgaHeader.Read(reader); |
12 |
|
13 |
Surface surface; |
14 |
|
15 |
switch (header.ImageType) |
16 |
{ |
17 |
case TgaImageType.TrueColor: |
18 |
surface = LoadTrueColor(header, reader); |
19 |
break; |
20 |
|
21 |
case TgaImageType.RleTrueColor: |
22 |
surface = LoadRleTrueColor(header, reader); |
23 |
break; |
24 |
|
25 |
default: |
26 |
throw new NotSupportedException(string.Format("Invalid or unsupported TGA image type {0}", header.ImageType)); |
27 |
} |
28 |
|
29 |
if (header.XFlip) |
30 |
surface.FlipHorizontal(); |
31 |
|
32 |
if (!header.YFlip) |
33 |
surface.FlipVertical(); |
34 |
|
35 |
return surface; |
36 |
} |
37 |
} |
38 |
|
39 |
private static Surface LoadTrueColor(TgaHeader header, BinaryReader reader) |
40 |
{ |
41 |
int pixelSize = header.PixelSize; |
42 |
var format = header.GetSurfaceFormat(); |
43 |
|
44 |
var dst = new Surface(header.Width, header.Height, format); |
45 |
var src = reader.ReadBytes(header.Width * header.Height * pixelSize); |
46 |
int srcOffset = 0; |
47 |
|
48 |
for (int y = 0; y < header.Height; y++) |
49 |
{ |
50 |
for (int x = 0; x < header.Width; x++) |
51 |
{ |
52 |
dst[x, y] = header.GetPixel(src, srcOffset); |
53 |
srcOffset += pixelSize; |
54 |
} |
55 |
} |
56 |
|
57 |
return dst; |
58 |
} |
59 |
|
60 |
private static Surface LoadRleTrueColor(TgaHeader header, BinaryReader reader) |
61 |
{ |
62 |
int pixelSize = header.PixelSize; |
63 |
var format = header.GetSurfaceFormat(); |
64 |
|
65 |
var dst = new Surface(header.Width, header.Height, format); |
66 |
|
67 |
var src = reader.ReadBytes(reader.Length - reader.Position); |
68 |
int srcOffset = 0; |
69 |
|
70 |
int y = 0; |
71 |
int x = 0; |
72 |
|
73 |
var color = Color.Black; |
74 |
|
75 |
while (y < header.Height) |
76 |
{ |
77 |
int packetType = src[srcOffset++]; |
78 |
|
79 |
int packetPixelCount = (packetType & 127) + 1; |
80 |
bool isRle = ((packetType & 128) != 0); |
81 |
|
82 |
for (int i = 0; i < packetPixelCount && y < header.Height; i++) |
83 |
{ |
84 |
if (i == 0 || !isRle) |
85 |
{ |
86 |
color = header.GetPixel(src, srcOffset); |
87 |
srcOffset += pixelSize; |
88 |
} |
89 |
|
90 |
dst[x, y] = color; |
91 |
x++; |
92 |
|
93 |
if (x == header.Width) |
94 |
{ |
95 |
x = 0; |
96 |
y++; |
97 |
} |
98 |
} |
99 |
} |
100 |
|
101 |
return dst; |
102 |
} |
103 |
} |
104 |
} |