1 module rip.io.formats.pam; 2 3 private { 4 import std.algorithm; 5 import std.conv : parse; 6 7 import std.stdio : File; 8 import std..string; 9 import std.algorithm; 10 import std.stdio; 11 12 import rip.io.interfaces; 13 import rip.concepts; 14 } 15 16 public: 17 static const auto PAM = new PamWorker; 18 19 private: 20 21 static final class PamWorker : FormatWorker!(Surface) { 22 override Surface save(in Surface surface, in string filename) const { 23 File file; 24 25 with (file) 26 { 27 open(filename, "w"); 28 writeln("P7"); 29 writeln("WIDTH ", surface.getWidth!uint); 30 writeln("HEIGHT ", surface.getHeight!uint); 31 writeln("DEPTH 3"); 32 writeln("MAXVAL 255"); 33 writeln("TUPLTYPE RGB"); 34 writeln("ENDHDR"); 35 36 //раскомментировать, когда ситуация с этим шаблоном разрешится 37 //mixin colorsToFile; 38 39 void toFile(in RGBColor color) { 40 file.write( 41 color.red!char, 42 color.green!char, 43 color.blue!char); 44 } 45 46 surface 47 .getPixels() 48 .each!toFile; 49 50 close(); 51 } 52 53 return cast(Surface)surface; 54 } 55 //вернёт false, если всё прошло успешно 56 override Surface decode(File file) const { 57 with (file) { 58 if (readln().strip == "P7") 59 { 60 size_t width, height; 61 auto strData = readln.split; 62 63 while(strData[0] != "ENDHDR") { 64 switch(strData[0]) { 65 case "WIDTH": width = parse!size_t(strData[1]); break; 66 case "HEIGHT": height = parse!size_t(strData[1]); break; 67 case "DEPTH": { 68 if(parse!ubyte(strData[1]) != 3) 69 assert(0, "P7: Only files with DEPTH 3 are supported"); 70 } break; 71 case "MAXVAL": { 72 if(parse!uint(strData[1]) != 255) 73 assert(0, "P7: Only files with MAXVAL 255 are supported"); 74 } break; 75 case "TUPLTYPE": { 76 if(strData[1] != "RGB") 77 assert(0, "P7: Only files with TUPLTYPE RGB are supported"); 78 } break; 79 80 default: break; 81 } 82 83 strData = readln.split; 84 } 85 86 auto buffer = new ubyte[width * 3]; 87 88 Surface surface = new Surface(width, height); 89 90 for (size_t i = 0; i < height; i++) 91 { 92 file.rawRead!ubyte(buffer); 93 for (size_t j = 0; j < width; j++) 94 { 95 96 surface[j + i * width] = new RGBColor( 97 buffer[j * 3], 98 buffer[j * 3 + 1], 99 buffer[j * 3 + 2] 100 ); 101 } 102 } 103 104 close(); 105 106 return surface; 107 } 108 } 109 110 assert(0, "PAM: Error. Decoding terminated."); 111 } 112 113 override bool checkOnHeader(File file) const { 114 ubyte[2] buff; 115 file.rawRead(buff); 116 file.seek(0); 117 return buff == [0x50, 0x37]; 118 } 119 120 override Surface load(in string name) const { 121 return null; 122 } 123 }