| 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 | } |