Visual Computing Library
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#include "serialization/serialize.h"
29
30#include <vclib/concepts/mesh/elements/element.h>
31#include <vclib/types.h>
32
33#include <filesystem>
34#include <fstream>
35#include <typeindex>
36
37namespace vcl {
38
39inline std::ofstream openOutputFileStream(
40 const std::string& filename,
41 const std::string& ext = "")
42{
43 setlocale(LC_ALL, "C");
44 std::string actualFileName = filename;
45 std::string path = FileInfo::pathWithoutFileName(filename);
46
47 if (!path.empty() && !std::filesystem::exists(path)) {
48 bool res = std::filesystem::create_directory(path);
49 if (!res) {
50 throw std::runtime_error("Cannot create directory: " + path);
51 }
52 }
53
54 if (!ext.empty()) {
55 actualFileName = FileInfo::addExtensionIfNeeded(filename, ext);
56 }
57
58 std::ofstream fp;
59 fp.imbue(std::locale().classic());
60
61 // need to set binary or windows will fail
62 fp.open(actualFileName, std::ofstream::binary);
63 if (!fp) {
64 throw CannotOpenFileException(actualFileName);
65 }
66
67 return fp;
68}
69
70namespace io {
71
72template<typename T>
73void writeChar(
74 std::ostream& file,
75 T p,
76 FileType format = FileType(),
77 bool isColor = false)
78{
79 if (isColor && !std::is_integral<T>::value)
80 p *= 255;
81 char tmp = p;
82 if (format.isBinary)
83 serialize(file, tmp, format.endian);
84 else
85 file << (int) p << " "; // cast necessary to not print the ascii char
86}
87
88template<typename T>
89void writeUChar(
90 std::ostream& file,
91 T p,
92 FileType format = FileType(),
93 bool isColor = false)
94{
95 if (isColor && !std::is_integral<T>::value)
96 p *= 255;
97 unsigned char tmp = p;
98 if (format.isBinary)
99 serialize(file, tmp, format.endian);
100 else
101 file << (uint) p << " "; // cast necessary to not print the ascii char
102}
103
104template<typename T>
105void writeShort(
106 std::ostream& file,
107 T p,
108 FileType format = FileType(),
109 bool isColor = false)
110{
111 if (isColor && !std::is_integral<T>::value)
112 p *= 255;
113 short tmp = p;
114 if (format.isBinary)
115 serialize(file, tmp, format.endian);
116 else
117 file << tmp << " ";
118}
119
120template<typename T>
121void writeUShort(
122 std::ostream& file,
123 T p,
124 FileType format = FileType(),
125 bool isColor = false)
126{
127 if (isColor && !std::is_integral<T>::value)
128 p *= 255;
129 unsigned short tmp = p;
130 if (format.isBinary)
131 serialize(file, tmp, format.endian);
132 else
133 file << tmp << " ";
134}
135
136template<typename T>
137void writeInt(
138 std::ostream& file,
139 T p,
140 FileType format = FileType(),
141 bool isColor = false)
142{
143 if (isColor && !std::is_integral<T>::value)
144 p *= 255;
145 int tmp = p;
146 if (format.isBinary)
147 serialize(file, tmp, format.endian);
148 else
149 file << tmp << " ";
150}
151
152template<typename T>
153void writeUInt(
154 std::ostream& file,
155 T p,
156 FileType format = FileType(),
157 bool isColor = false)
158{
159 if (isColor && !std::is_integral<T>::value)
160 p *= 255;
161 uint tmp = p;
162 if (format.isBinary)
163 serialize(file, tmp, format.endian);
164 else
165 file << tmp << " ";
166}
167
168template<typename T>
169void writeFloat(
170 std::ostream& file,
171 const T& p,
172 FileType format = FileType(),
173 bool isColor = false)
174{
175 float tmp = p;
176 if (isColor && std::is_integral<T>::value)
177 tmp /= 255;
178 if (format.isBinary)
179 serialize(file, tmp, format.endian);
180 else
181 file << tmp << " ";
182}
183
184template<typename T>
185void writeDouble(
186 std::ostream& file,
187 const T& p,
188 FileType format = FileType(),
189 bool isColor = false)
190{
191 double tmp = p;
192 if (isColor && std::is_integral<T>::value)
193 tmp /= 255;
194 if (format.isBinary)
195 serialize(file, tmp, format.endian);
196 else
197 file << tmp << " ";
198}
199
200// TODO - rename to writePrimitiveType
201template<typename T>
202void writeProperty(
203 std::ostream& file,
204 const T& p,
205 PrimitiveType type,
206 FileType format = FileType(),
207 bool isColor = false)
208{
209 switch (type) {
210 case PrimitiveType::CHAR: writeChar(file, p, format, isColor); break;
211 case PrimitiveType::UCHAR: writeUChar(file, p, format, isColor); break;
212 case PrimitiveType::SHORT: writeShort(file, p, format, isColor); break;
213 case PrimitiveType::USHORT: writeUShort(file, p, format, isColor); break;
214 case PrimitiveType::INT: writeInt(file, p, format, isColor); break;
215 case PrimitiveType::UINT: writeUInt(file, p, format, isColor); break;
216 case PrimitiveType::FLOAT: writeFloat(file, p, format, isColor); break;
217 case PrimitiveType::DOUBLE: writeDouble(file, p, format, isColor); break;
218 default: assert(0);
219 }
220}
221
222// TODO - move this to some specific mesh file
223template<ElementConcept El>
224void writeCustomComponent(
225 std::ostream& file,
226 const El& elem,
227 const std::string& cName,
228 PrimitiveType type,
229 FileType format = FileType())
230{
231 std::type_index ti = elem.customComponentType(cName);
232 if (ti == typeid(char))
233 writeProperty(
234 file, elem.template customComponent<char>(cName), type, format);
235 else if (ti == typeid(unsigned char))
236 writeProperty(
237 file,
238 elem.template customComponent<unsigned char>(cName),
239 type,
240 format);
241 else if (ti == typeid(short))
242 writeProperty(
243 file, elem.template customComponent<short>(cName), type, format);
244 else if (ti == typeid(unsigned short))
245 writeProperty(
246 file,
247 elem.template customComponent<unsigned short>(cName),
248 type,
249 format);
250 else if (ti == typeid(int))
251 writeProperty(
252 file, elem.template customComponent<int>(cName), type, format);
253 else if (ti == typeid(unsigned int))
254 writeProperty(
255 file, elem.template customComponent<uint>(cName), type, format);
256 else if (ti == typeid(float))
257 writeProperty(
258 file, elem.template customComponent<float>(cName), type, format);
259 else if (ti == typeid(double))
260 writeProperty(
261 file, elem.template customComponent<double>(cName), type, format);
262 else
263 assert(0);
264}
265
266} // namespace io
267} // namespace vcl
268
269#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:271
static std::string pathWithoutFileName(const std::string &fullpath)
Get the path of a file.
Definition file_info.h:197
PrimitiveType
A simple type that enumerates the main primitive types.
Definition base.h:58