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 }