1 2 module ws.file.tga; 3 4 import 5 core.stdc.string, 6 std.file, 7 std.string, 8 std.zlib, 9 ws.string, 10 ws.exception; 11 12 class TGA { 13 14 this(string s){ 15 load(s); 16 } 17 18 void load(string path){ 19 try { 20 const(void)[] file; 21 if(exists(path ~ ".gz")){ 22 auto uc = new UnCompress(HeaderFormat.gzip); 23 file = uc.uncompress(read(path ~ ".gz")); 24 file ~= uc.flush(); 25 }else 26 file = read(path); 27 size_t cursor = 18; 28 TGAHEADER header; 29 memcpy(&header, file.ptr, cursor); 30 31 width = header.width; 32 height = header.height; 33 depth = header.bits / 8; 34 origin = header.ystart > 0 ? 1 : 0; 35 36 if(header.bits != 8 && header.bits != 24 && header.bits != 32) 37 exception("Could not load TGA(\""~path~"\"): not 8, 24 or 32 bits ("~tostring(header.bits)~")"); 38 39 if(header.identsize) 40 cursor += header.identsize/8; 41 42 if(data.length < cursor + width * height * depth) 43 exception("%s is too small".format(path)); 44 45 data = cast(byte[])file[cursor..cast(uint)(cursor + width * height * depth)]; 46 }catch(FileException e){ 47 exception("Failed to open file \"" ~ path ~ "\""); 48 } 49 }; 50 51 //void save(string path); 52 53 long width; 54 long height; 55 long origin; // 0: top left, 1: bottom left 56 long depth; 57 58 byte[] data; 59 60 struct TGAHEADER { 61 align(1): 62 byte identsize; // Size of ID field that follows header (0) 63 byte colorMapType; // 0 = None, 1 = paletted 64 byte imageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle 65 ushort colorMapStart; // First colour map entry 66 ushort colorMapLength; // Number of colors 67 byte colorMapBits; // bits per palette entry 68 ushort xstart; // image x origin 69 ushort ystart; // image y origin 70 ushort width; // width in pixels 71 ushort height; // height in pixels 72 byte bits; // bits per pixel (8 16, 24, 32) 73 byte descriptor; // image descriptor 74 } 75 }