1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 16 // Third party copyrights are property of their respective owners. 17 // 18 // Redistribution and use in source and binary forms, with or without modification, 19 // are permitted provided that the following conditions are met: 20 // 21 // * Redistribution's of source code must retain the above copyright notice, 22 // this list of conditions and the following disclaimer. 23 // 24 // * Redistribution's in binary form must reproduce the above copyright notice, 25 // this list of conditions and the following disclaimer in the documentation 26 // and/or other materials provided with the distribution. 27 // 28 // * The name of the copyright holders may not be used to endorse or promote products 29 // derived from this software without specific prior written permission. 30 // 31 // This software is provided by the copyright holders and contributors "as is" and 32 // any express or implied warranties, including, but not limited to, the implied 33 // warranties of merchantability and fitness for a particular purpose are disclaimed. 34 // In no event shall the Intel Corporation or contributors be liable for any direct, 35 // indirect, incidental, special, exemplary, or consequential damages 36 // (including, but not limited to, procurement of substitute goods or services; 37 // loss of use, data, or profits; or business interruption) however caused 38 // and on any theory of liability, whether in contract, strict liability, 39 // or tort (including negligence or otherwise) arising in any way out of 40 // the use of this software, even if advised of the possibility of such damage. 41 // 42 //M*/ 43 44 #ifndef __OPENCV_CORE_PERSISTENCE_HPP__ 45 #define __OPENCV_CORE_PERSISTENCE_HPP__ 46 47 #ifndef __cplusplus 48 # error persistence.hpp header must be compiled as C++ 49 #endif 50 51 //! @addtogroup core_c 52 //! @{ 53 54 /** @brief "black box" representation of the file storage associated with a file on disk. 55 56 Several functions that are described below take CvFileStorage\* as inputs and allow the user to 57 save or to load hierarchical collections that consist of scalar values, standard CXCore objects 58 (such as matrices, sequences, graphs), and user-defined objects. 59 60 OpenCV can read and write data in XML (<http://www.w3c.org/XML>) or YAML (<http://www.yaml.org>) 61 formats. Below is an example of 3x3 floating-point identity matrix A, stored in XML and YAML files 62 using CXCore functions: 63 XML: 64 @code{.xml} 65 <?xml version="1.0"> 66 <opencv_storage> 67 <A type_id="opencv-matrix"> 68 <rows>3</rows> 69 <cols>3</cols> 70 <dt>f</dt> 71 <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data> 72 </A> 73 </opencv_storage> 74 @endcode 75 YAML: 76 @code{.yaml} 77 %YAML:1.0 78 A: !!opencv-matrix 79 rows: 3 80 cols: 3 81 dt: f 82 data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.] 83 @endcode 84 As it can be seen from the examples, XML uses nested tags to represent hierarchy, while YAML uses 85 indentation for that purpose (similar to the Python programming language). 86 87 The same functions can read and write data in both formats; the particular format is determined by 88 the extension of the opened file, ".xml" for XML files and ".yml" or ".yaml" for YAML. 89 */ 90 typedef struct CvFileStorage CvFileStorage; 91 typedef struct CvFileNode CvFileNode; 92 93 //! @} core_c 94 95 #include "opencv2/core/types.hpp" 96 #include "opencv2/core/mat.hpp" 97 98 namespace cv { 99 100 /** @addtogroup core_xml 101 102 XML/YAML file storages. {#xml_storage} 103 ======================= 104 Writing to a file storage. 105 -------------------------- 106 You can store and then restore various OpenCV data structures to/from XML (<http://www.w3c.org/XML>) 107 or YAML (<http://www.yaml.org>) formats. Also, it is possible store and load arbitrarily complex 108 data structures, which include OpenCV data structures, as well as primitive data types (integer and 109 floating-point numbers and text strings) as their elements. 110 111 Use the following procedure to write something to XML or YAML: 112 -# Create new FileStorage and open it for writing. It can be done with a single call to 113 FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor 114 and then call FileStorage::open. Format of the file (XML or YAML) is determined from the filename 115 extension (".xml" and ".yml"/".yaml", respectively) 116 -# Write all the data you want using the streaming operator `<<`, just like in the case of STL 117 streams. 118 -# Close the file using FileStorage::release. FileStorage destructor also closes the file. 119 120 Here is an example: 121 @code 122 #include "opencv2/opencv.hpp" 123 #include <time.h> 124 125 using namespace cv; 126 127 int main(int, char** argv) 128 { 129 FileStorage fs("test.yml", FileStorage::WRITE); 130 131 fs << "frameCount" << 5; 132 time_t rawtime; time(&rawtime); 133 fs << "calibrationDate" << asctime(localtime(&rawtime)); 134 Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1); 135 Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0); 136 fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs; 137 fs << "features" << "["; 138 for( int i = 0; i < 3; i++ ) 139 { 140 int x = rand() % 640; 141 int y = rand() % 480; 142 uchar lbp = rand() % 256; 143 144 fs << "{:" << "x" << x << "y" << y << "lbp" << "[:"; 145 for( int j = 0; j < 8; j++ ) 146 fs << ((lbp >> j) & 1); 147 fs << "]" << "}"; 148 } 149 fs << "]"; 150 fs.release(); 151 return 0; 152 } 153 @endcode 154 The sample above stores to XML and integer, text string (calibration date), 2 matrices, and a custom 155 structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here 156 is output of the sample: 157 @code{.yaml} 158 %YAML:1.0 159 frameCount: 5 160 calibrationDate: "Fri Jun 17 14:09:29 2011\n" 161 cameraMatrix: !!opencv-matrix 162 rows: 3 163 cols: 3 164 dt: d 165 data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ] 166 distCoeffs: !!opencv-matrix 167 rows: 5 168 cols: 1 169 dt: d 170 data: [ 1.0000000000000001e-01, 1.0000000000000000e-02, 171 -1.0000000000000000e-03, 0., 0. ] 172 features: 173 - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] } 174 - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] } 175 - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] } 176 @endcode 177 178 As an exercise, you can replace ".yml" with ".xml" in the sample above and see, how the 179 corresponding XML file will look like. 180 181 Several things can be noted by looking at the sample code and the output: 182 183 - The produced YAML (and XML) consists of heterogeneous collections that can be nested. There are 2 184 types of collections: named collections (mappings) and unnamed collections (sequences). In mappings 185 each element has a name and is accessed by name. This is similar to structures and std::map in 186 C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by 187 indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python. 188 "Heterogeneous" means that elements of each single collection can have different types. 189 190 Top-level collection in YAML/XML is a mapping. Each matrix is stored as a mapping, and the matrix 191 elements are stored as a sequence. Then, there is a sequence of features, where each feature is 192 represented a mapping, and lbp value in a nested sequence. 193 194 - When you write to a mapping (a structure), you write element name followed by its value. When you 195 write to a sequence, you simply write the elements one by one. OpenCV data structures (such as 196 cv::Mat) are written in absolutely the same way as simple C data structures - using `<<` 197 operator. 198 199 - To write a mapping, you first write the special string `{` to the storage, then write the 200 elements as pairs (`fs << <element_name> << <element_value>`) and then write the closing 201 `}`. 202 203 - To write a sequence, you first write the special string `[`, then write the elements, then 204 write the closing `]`. 205 206 - In YAML (but not XML), mappings and sequences can be written in a compact Python-like inline 207 form. In the sample above matrix elements, as well as each feature, including its lbp value, is 208 stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the 209 opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the 210 data is written to XML, those extra `:` are ignored. 211 212 Reading data from a file storage. 213 --------------------------------- 214 To read the previously written XML or YAML file, do the following: 215 -# Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method. 216 In the current implementation the whole file is parsed and the whole representation of file 217 storage is built in memory as a hierarchy of file nodes (see FileNode) 218 219 -# Read the data you are interested in. Use FileStorage::operator [], FileNode::operator [] 220 and/or FileNodeIterator. 221 222 -# Close the storage using FileStorage::release. 223 224 Here is how to read the file created by the code sample above: 225 @code 226 FileStorage fs2("test.yml", FileStorage::READ); 227 228 // first method: use (type) operator on FileNode. 229 int frameCount = (int)fs2["frameCount"]; 230 231 String date; 232 // second method: use FileNode::operator >> 233 fs2["calibrationDate"] >> date; 234 235 Mat cameraMatrix2, distCoeffs2; 236 fs2["cameraMatrix"] >> cameraMatrix2; 237 fs2["distCoeffs"] >> distCoeffs2; 238 239 cout << "frameCount: " << frameCount << endl 240 << "calibration date: " << date << endl 241 << "camera matrix: " << cameraMatrix2 << endl 242 << "distortion coeffs: " << distCoeffs2 << endl; 243 244 FileNode features = fs2["features"]; 245 FileNodeIterator it = features.begin(), it_end = features.end(); 246 int idx = 0; 247 std::vector<uchar> lbpval; 248 249 // iterate through a sequence using FileNodeIterator 250 for( ; it != it_end; ++it, idx++ ) 251 { 252 cout << "feature #" << idx << ": "; 253 cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: ("; 254 // you can also easily read numerical arrays using FileNode >> std::vector operator. 255 (*it)["lbp"] >> lbpval; 256 for( int i = 0; i < (int)lbpval.size(); i++ ) 257 cout << " " << (int)lbpval[i]; 258 cout << ")" << endl; 259 } 260 fs2.release(); 261 @endcode 262 263 Format specification {#format_spec} 264 -------------------- 265 `([count]{u|c|w|s|i|f|d})`... where the characters correspond to fundamental C++ types: 266 - `u` 8-bit unsigned number 267 - `c` 8-bit signed number 268 - `w` 16-bit unsigned number 269 - `s` 16-bit signed number 270 - `i` 32-bit signed number 271 - `f` single precision floating-point number 272 - `d` double precision floating-point number 273 - `r` pointer, 32 lower bits of which are written as a signed integer. The type can be used to 274 store structures with links between the elements. 275 276 `count` is the optional counter of values of a given type. For example, `2if` means that each array 277 element is a structure of 2 integers, followed by a single-precision floating-point number. The 278 equivalent notations of the above specification are `iif`, `2i1f` and so forth. Other examples: `u` 279 means that the array consists of bytes, and `2d` means the array consists of pairs of doubles. 280 281 @see @ref filestorage.cpp 282 */ 283 284 //! @{ 285 286 /** @example filestorage.cpp 287 A complete example using the FileStorage interface 288 */ 289 290 ////////////////////////// XML & YAML I/O ////////////////////////// 291 292 class CV_EXPORTS FileNode; 293 class CV_EXPORTS FileNodeIterator; 294 295 /** @brief XML/YAML file storage class that encapsulates all the information necessary for writing or reading 296 data to/from a file. 297 */ 298 class CV_EXPORTS_W FileStorage 299 { 300 public: 301 //! file storage mode 302 enum Mode 303 { 304 READ = 0, //!< value, open the file for reading 305 WRITE = 1, //!< value, open the file for writing 306 APPEND = 2, //!< value, open the file for appending 307 MEMORY = 4, //!< flag, read data from source or write data to the internal buffer (which is 308 //!< returned by FileStorage::release) 309 FORMAT_MASK = (7<<3), //!< mask for format flags 310 FORMAT_AUTO = 0, //!< flag, auto format 311 FORMAT_XML = (1<<3), //!< flag, XML format 312 FORMAT_YAML = (2<<3) //!< flag, YAML format 313 }; 314 enum 315 { 316 UNDEFINED = 0, 317 VALUE_EXPECTED = 1, 318 NAME_EXPECTED = 2, 319 INSIDE_MAP = 4 320 }; 321 322 /** @brief The constructors. 323 324 The full constructor opens the file. Alternatively you can use the default constructor and then 325 call FileStorage::open. 326 */ 327 CV_WRAP FileStorage(); 328 329 /** @overload 330 @param source Name of the file to open or the text string to read the data from. Extension of the 331 file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). Also you can append .gz 332 to work with compressed files, for example myHugeMatrix.xml.gz. If both FileStorage::WRITE and 333 FileStorage::MEMORY flags are specified, source is used just to specify the output file format (e.g. 334 mydata.xml, .yml etc.). 335 @param flags Mode of operation. See FileStorage::Mode 336 @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and 337 you should use 8-bit encoding instead of it. 338 */ 339 CV_WRAP FileStorage(const String& source, int flags, const String& encoding=String()); 340 341 /** @overload */ 342 FileStorage(CvFileStorage* fs, bool owning=true); 343 344 //! the destructor. calls release() 345 virtual ~FileStorage(); 346 347 /** @brief Opens a file. 348 349 See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release 350 before opening the file. 351 @param filename Name of the file to open or the text string to read the data from. 352 Extension of the file (.xml or .yml/.yaml) determines its format (XML or YAML respectively). 353 Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both 354 FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify 355 the output file format (e.g. mydata.xml, .yml etc.). 356 @param flags Mode of operation. One of FileStorage::Mode 357 @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and 358 you should use 8-bit encoding instead of it. 359 */ 360 CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String()); 361 362 /** @brief Checks whether the file is opened. 363 364 @returns true if the object is associated with the current file and false otherwise. It is a 365 good practice to call this method after you tried to open a file. 366 */ 367 CV_WRAP virtual bool isOpened() const; 368 369 /** @brief Closes the file and releases all the memory buffers. 370 371 Call this method after all I/O operations with the storage are finished. 372 */ 373 CV_WRAP virtual void release(); 374 375 /** @brief Closes the file and releases all the memory buffers. 376 377 Call this method after all I/O operations with the storage are finished. If the storage was 378 opened for writing data and FileStorage::WRITE was specified 379 */ 380 CV_WRAP virtual String releaseAndGetString(); 381 382 /** @brief Returns the first element of the top-level mapping. 383 @returns The first element of the top-level mapping. 384 */ 385 CV_WRAP FileNode getFirstTopLevelNode() const; 386 387 /** @brief Returns the top-level mapping 388 @param streamidx Zero-based index of the stream. In most cases there is only one stream in the file. 389 However, YAML supports multiple streams and so there can be several. 390 @returns The top-level mapping. 391 */ 392 CV_WRAP FileNode root(int streamidx=0) const; 393 394 /** @brief Returns the specified element of the top-level mapping. 395 @param nodename Name of the file node. 396 @returns Node with the given name. 397 */ 398 FileNode operator[](const String& nodename) const; 399 400 /** @overload */ 401 CV_WRAP FileNode operator[](const char* nodename) const; 402 403 /** @brief Returns the obsolete C FileStorage structure. 404 @returns Pointer to the underlying C FileStorage structure 405 */ 406 CvFileStorage* operator *() { return fs.get(); } 407 408 /** @overload */ 409 const CvFileStorage* operator *() const { return fs.get(); } 410 411 /** @brief Writes multiple numbers. 412 413 Writes one or more numbers of the specified format to the currently written structure. Usually it is 414 more convenient to use operator `<<` instead of this method. 415 @param fmt Specification of each array element, see @ref format_spec "format specification" 416 @param vec Pointer to the written array. 417 @param len Number of the uchar elements to write. 418 */ 419 void writeRaw( const String& fmt, const uchar* vec, size_t len ); 420 421 /** @brief Writes the registered C structure (CvMat, CvMatND, CvSeq). 422 @param name Name of the written object. 423 @param obj Pointer to the object. 424 @see ocvWrite for details. 425 */ 426 void writeObj( const String& name, const void* obj ); 427 428 /** @brief Returns the normalized object name for the specified name of a file. 429 @param filename Name of a file 430 @returns The normalized object name. 431 */ 432 static String getDefaultObjectName(const String& filename); 433 434 Ptr<CvFileStorage> fs; //!< the underlying C FileStorage structure 435 String elname; //!< the currently written element 436 std::vector<char> structs; //!< the stack of written structures 437 int state; //!< the writer state 438 }; 439 440 template<> CV_EXPORTS void DefaultDeleter<CvFileStorage>::operator ()(CvFileStorage* obj) const; 441 442 /** @brief File Storage Node class. 443 444 The node is used to store each and every element of the file storage opened for reading. When 445 XML/YAML file is read, it is first parsed and stored in the memory as a hierarchical collection of 446 nodes. Each node can be a leaf that is contain a single number or a string, or be a collection of 447 other nodes. There can be named collections (mappings) where each element has a name and it is 448 accessed by a name, and ordered collections (sequences) where elements do not have names but rather 449 accessed by index. Type of the file node can be determined using FileNode::type method. 450 451 Note that file nodes are only used for navigating file storages opened for reading. When a file 452 storage is opened for writing, no data is stored in memory after it is written. 453 */ 454 class CV_EXPORTS_W_SIMPLE FileNode 455 { 456 public: 457 //! type of the file storage node 458 enum Type 459 { 460 NONE = 0, //!< empty node 461 INT = 1, //!< an integer 462 REAL = 2, //!< floating-point number 463 FLOAT = REAL, //!< synonym or REAL 464 STR = 3, //!< text string in UTF-8 encoding 465 STRING = STR, //!< synonym for STR 466 REF = 4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others 467 SEQ = 5, //!< sequence 468 MAP = 6, //!< mapping 469 TYPE_MASK = 7, 470 FLOW = 8, //!< compact representation of a sequence or mapping. Used only by YAML writer 471 USER = 16, //!< a registered object (e.g. a matrix) 472 EMPTY = 32, //!< empty structure (sequence or mapping) 473 NAMED = 64 //!< the node has a name (i.e. it is element of a mapping) 474 }; 475 /** @brief The constructors. 476 477 These constructors are used to create a default file node, construct it from obsolete structures or 478 from the another file node. 479 */ 480 CV_WRAP FileNode(); 481 482 /** @overload 483 @param fs Pointer to the obsolete file storage structure. 484 @param node File node to be used as initialization for the created file node. 485 */ 486 FileNode(const CvFileStorage* fs, const CvFileNode* node); 487 488 /** @overload 489 @param node File node to be used as initialization for the created file node. 490 */ 491 FileNode(const FileNode& node); 492 493 /** @brief Returns element of a mapping node or a sequence node. 494 @param nodename Name of an element in the mapping node. 495 @returns Returns the element with the given identifier. 496 */ 497 FileNode operator[](const String& nodename) const; 498 499 /** @overload 500 @param nodename Name of an element in the mapping node. 501 */ 502 CV_WRAP FileNode operator[](const char* nodename) const; 503 504 /** @overload 505 @param i Index of an element in the sequence node. 506 */ 507 CV_WRAP FileNode operator[](int i) const; 508 509 /** @brief Returns type of the node. 510 @returns Type of the node. See FileNode::Type 511 */ 512 CV_WRAP int type() const; 513 514 //! returns true if the node is empty 515 CV_WRAP bool empty() const; 516 //! returns true if the node is a "none" object 517 CV_WRAP bool isNone() const; 518 //! returns true if the node is a sequence 519 CV_WRAP bool isSeq() const; 520 //! returns true if the node is a mapping 521 CV_WRAP bool isMap() const; 522 //! returns true if the node is an integer 523 CV_WRAP bool isInt() const; 524 //! returns true if the node is a floating-point number 525 CV_WRAP bool isReal() const; 526 //! returns true if the node is a text string 527 CV_WRAP bool isString() const; 528 //! returns true if the node has a name 529 CV_WRAP bool isNamed() const; 530 //! returns the node name or an empty string if the node is nameless 531 CV_WRAP String name() const; 532 //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise. 533 CV_WRAP size_t size() const; 534 //! returns the node content as an integer. If the node stores floating-point number, it is rounded. 535 operator int() const; 536 //! returns the node content as float 537 operator float() const; 538 //! returns the node content as double 539 operator double() const; 540 //! returns the node content as text string 541 operator String() const; 542 #ifndef OPENCV_NOSTL 543 operator std::string() const; 544 #endif 545 546 //! returns pointer to the underlying file node 547 CvFileNode* operator *(); 548 //! returns pointer to the underlying file node 549 const CvFileNode* operator* () const; 550 551 //! returns iterator pointing to the first node element 552 FileNodeIterator begin() const; 553 //! returns iterator pointing to the element following the last node element 554 FileNodeIterator end() const; 555 556 /** @brief Reads node elements to the buffer with the specified format. 557 558 Usually it is more convenient to use operator `>>` instead of this method. 559 @param fmt Specification of each array element. See @ref format_spec "format specification" 560 @param vec Pointer to the destination array. 561 @param len Number of elements to read. If it is greater than number of remaining elements then all 562 of them will be read. 563 */ 564 void readRaw( const String& fmt, uchar* vec, size_t len ) const; 565 566 //! reads the registered object and returns pointer to it 567 void* readObj() const; 568 569 // do not use wrapper pointer classes for better efficiency 570 const CvFileStorage* fs; 571 const CvFileNode* node; 572 }; 573 574 575 /** @brief used to iterate through sequences and mappings. 576 577 A standard STL notation, with node.begin(), node.end() denoting the beginning and the end of a 578 sequence, stored in node. See the data reading sample in the beginning of the section. 579 */ 580 class CV_EXPORTS FileNodeIterator 581 { 582 public: 583 /** @brief The constructors. 584 585 These constructors are used to create a default iterator, set it to specific element in a file node 586 or construct it from another iterator. 587 */ 588 FileNodeIterator(); 589 590 /** @overload 591 @param fs File storage for the iterator. 592 @param node File node for the iterator. 593 @param ofs Index of the element in the node. The created iterator will point to this element. 594 */ 595 FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0); 596 597 /** @overload 598 @param it Iterator to be used as initialization for the created iterator. 599 */ 600 FileNodeIterator(const FileNodeIterator& it); 601 602 //! returns the currently observed element 603 FileNode operator *() const; 604 //! accesses the currently observed element methods 605 FileNode operator ->() const; 606 607 //! moves iterator to the next node 608 FileNodeIterator& operator ++ (); 609 //! moves iterator to the next node 610 FileNodeIterator operator ++ (int); 611 //! moves iterator to the previous node 612 FileNodeIterator& operator -- (); 613 //! moves iterator to the previous node 614 FileNodeIterator operator -- (int); 615 //! moves iterator forward by the specified offset (possibly negative) 616 FileNodeIterator& operator += (int ofs); 617 //! moves iterator backward by the specified offset (possibly negative) 618 FileNodeIterator& operator -= (int ofs); 619 620 /** @brief Reads node elements to the buffer with the specified format. 621 622 Usually it is more convenient to use operator `>>` instead of this method. 623 @param fmt Specification of each array element. See @ref format_spec "format specification" 624 @param vec Pointer to the destination array. 625 @param maxCount Number of elements to read. If it is greater than number of remaining elements then 626 all of them will be read. 627 */ 628 FileNodeIterator& readRaw( const String& fmt, uchar* vec, 629 size_t maxCount=(size_t)INT_MAX ); 630 631 struct SeqReader 632 { 633 int header_size; 634 void* seq; /* sequence, beign read; CvSeq */ 635 void* block; /* current block; CvSeqBlock */ 636 schar* ptr; /* pointer to element be read next */ 637 schar* block_min; /* pointer to the beginning of block */ 638 schar* block_max; /* pointer to the end of block */ 639 int delta_index;/* = seq->first->start_index */ 640 schar* prev_elem; /* pointer to previous element */ 641 }; 642 643 const CvFileStorage* fs; 644 const CvFileNode* container; 645 SeqReader reader; 646 size_t remaining; 647 }; 648 649 //! @} core_xml 650 651 /////////////////// XML & YAML I/O implementation ////////////////// 652 653 //! @relates cv::FileStorage 654 //! @{ 655 656 CV_EXPORTS void write( FileStorage& fs, const String& name, int value ); 657 CV_EXPORTS void write( FileStorage& fs, const String& name, float value ); 658 CV_EXPORTS void write( FileStorage& fs, const String& name, double value ); 659 CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value ); 660 CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value ); 661 CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value ); 662 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& value); 663 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DMatch>& value); 664 665 CV_EXPORTS void writeScalar( FileStorage& fs, int value ); 666 CV_EXPORTS void writeScalar( FileStorage& fs, float value ); 667 CV_EXPORTS void writeScalar( FileStorage& fs, double value ); 668 CV_EXPORTS void writeScalar( FileStorage& fs, const String& value ); 669 670 //! @} 671 672 //! @relates cv::FileNode 673 //! @{ 674 675 CV_EXPORTS void read(const FileNode& node, int& value, int default_value); 676 CV_EXPORTS void read(const FileNode& node, float& value, float default_value); 677 CV_EXPORTS void read(const FileNode& node, double& value, double default_value); 678 CV_EXPORTS void read(const FileNode& node, String& value, const String& default_value); 679 CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() ); 680 CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() ); 681 CV_EXPORTS void read(const FileNode& node, std::vector<KeyPoint>& keypoints); 682 CV_EXPORTS void read(const FileNode& node, std::vector<DMatch>& matches); 683 684 template<typename _Tp> static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value) 685 { 686 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 687 value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); 688 } 689 690 template<typename _Tp> static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value) 691 { 692 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 693 value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), 694 saturate_cast<_Tp>(temp[2])); 695 } 696 697 template<typename _Tp> static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value) 698 { 699 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 700 value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); 701 } 702 703 template<typename _Tp> static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value) 704 { 705 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 706 value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1])); 707 } 708 709 template<typename _Tp> static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value) 710 { 711 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 712 value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), 713 saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); 714 } 715 716 template<typename _Tp, int cn> static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value) 717 { 718 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 719 value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]); 720 } 721 722 template<typename _Tp> static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value) 723 { 724 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp; 725 value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]), 726 saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3])); 727 } 728 729 static inline void read(const FileNode& node, Range& value, const Range& default_value) 730 { 731 Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end); 732 read(node, temp, default_temp); 733 value.start = temp.x; value.end = temp.y; 734 } 735 736 //! @} 737 738 /** @brief Writes string to a file storage. 739 @relates cv::FileStorage 740 */ 741 CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str); 742 743 //! @cond IGNORED 744 745 namespace internal 746 { 747 class CV_EXPORTS WriteStructContext 748 { 749 public: 750 WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String()); 751 ~WriteStructContext(); 752 private: 753 FileStorage* fs; 754 }; 755 756 template<typename _Tp, int numflag> class VecWriterProxy 757 { 758 public: 759 VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} 760 void operator()(const std::vector<_Tp>& vec) const 761 { 762 size_t count = vec.size(); 763 for (size_t i = 0; i < count; i++) 764 write(*fs, vec[i]); 765 } 766 private: 767 FileStorage* fs; 768 }; 769 770 template<typename _Tp> class VecWriterProxy<_Tp, 1> 771 { 772 public: 773 VecWriterProxy( FileStorage* _fs ) : fs(_fs) {} 774 void operator()(const std::vector<_Tp>& vec) const 775 { 776 int _fmt = DataType<_Tp>::fmt; 777 char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' }; 778 fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp)); 779 } 780 private: 781 FileStorage* fs; 782 }; 783 784 template<typename _Tp, int numflag> class VecReaderProxy 785 { 786 public: 787 VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} 788 void operator()(std::vector<_Tp>& vec, size_t count) const 789 { 790 count = std::min(count, it->remaining); 791 vec.resize(count); 792 for (size_t i = 0; i < count; i++, ++(*it)) 793 read(**it, vec[i], _Tp()); 794 } 795 private: 796 FileNodeIterator* it; 797 }; 798 799 template<typename _Tp> class VecReaderProxy<_Tp, 1> 800 { 801 public: 802 VecReaderProxy( FileNodeIterator* _it ) : it(_it) {} 803 void operator()(std::vector<_Tp>& vec, size_t count) const 804 { 805 size_t remaining = it->remaining; 806 size_t cn = DataType<_Tp>::channels; 807 int _fmt = DataType<_Tp>::fmt; 808 char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' }; 809 size_t remaining1 = remaining / cn; 810 count = count < remaining1 ? count : remaining1; 811 vec.resize(count); 812 it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp)); 813 } 814 private: 815 FileNodeIterator* it; 816 }; 817 818 } // internal 819 820 //! @endcond 821 822 //! @relates cv::FileStorage 823 //! @{ 824 825 template<typename _Tp> static inline 826 void write(FileStorage& fs, const _Tp& value) 827 { 828 write(fs, String(), value); 829 } 830 831 template<> inline 832 void write( FileStorage& fs, const int& value ) 833 { 834 writeScalar(fs, value); 835 } 836 837 template<> inline 838 void write( FileStorage& fs, const float& value ) 839 { 840 writeScalar(fs, value); 841 } 842 843 template<> inline 844 void write( FileStorage& fs, const double& value ) 845 { 846 writeScalar(fs, value); 847 } 848 849 template<> inline 850 void write( FileStorage& fs, const String& value ) 851 { 852 writeScalar(fs, value); 853 } 854 855 template<typename _Tp> static inline 856 void write(FileStorage& fs, const Point_<_Tp>& pt ) 857 { 858 write(fs, pt.x); 859 write(fs, pt.y); 860 } 861 862 template<typename _Tp> static inline 863 void write(FileStorage& fs, const Point3_<_Tp>& pt ) 864 { 865 write(fs, pt.x); 866 write(fs, pt.y); 867 write(fs, pt.z); 868 } 869 870 template<typename _Tp> static inline 871 void write(FileStorage& fs, const Size_<_Tp>& sz ) 872 { 873 write(fs, sz.width); 874 write(fs, sz.height); 875 } 876 877 template<typename _Tp> static inline 878 void write(FileStorage& fs, const Complex<_Tp>& c ) 879 { 880 write(fs, c.re); 881 write(fs, c.im); 882 } 883 884 template<typename _Tp> static inline 885 void write(FileStorage& fs, const Rect_<_Tp>& r ) 886 { 887 write(fs, r.x); 888 write(fs, r.y); 889 write(fs, r.width); 890 write(fs, r.height); 891 } 892 893 template<typename _Tp, int cn> static inline 894 void write(FileStorage& fs, const Vec<_Tp, cn>& v ) 895 { 896 for(int i = 0; i < cn; i++) 897 write(fs, v.val[i]); 898 } 899 900 template<typename _Tp> static inline 901 void write(FileStorage& fs, const Scalar_<_Tp>& s ) 902 { 903 write(fs, s.val[0]); 904 write(fs, s.val[1]); 905 write(fs, s.val[2]); 906 write(fs, s.val[3]); 907 } 908 909 static inline 910 void write(FileStorage& fs, const Range& r ) 911 { 912 write(fs, r.start); 913 write(fs, r.end); 914 } 915 916 template<typename _Tp> static inline 917 void write( FileStorage& fs, const std::vector<_Tp>& vec ) 918 { 919 cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs); 920 w(vec); 921 } 922 923 924 template<typename _Tp> static inline 925 void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt ) 926 { 927 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 928 write(fs, pt); 929 } 930 931 template<typename _Tp> static inline 932 void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt ) 933 { 934 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 935 write(fs, pt); 936 } 937 938 template<typename _Tp> static inline 939 void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz ) 940 { 941 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 942 write(fs, sz); 943 } 944 945 template<typename _Tp> static inline 946 void write(FileStorage& fs, const String& name, const Complex<_Tp>& c ) 947 { 948 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 949 write(fs, c); 950 } 951 952 template<typename _Tp> static inline 953 void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r ) 954 { 955 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 956 write(fs, r); 957 } 958 959 template<typename _Tp, int cn> static inline 960 void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v ) 961 { 962 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 963 write(fs, v); 964 } 965 966 template<typename _Tp> static inline 967 void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s ) 968 { 969 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 970 write(fs, s); 971 } 972 973 static inline 974 void write(FileStorage& fs, const String& name, const Range& r ) 975 { 976 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW); 977 write(fs, r); 978 } 979 980 template<typename _Tp> static inline 981 void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec ) 982 { 983 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0)); 984 write(fs, vec); 985 } 986 987 //! @} FileStorage 988 989 //! @relates cv::FileNode 990 //! @{ 991 992 static inline 993 void read(const FileNode& node, bool& value, bool default_value) 994 { 995 int temp; 996 read(node, temp, (int)default_value); 997 value = temp != 0; 998 } 999 1000 static inline 1001 void read(const FileNode& node, uchar& value, uchar default_value) 1002 { 1003 int temp; 1004 read(node, temp, (int)default_value); 1005 value = saturate_cast<uchar>(temp); 1006 } 1007 1008 static inline 1009 void read(const FileNode& node, schar& value, schar default_value) 1010 { 1011 int temp; 1012 read(node, temp, (int)default_value); 1013 value = saturate_cast<schar>(temp); 1014 } 1015 1016 static inline 1017 void read(const FileNode& node, ushort& value, ushort default_value) 1018 { 1019 int temp; 1020 read(node, temp, (int)default_value); 1021 value = saturate_cast<ushort>(temp); 1022 } 1023 1024 static inline 1025 void read(const FileNode& node, short& value, short default_value) 1026 { 1027 int temp; 1028 read(node, temp, (int)default_value); 1029 value = saturate_cast<short>(temp); 1030 } 1031 1032 template<typename _Tp> static inline 1033 void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX ) 1034 { 1035 cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); 1036 r(vec, maxCount); 1037 } 1038 1039 template<typename _Tp> static inline 1040 void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() ) 1041 { 1042 if(!node.node) 1043 vec = default_value; 1044 else 1045 { 1046 FileNodeIterator it = node.begin(); 1047 read( it, vec ); 1048 } 1049 } 1050 1051 //! @} FileNode 1052 1053 //! @relates cv::FileStorage 1054 //! @{ 1055 1056 /** @brief Writes data to a file storage. 1057 */ 1058 template<typename _Tp> static inline 1059 FileStorage& operator << (FileStorage& fs, const _Tp& value) 1060 { 1061 if( !fs.isOpened() ) 1062 return fs; 1063 if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP ) 1064 CV_Error( Error::StsError, "No element name has been given" ); 1065 write( fs, fs.elname, value ); 1066 if( fs.state & FileStorage::INSIDE_MAP ) 1067 fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP; 1068 return fs; 1069 } 1070 1071 /** @brief Writes data to a file storage. 1072 */ 1073 static inline 1074 FileStorage& operator << (FileStorage& fs, const char* str) 1075 { 1076 return (fs << String(str)); 1077 } 1078 1079 /** @brief Writes data to a file storage. 1080 */ 1081 static inline 1082 FileStorage& operator << (FileStorage& fs, char* value) 1083 { 1084 return (fs << String(value)); 1085 } 1086 1087 //! @} FileStorage 1088 1089 //! @relates cv::FileNodeIterator 1090 //! @{ 1091 1092 /** @brief Reads data from a file storage. 1093 */ 1094 template<typename _Tp> static inline 1095 FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value) 1096 { 1097 read( *it, value, _Tp()); 1098 return ++it; 1099 } 1100 1101 /** @brief Reads data from a file storage. 1102 */ 1103 template<typename _Tp> static inline 1104 FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec) 1105 { 1106 cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it); 1107 r(vec, (size_t)INT_MAX); 1108 return it; 1109 } 1110 1111 //! @} FileNodeIterator 1112 1113 //! @relates cv::FileNode 1114 //! @{ 1115 1116 /** @brief Reads data from a file storage. 1117 */ 1118 template<typename _Tp> static inline 1119 void operator >> (const FileNode& n, _Tp& value) 1120 { 1121 read( n, value, _Tp()); 1122 } 1123 1124 /** @brief Reads data from a file storage. 1125 */ 1126 template<typename _Tp> static inline 1127 void operator >> (const FileNode& n, std::vector<_Tp>& vec) 1128 { 1129 FileNodeIterator it = n.begin(); 1130 it >> vec; 1131 } 1132 1133 //! @} FileNode 1134 1135 //! @relates cv::FileNodeIterator 1136 //! @{ 1137 1138 static inline 1139 bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2) 1140 { 1141 return it1.fs == it2.fs && it1.container == it2.container && 1142 it1.reader.ptr == it2.reader.ptr && it1.remaining == it2.remaining; 1143 } 1144 1145 static inline 1146 bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2) 1147 { 1148 return !(it1 == it2); 1149 } 1150 1151 static inline 1152 ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2) 1153 { 1154 return it2.remaining - it1.remaining; 1155 } 1156 1157 static inline 1158 bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2) 1159 { 1160 return it1.remaining > it2.remaining; 1161 } 1162 1163 //! @} FileNodeIterator 1164 1165 //! @cond IGNORED 1166 1167 inline FileNode FileStorage::getFirstTopLevelNode() const { FileNode r = root(); FileNodeIterator it = r.begin(); return it != r.end() ? *it : FileNode(); } 1168 inline FileNode::FileNode() : fs(0), node(0) {} 1169 inline FileNode::FileNode(const CvFileStorage* _fs, const CvFileNode* _node) : fs(_fs), node(_node) {} 1170 inline FileNode::FileNode(const FileNode& _node) : fs(_node.fs), node(_node.node) {} 1171 inline bool FileNode::empty() const { return node == 0; } 1172 inline bool FileNode::isNone() const { return type() == NONE; } 1173 inline bool FileNode::isSeq() const { return type() == SEQ; } 1174 inline bool FileNode::isMap() const { return type() == MAP; } 1175 inline bool FileNode::isInt() const { return type() == INT; } 1176 inline bool FileNode::isReal() const { return type() == REAL; } 1177 inline bool FileNode::isString() const { return type() == STR; } 1178 inline CvFileNode* FileNode::operator *() { return (CvFileNode*)node; } 1179 inline const CvFileNode* FileNode::operator* () const { return node; } 1180 inline FileNode::operator int() const { int value; read(*this, value, 0); return value; } 1181 inline FileNode::operator float() const { float value; read(*this, value, 0.f); return value; } 1182 inline FileNode::operator double() const { double value; read(*this, value, 0.); return value; } 1183 inline FileNode::operator String() const { String value; read(*this, value, value); return value; } 1184 inline FileNodeIterator FileNode::begin() const { return FileNodeIterator(fs, node); } 1185 inline FileNodeIterator FileNode::end() const { return FileNodeIterator(fs, node, size()); } 1186 inline void FileNode::readRaw( const String& fmt, uchar* vec, size_t len ) const { begin().readRaw( fmt, vec, len ); } 1187 inline FileNode FileNodeIterator::operator *() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); } 1188 inline FileNode FileNodeIterator::operator ->() const { return FileNode(fs, (const CvFileNode*)(const void*)reader.ptr); } 1189 inline String::String(const FileNode& fn): cstr_(0), len_(0) { read(fn, *this, *this); } 1190 1191 //! @endcond 1192 1193 } // cv 1194 1195 #endif // __OPENCV_CORE_PERSISTENCE_HPP__ 1196