Visual Computing Library  devel
Loading...
Searching...
No Matches
write.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_IO_WRITE_H
24#define VCL_IO_WRITE_H
25
26#include "file_info.h"
27#include "file_type.h"
28
29#include <vclib/io/exceptions.h>
30
31#include <vclib/base.h>
32#include <vclib/mesh.h>
33
34#include <filesystem>
35#include <fstream>
36#include <typeindex>
37
38namespace vcl {
39
40inline std::ofstream openOutputFileStream(
41 const std::string& filename,
42 const std::string& ext = "")
43{
44 setlocale(LC_ALL, "C");
45 std::string actualFileName = filename;
46 std::string path = FileInfo::pathWithoutFileName(filename);
47
48 if (!path.empty() && !std::filesystem::exists(path)) {
49 bool res = std::filesystem::create_directory(path);
50 if (!res) {
51 throw std::runtime_error("Cannot create directory: " + path);
52 }
53 }
54
55 if (!ext.empty()) {
56 actualFileName = FileInfo::addExtensionIfNeeded(filename, ext);
57 }
58
59 std::ofstream fp;
60 fp.imbue(std::locale().classic());
61
62 // need to set binary or windows will fail
63 fp.open(actualFileName, std::ofstream::binary);
64 if (!fp) {
65 throw CannotOpenFileException(actualFileName);
66 }
67
68 return fp;
69}
70
71namespace io {
72
73template<typename T>
74void writeChar(
75 std::ostream& file,
76 T p,
77 FileType format = FileType(),
78 bool isColor = false)
79{
80 if (isColor && !std::is_integral<T>::value)
81 p *= 255;
82 char tmp = p;
83 if (format.isBinary)
84 serialize(file, tmp, format.endian);
85 else
86 file << (int) p << " "; // cast necessary to not print the ascii char
87}
88
89template<typename T>
90void writeUChar(
91 std::ostream& file,
92 T p,
93 FileType format = FileType(),
94 bool isColor = false)
95{
96 if (isColor && !std::is_integral<T>::value)
97 p *= 255;
98 unsigned char tmp = p;
99 if (format.isBinary)
100 serialize(file, tmp, format.endian);
101 else
102 file << (uint) p << " "; // cast necessary to not print the ascii char
103}
104
105template<typename T>
106void writeShort(
107 std::ostream& file,
108 T p,
109 FileType format = FileType(),
110 bool isColor = false)
111{
112 if (isColor && !std::is_integral<T>::value)
113 p *= 255;
114 short tmp = p;
115 if (format.isBinary)
116 serialize(file, tmp, format.endian);
117 else
118 file << tmp << " ";
119}
120
121template<typename T>
122void writeUShort(
123 std::ostream& file,
124 T p,
125 FileType format = FileType(),
126 bool isColor = false)
127{
128 if (isColor && !std::is_integral<T>::value)
129 p *= 255;
130 unsigned short tmp = p;
131 if (format.isBinary)
132 serialize(file, tmp, format.endian);
133 else
134 file << tmp << " ";
135}
136
137template<typename T>
138void writeInt(
139 std::ostream& file,
140 T p,
141 FileType format = FileType(),
142 bool isColor = false)
143{
144 if (isColor && !std::is_integral<T>::value)
145 p *= 255;
146 int tmp = p;
147 if (format.isBinary)
148 serialize(file, tmp, format.endian);
149 else
150 file << tmp << " ";
151}
152
153template<typename T>
154void writeUInt(
155 std::ostream& file,
156 T p,
157 FileType format = FileType(),
158 bool isColor = false)
159{
160 if (isColor && !std::is_integral<T>::value)
161 p *= 255;
162 uint tmp = p;
163 if (format.isBinary)
164 serialize(file, tmp, format.endian);
165 else
166 file << tmp << " ";
167}
168
169template<typename T>
170void writeFloat(
171 std::ostream& file,
172 const T& p,
173 FileType format = FileType(),
174 bool isColor = false)
175{
176 float tmp = p;
177 if (isColor && std::is_integral<T>::value)
178 tmp /= 255;
179 if (format.isBinary)
180 serialize(file, tmp, format.endian);
181 else
182 file << tmp << " ";
183}
184
185template<typename T>
186void writeDouble(
187 std::ostream& file,
188 const T& p,
189 FileType format = FileType(),
190 bool isColor = false)
191{
192 double tmp = p;
193 if (isColor && std::is_integral<T>::value)
194 tmp /= 255;
195 if (format.isBinary)
196 serialize(file, tmp, format.endian);
197 else
198 file << tmp << " ";
199}
200
201// TODO - rename to writePrimitiveType
202template<typename T>
203void writeProperty(
204 std::ostream& file,
205 const T& p,
206 PrimitiveType type,
207 FileType format = FileType(),
208 bool isColor = false)
209{
210 switch (type) {
211 case PrimitiveType::CHAR: writeChar(file, p, format, isColor); break;
212 case PrimitiveType::UCHAR: writeUChar(file, p, format, isColor); break;
213 case PrimitiveType::SHORT: writeShort(file, p, format, isColor); break;
214 case PrimitiveType::USHORT: writeUShort(file, p, format, isColor); break;
215 case PrimitiveType::INT: writeInt(file, p, format, isColor); break;
216 case PrimitiveType::UINT: writeUInt(file, p, format, isColor); break;
217 case PrimitiveType::FLOAT: writeFloat(file, p, format, isColor); break;
218 case PrimitiveType::DOUBLE: writeDouble(file, p, format, isColor); break;
219 default: assert(0);
220 }
221}
222
223// TODO - move this to some specific mesh file
224template<ElementConcept El>
225void writeCustomComponent(
226 std::ostream& file,
227 const El& elem,
228 const std::string& cName,
229 PrimitiveType type,
230 FileType format = FileType())
231{
232 std::type_index ti = elem.customComponentType(cName);
233 if (ti == typeid(char))
234 writeProperty(
235 file, elem.template customComponent<char>(cName), type, format);
236 else if (ti == typeid(unsigned char))
237 writeProperty(
238 file,
239 elem.template customComponent<unsigned char>(cName),
240 type,
241 format);
242 else if (ti == typeid(short))
243 writeProperty(
244 file, elem.template customComponent<short>(cName), type, format);
245 else if (ti == typeid(unsigned short))
246 writeProperty(
247 file,
248 elem.template customComponent<unsigned short>(cName),
249 type,
250 format);
251 else if (ti == typeid(int))
252 writeProperty(
253 file, elem.template customComponent<int>(cName), type, format);
254 else if (ti == typeid(unsigned int))
255 writeProperty(
256 file, elem.template customComponent<uint>(cName), type, format);
257 else if (ti == typeid(float))
258 writeProperty(
259 file, elem.template customComponent<float>(cName), type, format);
260 else if (ti == typeid(double))
261 writeProperty(
262 file, elem.template customComponent<double>(cName), type, format);
263 else
264 assert(0);
265}
266
267} // namespace io
268} // namespace vcl
269
270#endif // VCL_IO_WRITE_H
static std::string addExtensionIfNeeded(const std::string &filename, const std::string &ext)
Adds an extension to a file name if it doesn't already have it.
Definition file_info.h:292
static std::string pathWithoutFileName(const std::string &fullpath)
Get the path of a file.
Definition file_info.h:200
PrimitiveType
A simple type that enumerates the main primitive types.
Definition base.h:58