42#include <visp3/core/vpConfig.h>
51#include <visp3/core/vpColor.h>
52#include <visp3/core/vpEndian.h>
59#if VISP_CXX_STANDARD > VISP_CXX_STANDARD_98
63#ifndef DOXYGEN_SHOULD_SKIP_THIS
65static inline unsigned long vp_mz_crc32(
unsigned long crc,
const unsigned char *ptr,
size_t buf_len)
67 static const unsigned int s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
68 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
69 unsigned int crcu32 =
static_cast<unsigned int>(crc);
73 unsigned char b = *ptr++;
74 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
75 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
81#if defined(VISP_HAVE_MINIZ) && defined(VISP_HAVE_WORKING_REGEX)
100 NpyArray(
const std::vector<size_t> &_shape,
size_t _word_size,
bool _fortran_order,
char _data_type) :
114 return reinterpret_cast<T *
>(&(*data_holder)[0]);
120 return reinterpret_cast<T *
>(&(*data_holder)[0]);
128 if (!std::is_same<T, char>::value) {
129 throw std::runtime_error(
"NpyArray.as_vec(): datatype contains string data but as_vec() is not templated as <char>");
134 return std::vector<T>(p, p+
num_vals);
141 throw std::runtime_error(
"NpyArray.as_utf8_string_vec(): not a string data");
144 std::vector<std::string> vec_string;
147 for (
size_t i = 0; i <
num_vals; i++) {
155 str += (*data_holder)[idx];
158 vec_string.push_back(str);
177using npz_t = std::map<std::string, NpyArray>;
180VISP_EXPORT
char map_type(
const std::type_info &t);
181template<
typename T> std::vector<char>
create_npy_header(
const std::vector<size_t> &shape);
182VISP_EXPORT
void parse_npy_header(FILE *fp,
size_t &word_size, std::vector<size_t> &shape,
bool &fortran_order,
bool &little_endian,
char &data_type);
183VISP_EXPORT
void parse_npy_header(
unsigned char *buffer,
size_t &word_size, std::vector<size_t> &shape,
bool &fortran_order,
bool &little_endian,
char &data_type);
184VISP_EXPORT
void parse_zip_footer(FILE *fp, uint16_t &nrecs,
size_t &global_header_size,
size_t &global_header_offset);
185VISP_EXPORT
NpyArray npz_load(
const std::string &fname,
const std::string &varname);
188VISP_EXPORT
void npz_save(
const std::string &zipname, std::string fname,
const std::vector<std::string> &data_vec,
const std::vector<size_t> &shape,
const std::string &mode =
"w");
189VISP_EXPORT
void npz_save(
const std::string &zipname,
const std::string &fname,
const std::string &data,
const std::string &mode =
"w");
191template<
typename T> std::vector<char> &
operator+=(std::vector<char> &lhs,
const T rhs)
194 for (
size_t byte = 0;
byte <
sizeof(T); ++byte) {
195 char val = *((
char *)&rhs+
byte);
201template<>
inline std::vector<char> &
operator+=(std::vector<char> &lhs,
const std::string rhs)
203 lhs.insert(lhs.end(), rhs.begin(), rhs.end());
207template<>
inline std::vector<char> &
operator+=(std::vector<char> &lhs,
const char *rhs)
210 size_t len = strlen(rhs);
212 for (
size_t byte = 0;
byte < len; ++byte) {
213 lhs.push_back(rhs[
byte]);
228template<
typename T>
void npy_save(
const std::string &fname,
const T *data,
const std::vector<size_t> &shape,
const std::string &mode =
"w")
231 std::vector<size_t> true_data_shape;
233 if (mode ==
"a") fp = fopen(fname.c_str(),
"r+b");
238 bool fortran_order, little_endian;
239 char data_type =
'i';
240 parse_npy_header(fp, word_size, true_data_shape, fortran_order, little_endian, data_type);
241 assert(!fortran_order);
243 if (word_size !=
sizeof(T)) {
244 std::cerr <<
"libnpy error: " << fname <<
" has word size " << word_size <<
" but npy_save appending data sized " <<
sizeof(T) <<
"\n";
245 assert(word_size ==
sizeof(T));
247 if (true_data_shape.size() != shape.size()) {
248 std::cerr <<
"libnpy error: npy_save attempting to append misdimensioned data to " << fname <<
"\n";
249 assert(true_data_shape.size() != shape.size());
252 for (
size_t i = 1; i < shape.size(); ++i) {
253 if (shape[i] != true_data_shape[i]) {
254 std::cerr <<
"libnpy error: npy_save attempting to append misshaped data to " << fname <<
"\n";
255 assert(shape[i] == true_data_shape[i]);
258 true_data_shape[0] += shape[0];
261 fp = fopen(fname.c_str(),
"wb");
262 true_data_shape = shape;
267 size_t nels = std::accumulate(shape.begin(), shape.end(),
static_cast<size_t>(1), std::multiplies<size_t>());
269 fseek(fp, 0, SEEK_SET);
270 fwrite(&header[0],
sizeof(
char), header.size(), fp);
271 fseek(fp, 0, SEEK_END);
272 if (data !=
nullptr) {
273 fwrite(&data[0],
sizeof(T), nels, fp);
291template<
typename T>
void npz_save(
const std::string &zipname, std::string fname,
const T *data,
const std::vector<size_t> &shape,
const std::string &mode =
"w")
299 size_t global_header_offset = 0;
300 std::vector<char> global_header;
302 if (mode ==
"a") fp = fopen(zipname.c_str(),
"r+b");
309 size_t global_header_size;
311 fseek(fp,
static_cast<long>(global_header_offset), SEEK_SET);
312 global_header.resize(global_header_size);
313 size_t res = fread(&global_header[0],
sizeof(
char), global_header_size, fp);
314 if (res != global_header_size) {
315 throw std::runtime_error(
"npz_save: header read error while adding to existing zip");
317 fseek(fp,
static_cast<long>(global_header_offset), SEEK_SET);
320 fp = fopen(zipname.c_str(),
"wb");
326 size_t nels = std::accumulate(shape.begin(), shape.end(),
static_cast<size_t>(1), std::multiplies<size_t>());
327 size_t nbytes = nels*
sizeof(T) + npy_header.size();
330 uint32_t crc = vp_mz_crc32(0L, (uint8_t *)&npy_header[0], npy_header.size());
332 crc = vp_mz_crc32(crc, (uint8_t *)data, nels*
sizeof(T));
336 std::vector<char> local_header;
337 local_header +=
"PK";
338#ifdef VISP_BIG_ENDIAN
351 local_header +=
static_cast<uint16_t
>(0x0403);
352 local_header +=
static_cast<uint16_t
>(20);
353 local_header +=
static_cast<uint16_t
>(0);
354 local_header +=
static_cast<uint16_t
>(0);
355 local_header +=
static_cast<uint16_t
>(0);
356 local_header +=
static_cast<uint16_t
>(0);
357 local_header +=
static_cast<uint32_t
>(crc);
358 local_header +=
static_cast<uint32_t
>(nbytes);
359 local_header +=
static_cast<uint32_t
>(nbytes);
360 local_header +=
static_cast<uint16_t
>(fname.size());
361 local_header +=
static_cast<uint16_t
>(0);
363 local_header += fname;
366 global_header +=
"PK";
367#ifdef VISP_BIG_ENDIAN
370 global_header.insert(global_header.end(), local_header.begin()+4, local_header.begin()+30);
371 global_header +=
static_cast<uint16_t
>(0);
372 global_header +=
static_cast<uint16_t
>(0);
373 global_header +=
static_cast<uint16_t
>(0);
374 global_header +=
static_cast<uint32_t
>(0);
377 global_header +=
static_cast<uint16_t
>(0x0201);
378 global_header +=
static_cast<uint16_t
>(20);
379 global_header.insert(global_header.end(), local_header.begin()+4, local_header.begin()+30);
380 global_header +=
static_cast<uint16_t
>(0);
381 global_header +=
static_cast<uint16_t
>(0);
382 global_header +=
static_cast<uint16_t
>(0);
383 global_header +=
static_cast<uint32_t
>(0);
384 global_header +=
static_cast<uint32_t
>(global_header_offset);
386 global_header += fname;
389 std::vector<char> footer;
391#ifdef VISP_BIG_ENDIAN
393 footer +=
static_cast<uint16_t
>(0);
394 footer +=
static_cast<uint16_t
>(0);
398 footer +=
vpEndian::swap32bits(
static_cast<uint32_t
>(global_header_offset + nbytes + local_header.size()));
400 footer +=
static_cast<uint16_t
>(0x0605);
401 footer +=
static_cast<uint16_t
>(0);
402 footer +=
static_cast<uint16_t
>(0);
403 footer +=
static_cast<uint16_t
>(nrecs+1);
404 footer +=
static_cast<uint16_t
>(nrecs+1);
405 footer +=
static_cast<uint32_t
>(global_header.size());
406 footer +=
static_cast<uint32_t
>(global_header_offset + nbytes + local_header.size());
408 footer +=
static_cast<uint16_t
>(0);
411 fwrite(&local_header[0],
sizeof(
char), local_header.size(), fp);
412 fwrite(&npy_header[0],
sizeof(
char), npy_header.size(), fp);
413 if (data !=
nullptr) {
414 fwrite(&data[0],
sizeof(T), nels, fp);
416 fwrite(&global_header[0],
sizeof(
char), global_header.size(), fp);
417 fwrite(&footer[0],
sizeof(
char), footer.size(), fp);
430template<
typename T>
void npy_save(
const std::string &fname,
const std::vector<T> &data,
const std::string &mode =
"w")
432 std::vector<size_t> shape;
433 shape.push_back(data.size());
434 npy_save(fname, &data[0], shape, mode);
449template<
typename T>
void npz_save(
const std::string &zipname,
const std::string &fname,
const std::vector<T> &data,
const std::string &mode =
"w")
451 std::vector<size_t> shape;
452 shape.push_back(data.size());
453 npz_save(zipname, fname, &data[0], shape, mode);
458 std::vector<char> dict;
459 dict +=
"{'descr': '";
462 dict += std::to_string(
sizeof(T));
463 dict +=
"', 'fortran_order': False, 'shape': (";
464 dict += std::to_string(shape[0]);
465 for (
size_t i = 1; i < shape.size(); ++i) {
467 dict += std::to_string(shape[i]);
469 if (shape.size() == 1) dict +=
",";
472 int remainder = 16 - (10 + dict.size()) % 16;
473 dict.insert(dict.end(), remainder,
' ');
476 std::vector<char> header;
477 header +=
static_cast<char>(0x93);
479 header +=
static_cast<char>(0x01);
480 header +=
static_cast<char>(0x00);
481#ifdef VISP_BIG_ENDIAN
484 header +=
static_cast<uint16_t
>(dict.size());
486 header.insert(header.end(), dict.begin(), dict.end());
611 static std::string
getenv(
const std::string &env);
613 static void getVersion(
const std::string &version,
unsigned int &major,
unsigned int &minor,
unsigned int &patch);
615 static bool checkFifo(
const std::string &filename);
617 static bool copy(
const std::string &src,
const std::string &dst);
618 static std::string
formatString(
const std::string &name,
unsigned int val);
621 static void makeFifo(
const std::string &dirname);
623 static std::string
path(
const std::string &pathname);
625 static bool remove(
const std::string &filename);
626 static bool rename(
const std::string &oldfilename,
const std::string &newfilename);
634 static std::string
toUpperCase(
const std::string &input);
635 static std::string
toLowerCase(
const std::string &input);
638 static std::string
getFileExtension(
const std::string &pathname,
bool checkFile =
false);
639 static long getIndex(
const std::string &filename,
const std::string &format);
640 static std::string
getName(
const std::string &pathname);
641 static std::string
getNameWE(
const std::string &pathname);
642 static std::string
getParent(
const std::string &pathname);
643 static std::string
createFilePath(
const std::string &parent,
const std::string &child);
645 static bool isSamePathname(
const std::string &pathname1,
const std::string &pathname2);
646 static std::pair<std::string, std::string>
splitDrive(
const std::string &pathname);
647 static std::vector<std::string>
splitChain(
const std::string &chain,
const std::string &sep);
648 static std::vector<std::string>
getDirFiles(
const std::string &dirname);
656 static bool readConfigVar(
const std::string &var,
float &value);
657 static bool readConfigVar(
const std::string &var,
double &value);
658 static bool readConfigVar(
const std::string &var,
int &value);
659 static bool readConfigVar(
const std::string &var,
unsigned int &value);
660 static bool readConfigVar(
const std::string &var,
bool &value);
661 static bool readConfigVar(
const std::string &var, std::string &value);
664 const unsigned int &nRows = 0);
668 static void setBaseDir(
const std::string &dir);
669 static void addNameElement(
const std::string &strTrue,
const bool &cond =
true,
const std::string &strFalse =
"");
670 static void addNameElement(
const std::string &strTrue,
const double &val);
694 static std::string
trim(std::string s);
703#ifndef DOXYGEN_SHOULD_SKIP_THIS
704 static int mkdir_p(
const std::string &
path,
int mode);
Implementation of a generic 2D array used as base class for matrices and vectors.
Class to define RGB colors available for display functionalities.
Helpers to convert NPY/NPZ format to/from ViSP format.
VISP_EXPORT npz_t npz_load(const std::string &fname)
VISP_EXPORT char map_type(const std::type_info &t)
std::map< std::string, NpyArray > npz_t
std::vector< char > create_npy_header(const std::vector< size_t > &shape)
std::vector< char > & operator+=(std::vector< char > &lhs, const T rhs)
VISP_EXPORT NpyArray npy_load(const std::string &fname)
VISP_EXPORT void parse_zip_footer(FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
VISP_EXPORT void npz_save(const std::string &zipname, std::string fname, const std::vector< std::string > &data_vec, const std::vector< size_t > &shape, const std::string &mode="w")
void npy_save(const std::string &fname, const T *data, const std::vector< size_t > &shape, const std::string &mode="w")
VISP_EXPORT char BigEndianTest()
VISP_EXPORT void parse_npy_header(FILE *fp, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order, bool &little_endian, char &data_type)
VISP_EXPORT uint32_t swap32bits(uint32_t val)
VISP_EXPORT uint16_t swap16bits(uint16_t val)
std::shared_ptr< std::vector< char > > data_holder
std::vector< size_t > shape
std::vector< T > as_vec() const
NpyArray(const std::vector< size_t > &_shape, size_t _word_size, bool _fortran_order, char _data_type)
std::vector< std::string > as_utf8_string_vec() const