1 module rip.io.formats.ppm;
2 
3 private {
4 	import std.algorithm;
5 	import std.conv : parse;
6 
7 	import std.stdio : File;
8 	import std..string;
9 
10 	import rip.concepts;
11 	import rip.io.interfaces;
12 }
13 
14 public:
15 static const auto P6 = new P6Worker;
16 
17 private:
18 
19 static final class P6Worker : FormatWorker!(Surface) {
20 
21 	override Surface save(in Surface surface, in string filename) const {
22 		File file;
23 
24 		with (file)
25 		{
26 			open(filename, "w");
27 			writeln("P6");
28 			writeln(surface.getWidth!uint, " ", surface.getHeight!uint);
29 			writeln(255);
30 
31 			//раскомментировать, когда ситуация с этим шаблоном разрешится
32 			//mixin colorsToFile;
33 
34 			void toFile(in RGBColor a) {
35 				file.write(
36 					a.red!char,
37 					a.green!char,
38 					a.blue!char);
39 			}
40 
41 			surface
42 				.getPixels()
43 				.each!toFile;
44 
45 			close();
46 		}
47 
48 		return cast(Surface)surface;
49 	}
50 	//вернёт false, если всё прошло успешно
51 
52 	override Surface decode(File file) const {
53 		with (file) {
54 			if (readln().strip == "P6")
55 			{
56 				auto imageSize = readln.split;
57 				auto width = parse!size_t(imageSize[0]);
58 				auto height = parse!size_t(imageSize[1]);
59 				readln();
60 				auto buffer = new ubyte[width * 3];
61 
62 				Surface surface = new Surface(width, height);
63 
64 				for (size_t i = 0; i < height; i++)
65 				{
66 					file.rawRead!ubyte(buffer);
67 					for (size_t j = 0; j < width; j++)
68 					{
69 
70 						surface[j + i * width] = new RGBColor(
71 							buffer[j * 3],
72 							buffer[j * 3 + 1],
73 							buffer[j * 3 + 2]
74 							);
75 					}
76 				}
77 
78 				close();
79 
80 				return surface;
81 			}
82 		}
83 
84 		assert(0, "PPM: Error. Decoding terminated.");
85 	}
86 
87 	override bool checkOnHeader(File file) const {
88 		ubyte[2] buff;
89 		file.rawRead(buff);
90 		file.seek(0);
91 		return buff == [0x50, 0x36];
92 	}
93 
94 	override Surface load(in string filename) const {
95 		File file;
96 
97 		file.open(filename, "r");
98 
99 		return this.decode(file);
100 	}
101 }