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 CV_DOXYGEN
48 /// Define to support persistence legacy formats
49 #define CV__LEGACY_PERSISTENCE
50 #endif
51
52 #ifndef __cplusplus
53 # error persistence.hpp header must be compiled as C++
54 #endif
55
56 //! @addtogroup core_c
57 //! @{
58
59 /** @brief "black box" representation of the file storage associated with a file on disk.
60
61 Several functions that are described below take CvFileStorage\* as inputs and allow the user to
62 save or to load hierarchical collections that consist of scalar values, standard CXCore objects
63 (such as matrices, sequences, graphs), and user-defined objects.
64
65 OpenCV can read and write data in XML (<http://www.w3c.org/XML>), YAML (<http://www.yaml.org>) or
66 JSON (<http://www.json.org/>) formats. Below is an example of 3x3 floating-point identity matrix A,
67 stored in XML and YAML files
68 using CXCore functions:
69 XML:
70 @code{.xml}
71 <?xml version="1.0">
72 <opencv_storage>
73 <A type_id="opencv-matrix">
74 <rows>3</rows>
75 <cols>3</cols>
76 <dt>f</dt>
77 <data>1. 0. 0. 0. 1. 0. 0. 0. 1.</data>
78 </A>
79 </opencv_storage>
80 @endcode
81 YAML:
82 @code{.yaml}
83 %YAML:1.0
84 A: !!opencv-matrix
85 rows: 3
86 cols: 3
87 dt: f
88 data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1.]
89 @endcode
90 As it can be seen from the examples, XML uses nested tags to represent hierarchy, while YAML uses
91 indentation for that purpose (similar to the Python programming language).
92
93 The same functions can read and write data in both formats; the particular format is determined by
94 the extension of the opened file, ".xml" for XML files, ".yml" or ".yaml" for YAML and ".json" for
95 JSON.
96 */
97
98 //! @} core_c
99
100 #include "opencv2/core/types.hpp"
101 #include "opencv2/core/mat.hpp"
102
103 namespace cv {
104
105 /** @addtogroup core_xml
106
107 XML/YAML/JSON file storages. {#xml_storage}
108 =======================
109 Writing to a file storage.
110 --------------------------
111 You can store and then restore various OpenCV data structures to/from XML (<http://www.w3c.org/XML>),
112 YAML (<http://www.yaml.org>) or JSON (<http://www.json.org/>) formats. Also, it is possible to store
113 and load arbitrarily complex data structures, which include OpenCV data structures, as well as
114 primitive data types (integer and floating-point numbers and text strings) as their elements.
115
116 Use the following procedure to write something to XML, YAML or JSON:
117 -# Create new FileStorage and open it for writing. It can be done with a single call to
118 FileStorage::FileStorage constructor that takes a filename, or you can use the default constructor
119 and then call FileStorage::open. Format of the file (XML, YAML or JSON) is determined from the filename
120 extension (".xml", ".yml"/".yaml" and ".json", respectively)
121 -# Write all the data you want using the streaming operator `<<`, just like in the case of STL
122 streams.
123 -# Close the file using FileStorage::release. FileStorage destructor also closes the file.
124
125 Here is an example:
126 @code
127 #include "opencv2/core.hpp"
128 #include <time.h>
129
130 using namespace cv;
131
132 int main(int, char** argv)
133 {
134 FileStorage fs("test.yml", FileStorage::WRITE);
135
136 fs << "frameCount" << 5;
137 time_t rawtime; time(&rawtime);
138 fs << "calibrationDate" << asctime(localtime(&rawtime));
139 Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
140 Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
141 fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
142 fs << "features" << "[";
143 for( int i = 0; i < 3; i++ )
144 {
145 int x = rand() % 640;
146 int y = rand() % 480;
147 uchar lbp = rand() % 256;
148
149 fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
150 for( int j = 0; j < 8; j++ )
151 fs << ((lbp >> j) & 1);
152 fs << "]" << "}";
153 }
154 fs << "]";
155 fs.release();
156 return 0;
157 }
158 @endcode
159 The sample above stores to YML an integer, a text string (calibration date), 2 matrices, and a custom
160 structure "feature", which includes feature coordinates and LBP (local binary pattern) value. Here
161 is output of the sample:
162 @code{.yaml}
163 %YAML:1.0
164 frameCount: 5
165 calibrationDate: "Fri Jun 17 14:09:29 2011\n"
166 cameraMatrix: !!opencv-matrix
167 rows: 3
168 cols: 3
169 dt: d
170 data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
171 distCoeffs: !!opencv-matrix
172 rows: 5
173 cols: 1
174 dt: d
175 data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
176 -1.0000000000000000e-03, 0., 0. ]
177 features:
178 - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
179 - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
180 - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }
181 @endcode
182
183 As an exercise, you can replace ".yml" with ".xml" or ".json" in the sample above and see, how the
184 corresponding XML file will look like.
185
186 Several things can be noted by looking at the sample code and the output:
187
188 - The produced YAML (and XML/JSON) consists of heterogeneous collections that can be nested. There are
189 2 types of collections: named collections (mappings) and unnamed collections (sequences). In mappings
190 each element has a name and is accessed by name. This is similar to structures and std::map in
191 C/C++ and dictionaries in Python. In sequences elements do not have names, they are accessed by
192 indices. This is similar to arrays and std::vector in C/C++ and lists, tuples in Python.
193 "Heterogeneous" means that elements of each single collection can have different types.
194
195 Top-level collection in YAML/XML/JSON is a mapping. Each matrix is stored as a mapping, and the matrix
196 elements are stored as a sequence. Then, there is a sequence of features, where each feature is
197 represented a mapping, and lbp value in a nested sequence.
198
199 - When you write to a mapping (a structure), you write element name followed by its value. When you
200 write to a sequence, you simply write the elements one by one. OpenCV data structures (such as
201 cv::Mat) are written in absolutely the same way as simple C data structures - using `<<`
202 operator.
203
204 - To write a mapping, you first write the special string `{` to the storage, then write the
205 elements as pairs (`fs << <element_name> << <element_value>`) and then write the closing
206 `}`.
207
208 - To write a sequence, you first write the special string `[`, then write the elements, then
209 write the closing `]`.
210
211 - In YAML/JSON (but not XML), mappings and sequences can be written in a compact Python-like inline
212 form. In the sample above matrix elements, as well as each feature, including its lbp value, is
213 stored in such inline form. To store a mapping/sequence in a compact form, put `:` after the
214 opening character, e.g. use `{:` instead of `{` and `[:` instead of `[`. When the
215 data is written to XML, those extra `:` are ignored.
216
217 Reading data from a file storage.
218 ---------------------------------
219 To read the previously written XML, YAML or JSON file, do the following:
220 -# Open the file storage using FileStorage::FileStorage constructor or FileStorage::open method.
221 In the current implementation the whole file is parsed and the whole representation of file
222 storage is built in memory as a hierarchy of file nodes (see FileNode)
223
224 -# Read the data you are interested in. Use FileStorage::operator [], FileNode::operator []
225 and/or FileNodeIterator.
226
227 -# Close the storage using FileStorage::release.
228
229 Here is how to read the file created by the code sample above:
230 @code
231 FileStorage fs2("test.yml", FileStorage::READ);
232
233 // first method: use (type) operator on FileNode.
234 int frameCount = (int)fs2["frameCount"];
235
236 String date;
237 // second method: use FileNode::operator >>
238 fs2["calibrationDate"] >> date;
239
240 Mat cameraMatrix2, distCoeffs2;
241 fs2["cameraMatrix"] >> cameraMatrix2;
242 fs2["distCoeffs"] >> distCoeffs2;
243
244 cout << "frameCount: " << frameCount << endl
245 << "calibration date: " << date << endl
246 << "camera matrix: " << cameraMatrix2 << endl
247 << "distortion coeffs: " << distCoeffs2 << endl;
248
249 FileNode features = fs2["features"];
250 FileNodeIterator it = features.begin(), it_end = features.end();
251 int idx = 0;
252 std::vector<uchar> lbpval;
253
254 // iterate through a sequence using FileNodeIterator
255 for( ; it != it_end; ++it, idx++ )
256 {
257 cout << "feature #" << idx << ": ";
258 cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
259 // you can also easily read numerical arrays using FileNode >> std::vector operator.
260 (*it)["lbp"] >> lbpval;
261 for( int i = 0; i < (int)lbpval.size(); i++ )
262 cout << " " << (int)lbpval[i];
263 cout << ")" << endl;
264 }
265 fs2.release();
266 @endcode
267
268 Format specification {#format_spec}
269 --------------------
270 `([count]{u|c|w|s|i|f|d})`... where the characters correspond to fundamental C++ types:
271 - `u` 8-bit unsigned number
272 - `c` 8-bit signed number
273 - `w` 16-bit unsigned number
274 - `s` 16-bit signed number
275 - `i` 32-bit signed number
276 - `f` single precision floating-point number
277 - `d` double precision floating-point number
278 - `r` pointer, 32 lower bits of which are written as a signed integer. The type can be used to
279 store structures with links between the elements.
280
281 `count` is the optional counter of values of a given type. For example, `2if` means that each array
282 element is a structure of 2 integers, followed by a single-precision floating-point number. The
283 equivalent notations of the above specification are `iif`, `2i1f` and so forth. Other examples: `u`
284 means that the array consists of bytes, and `2d` means the array consists of pairs of doubles.
285
286 @see @ref samples/cpp/filestorage.cpp
287 */
288
289 //! @{
290
291 /** @example samples/cpp/filestorage.cpp
292 A complete example using the FileStorage interface
293 */
294
295 ////////////////////////// XML & YAML I/O //////////////////////////
296
297 class CV_EXPORTS FileNode;
298 class CV_EXPORTS FileNodeIterator;
299
300 /** @brief XML/YAML/JSON file storage class that encapsulates all the information necessary for writing or
301 reading data to/from a file.
302 */
303 class CV_EXPORTS_W FileStorage
304 {
305 public:
306 //! file storage mode
307 enum Mode
308 {
309 READ = 0, //!< value, open the file for reading
310 WRITE = 1, //!< value, open the file for writing
311 APPEND = 2, //!< value, open the file for appending
312 MEMORY = 4, //!< flag, read data from source or write data to the internal buffer (which is
313 //!< returned by FileStorage::release)
314 FORMAT_MASK = (7<<3), //!< mask for format flags
315 FORMAT_AUTO = 0, //!< flag, auto format
316 FORMAT_XML = (1<<3), //!< flag, XML format
317 FORMAT_YAML = (2<<3), //!< flag, YAML format
318 FORMAT_JSON = (3<<3), //!< flag, JSON format
319
320 BASE64 = 64, //!< flag, write rawdata in Base64 by default. (consider using WRITE_BASE64)
321 WRITE_BASE64 = BASE64 | WRITE, //!< flag, enable both WRITE and BASE64
322 };
323 enum State
324 {
325 UNDEFINED = 0,
326 VALUE_EXPECTED = 1,
327 NAME_EXPECTED = 2,
328 INSIDE_MAP = 4
329 };
330
331 /** @brief The constructors.
332
333 The full constructor opens the file. Alternatively you can use the default constructor and then
334 call FileStorage::open.
335 */
336 CV_WRAP FileStorage();
337
338 /** @overload
339 @copydoc open()
340 */
341 CV_WRAP FileStorage(const String& filename, int flags, const String& encoding=String());
342
343 //! the destructor. calls release()
344 virtual ~FileStorage();
345
346 /** @brief Opens a file.
347
348 See description of parameters in FileStorage::FileStorage. The method calls FileStorage::release
349 before opening the file.
350 @param filename Name of the file to open or the text string to read the data from.
351 Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON
352 respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both
353 FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
354 the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters.
355 You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to
356 FileStorage::BASE64 flag.
357 @param flags Mode of operation. One of FileStorage::Mode
358 @param encoding Encoding of the file. Note that UTF-16 XML encoding is not supported currently and
359 you should use 8-bit encoding instead of it.
360 */
361 CV_WRAP virtual bool open(const String& filename, int flags, const String& encoding=String());
362
363 /** @brief Checks whether the file is opened.
364
365 @returns true if the object is associated with the current file and false otherwise. It is a
366 good practice to call this method after you tried to open a file.
367 */
368 CV_WRAP virtual bool isOpened() const;
369
370 /** @brief Closes the file and releases all the memory buffers.
371
372 Call this method after all I/O operations with the storage are finished.
373 */
374 CV_WRAP virtual void release();
375
376 /** @brief Closes the file and releases all the memory buffers.
377
378 Call this method after all I/O operations with the storage are finished. If the storage was
379 opened for writing data and FileStorage::WRITE was specified
380 */
381 CV_WRAP virtual String releaseAndGetString();
382
383 /** @brief Returns the first element of the top-level mapping.
384 @returns The first element of the top-level mapping.
385 */
386 CV_WRAP FileNode getFirstTopLevelNode() const;
387
388 /** @brief Returns the top-level mapping
389 @param streamidx Zero-based index of the stream. In most cases there is only one stream in the file.
390 However, YAML supports multiple streams and so there can be several.
391 @returns The top-level mapping.
392 */
393 CV_WRAP FileNode root(int streamidx=0) const;
394
395 /** @brief Returns the specified element of the top-level mapping.
396 @param nodename Name of the file node.
397 @returns Node with the given name.
398 */
399 FileNode operator[](const String& nodename) const;
400
401 /** @overload */
402 CV_WRAP_AS(getNode) FileNode operator[](const char* nodename) const;
403
404 /**
405 * @brief Simplified writing API to use with bindings.
406 * @param name Name of the written object. When writing to sequences (a.k.a. "arrays"), pass an empty string.
407 * @param val Value of the written object.
408 */
409 CV_WRAP void write(const String& name, int val);
410 /// @overload
411 CV_WRAP void write(const String& name, double val);
412 /// @overload
413 CV_WRAP void write(const String& name, const String& val);
414 /// @overload
415 CV_WRAP void write(const String& name, const Mat& val);
416 /// @overload
417 CV_WRAP void write(const String& name, const std::vector<String>& val);
418
419 /** @brief Writes multiple numbers.
420
421 Writes one or more numbers of the specified format to the currently written structure. Usually it is
422 more convenient to use operator `<<` instead of this method.
423 @param fmt Specification of each array element, see @ref format_spec "format specification"
424 @param vec Pointer to the written array.
425 @param len Number of the uchar elements to write.
426 */
427 void writeRaw( const String& fmt, const void* vec, size_t len );
428
429 /** @brief Writes a comment.
430
431 The function writes a comment into file storage. The comments are skipped when the storage is read.
432 @param comment The written comment, single-line or multi-line
433 @param append If true, the function tries to put the comment at the end of current line.
434 Else if the comment is multi-line, or if it does not fit at the end of the current
435 line, the comment starts a new line.
436 */
437 CV_WRAP void writeComment(const String& comment, bool append = false);
438
439 /** @brief Starts to write a nested structure (sequence or a mapping).
440 @param name name of the structure. When writing to sequences (a.k.a. "arrays"), pass an empty string.
441 @param flags type of the structure (FileNode::MAP or FileNode::SEQ (both with optional FileNode::FLOW)).
442 @param typeName optional name of the type you store. The effect of setting this depends on the storage format.
443 I.e. if the format has a specification for storing type information, this parameter is used.
444 */
445 CV_WRAP void startWriteStruct(const String& name, int flags, const String& typeName=String());
446
447 /** @brief Finishes writing nested structure (should pair startWriteStruct())
448 */
449 CV_WRAP void endWriteStruct();
450
451 /** @brief Returns the normalized object name for the specified name of a file.
452 @param filename Name of a file
453 @returns The normalized object name.
454 */
455 static String getDefaultObjectName(const String& filename);
456
457 /** @brief Returns the current format.
458 * @returns The current format, see FileStorage::Mode
459 */
460 CV_WRAP int getFormat() const;
461
462 int state;
463 std::string elname;
464
465 class Impl;
466 Ptr<Impl> p;
467 };
468
469 /** @brief File Storage Node class.
470
471 The node is used to store each and every element of the file storage opened for reading. When
472 XML/YAML file is read, it is first parsed and stored in the memory as a hierarchical collection of
473 nodes. Each node can be a "leaf" that is contain a single number or a string, or be a collection of
474 other nodes. There can be named collections (mappings) where each element has a name and it is
475 accessed by a name, and ordered collections (sequences) where elements do not have names but rather
476 accessed by index. Type of the file node can be determined using FileNode::type method.
477
478 Note that file nodes are only used for navigating file storages opened for reading. When a file
479 storage is opened for writing, no data is stored in memory after it is written.
480 */
481 class CV_EXPORTS_W_SIMPLE FileNode
482 {
483 public:
484 //! type of the file storage node
485 enum
486 {
487 NONE = 0, //!< empty node
488 INT = 1, //!< an integer
489 REAL = 2, //!< floating-point number
490 FLOAT = REAL, //!< synonym or REAL
491 STR = 3, //!< text string in UTF-8 encoding
492 STRING = STR, //!< synonym for STR
493 SEQ = 4, //!< sequence
494 MAP = 5, //!< mapping
495 TYPE_MASK = 7,
496
497 FLOW = 8, //!< compact representation of a sequence or mapping. Used only by YAML writer
498 UNIFORM = 8, //!< if set, means that all the collection elements are numbers of the same type (real's or int's).
499 //!< UNIFORM is used only when reading FileStorage; FLOW is used only when writing. So they share the same bit
500 EMPTY = 16, //!< empty structure (sequence or mapping)
501 NAMED = 32 //!< the node has a name (i.e. it is element of a mapping).
502 };
503 /** @brief The constructors.
504
505 These constructors are used to create a default file node, construct it from obsolete structures or
506 from the another file node.
507 */
508 CV_WRAP FileNode();
509
510 /** @overload
511 @param fs Pointer to the file storage structure.
512 @param blockIdx Index of the memory block where the file node is stored
513 @param ofs Offset in bytes from the beginning of the serialized storage
514
515 @deprecated
516 */
517 FileNode(const FileStorage* fs, size_t blockIdx, size_t ofs);
518
519 /** @overload
520 @param node File node to be used as initialization for the created file node.
521 */
522 FileNode(const FileNode& node);
523
524 FileNode& operator=(const FileNode& node);
525
526 /** @brief Returns element of a mapping node or a sequence node.
527 @param nodename Name of an element in the mapping node.
528 @returns Returns the element with the given identifier.
529 */
530 FileNode operator[](const String& nodename) const;
531
532 /** @overload
533 @param nodename Name of an element in the mapping node.
534 */
535 CV_WRAP_AS(getNode) FileNode operator[](const char* nodename) const;
536
537 /** @overload
538 @param i Index of an element in the sequence node.
539 */
540 CV_WRAP_AS(at) FileNode operator[](int i) const;
541
542 /** @brief Returns keys of a mapping node.
543 @returns Keys of a mapping node.
544 */
545 CV_WRAP std::vector<String> keys() const;
546
547 /** @brief Returns type of the node.
548 @returns Type of the node. See FileNode::Type
549 */
550 CV_WRAP int type() const;
551
552 //! returns true if the node is empty
553 CV_WRAP bool empty() const;
554 //! returns true if the node is a "none" object
555 CV_WRAP bool isNone() const;
556 //! returns true if the node is a sequence
557 CV_WRAP bool isSeq() const;
558 //! returns true if the node is a mapping
559 CV_WRAP bool isMap() const;
560 //! returns true if the node is an integer
561 CV_WRAP bool isInt() const;
562 //! returns true if the node is a floating-point number
563 CV_WRAP bool isReal() const;
564 //! returns true if the node is a text string
565 CV_WRAP bool isString() const;
566 //! returns true if the node has a name
567 CV_WRAP bool isNamed() const;
568 //! returns the node name or an empty string if the node is nameless
569 CV_WRAP std::string name() const;
570 //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise.
571 CV_WRAP size_t size() const;
572 //! returns raw size of the FileNode in bytes
573 CV_WRAP size_t rawSize() const;
574 //! returns the node content as an integer. If the node stores floating-point number, it is rounded.
575 operator int() const;
576 //! returns the node content as float
577 operator float() const;
578 //! returns the node content as double
579 operator double() const;
580 //! returns the node content as text string
operator std::string() const581 inline operator std::string() const { return this->string(); }
582
583 static bool isMap(int flags);
584 static bool isSeq(int flags);
585 static bool isCollection(int flags);
586 static bool isEmptyCollection(int flags);
587 static bool isFlow(int flags);
588
589 uchar* ptr();
590 const uchar* ptr() const;
591
592 //! returns iterator pointing to the first node element
593 FileNodeIterator begin() const;
594 //! returns iterator pointing to the element following the last node element
595 FileNodeIterator end() const;
596
597 /** @brief Reads node elements to the buffer with the specified format.
598
599 Usually it is more convenient to use operator `>>` instead of this method.
600 @param fmt Specification of each array element. See @ref format_spec "format specification"
601 @param vec Pointer to the destination array.
602 @param len Number of bytes to read (buffer size limit). If it is greater than number of
603 remaining elements then all of them will be read.
604 */
605 void readRaw( const String& fmt, void* vec, size_t len ) const;
606
607 /** Internal method used when reading FileStorage.
608 Sets the type (int, real or string) and value of the previously created node.
609 */
610 void setValue( int type, const void* value, int len=-1 );
611
612 //! Simplified reading API to use with bindings.
613 CV_WRAP double real() const;
614 //! Simplified reading API to use with bindings.
615 CV_WRAP std::string string() const;
616 //! Simplified reading API to use with bindings.
617 CV_WRAP Mat mat() const;
618
619 //protected:
620 FileNode(FileStorage::Impl* fs, size_t blockIdx, size_t ofs);
621
622 FileStorage::Impl* fs;
623 size_t blockIdx;
624 size_t ofs;
625 };
626
627
628 /** @brief used to iterate through sequences and mappings.
629
630 A standard STL notation, with node.begin(), node.end() denoting the beginning and the end of a
631 sequence, stored in node. See the data reading sample in the beginning of the section.
632 */
633 class CV_EXPORTS FileNodeIterator
634 {
635 public:
636 /** @brief The constructors.
637
638 These constructors are used to create a default iterator, set it to specific element in a file node
639 or construct it from another iterator.
640 */
641 FileNodeIterator();
642
643 /** @overload
644 @param node File node - the collection to iterate over;
645 it can be a scalar (equivalent to 1-element collection) or "none" (equivalent to empty collection).
646 @param seekEnd - true if iterator needs to be set after the last element of the node;
647 that is:
648 * node.begin() => FileNodeIterator(node, false)
649 * node.end() => FileNodeIterator(node, true)
650 */
651 FileNodeIterator(const FileNode& node, bool seekEnd);
652
653 /** @overload
654 @param it Iterator to be used as initialization for the created iterator.
655 */
656 FileNodeIterator(const FileNodeIterator& it);
657
658 FileNodeIterator& operator=(const FileNodeIterator& it);
659
660 //! returns the currently observed element
661 FileNode operator *() const;
662
663 //! moves iterator to the next node
664 FileNodeIterator& operator ++ ();
665 //! moves iterator to the next node
666 FileNodeIterator operator ++ (int);
667 //! moves iterator forward by the specified offset (possibly negative)
668 FileNodeIterator& operator += (int ofs);
669
670 /** @brief Reads node elements to the buffer with the specified format.
671
672 Usually it is more convenient to use operator `>>` instead of this method.
673 @param fmt Specification of each array element. See @ref format_spec "format specification"
674 @param vec Pointer to the destination array.
675 @param len Number of bytes to read (buffer size limit). If it is greater than number of
676 remaining elements then all of them will be read.
677 */
678 FileNodeIterator& readRaw( const String& fmt, void* vec,
679 size_t len=(size_t)INT_MAX );
680
681 //! returns the number of remaining (not read yet) elements
682 size_t remaining() const;
683
684 bool equalTo(const FileNodeIterator& it) const;
685
686 protected:
687 FileStorage::Impl* fs;
688 size_t blockIdx;
689 size_t ofs;
690 size_t blockSize;
691 size_t nodeNElems;
692 size_t idx;
693 };
694
695 //! @} core_xml
696
697 /////////////////// XML & YAML I/O implementation //////////////////
698
699 //! @relates cv::FileStorage
700 //! @{
701
702 CV_EXPORTS void write( FileStorage& fs, const String& name, int value );
703 CV_EXPORTS void write( FileStorage& fs, const String& name, float value );
704 CV_EXPORTS void write( FileStorage& fs, const String& name, double value );
705 CV_EXPORTS void write( FileStorage& fs, const String& name, const String& value );
706 CV_EXPORTS void write( FileStorage& fs, const String& name, const Mat& value );
707 CV_EXPORTS void write( FileStorage& fs, const String& name, const SparseMat& value );
708 #ifdef CV__LEGACY_PERSISTENCE
709 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<KeyPoint>& value);
710 CV_EXPORTS void write( FileStorage& fs, const String& name, const std::vector<DMatch>& value);
711 #endif
712
713 CV_EXPORTS void writeScalar( FileStorage& fs, int value );
714 CV_EXPORTS void writeScalar( FileStorage& fs, float value );
715 CV_EXPORTS void writeScalar( FileStorage& fs, double value );
716 CV_EXPORTS void writeScalar( FileStorage& fs, const String& value );
717
718 //! @}
719
720 //! @relates cv::FileNode
721 //! @{
722
723 CV_EXPORTS void read(const FileNode& node, int& value, int default_value);
724 CV_EXPORTS void read(const FileNode& node, float& value, float default_value);
725 CV_EXPORTS void read(const FileNode& node, double& value, double default_value);
726 CV_EXPORTS void read(const FileNode& node, std::string& value, const std::string& default_value);
727 CV_EXPORTS void read(const FileNode& node, Mat& mat, const Mat& default_mat = Mat() );
728 CV_EXPORTS void read(const FileNode& node, SparseMat& mat, const SparseMat& default_mat = SparseMat() );
729 #ifdef CV__LEGACY_PERSISTENCE
730 CV_EXPORTS void read(const FileNode& node, std::vector<KeyPoint>& keypoints);
731 CV_EXPORTS void read(const FileNode& node, std::vector<DMatch>& matches);
732 #endif
733 CV_EXPORTS void read(const FileNode& node, KeyPoint& value, const KeyPoint& default_value);
734 CV_EXPORTS void read(const FileNode& node, DMatch& value, const DMatch& default_value);
735
read(const FileNode & node,Point_<_Tp> & value,const Point_<_Tp> & default_value)736 template<typename _Tp> static inline void read(const FileNode& node, Point_<_Tp>& value, const Point_<_Tp>& default_value)
737 {
738 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
739 value = temp.size() != 2 ? default_value : Point_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
740 }
741
read(const FileNode & node,Point3_<_Tp> & value,const Point3_<_Tp> & default_value)742 template<typename _Tp> static inline void read(const FileNode& node, Point3_<_Tp>& value, const Point3_<_Tp>& default_value)
743 {
744 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
745 value = temp.size() != 3 ? default_value : Point3_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
746 saturate_cast<_Tp>(temp[2]));
747 }
748
read(const FileNode & node,Size_<_Tp> & value,const Size_<_Tp> & default_value)749 template<typename _Tp> static inline void read(const FileNode& node, Size_<_Tp>& value, const Size_<_Tp>& default_value)
750 {
751 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
752 value = temp.size() != 2 ? default_value : Size_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
753 }
754
read(const FileNode & node,Complex<_Tp> & value,const Complex<_Tp> & default_value)755 template<typename _Tp> static inline void read(const FileNode& node, Complex<_Tp>& value, const Complex<_Tp>& default_value)
756 {
757 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
758 value = temp.size() != 2 ? default_value : Complex<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]));
759 }
760
read(const FileNode & node,Rect_<_Tp> & value,const Rect_<_Tp> & default_value)761 template<typename _Tp> static inline void read(const FileNode& node, Rect_<_Tp>& value, const Rect_<_Tp>& default_value)
762 {
763 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
764 value = temp.size() != 4 ? default_value : Rect_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
765 saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
766 }
767
read(const FileNode & node,Vec<_Tp,cn> & value,const Vec<_Tp,cn> & default_value)768 template<typename _Tp, int cn> static inline void read(const FileNode& node, Vec<_Tp, cn>& value, const Vec<_Tp, cn>& default_value)
769 {
770 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
771 value = temp.size() != cn ? default_value : Vec<_Tp, cn>(&temp[0]);
772 }
773
774 template<typename _Tp, int m, int n> static inline void read(const FileNode& node, Matx<_Tp, m, n>& value, const Matx<_Tp, m, n>& default_matx = Matx<_Tp, m, n>())
775 {
776 Mat temp;
777 read(node, temp); // read as a Mat class
778
779 if (temp.empty())
780 value = default_matx;
781 else
782 value = Matx<_Tp, m, n>(temp);
783 }
784
read(const FileNode & node,Scalar_<_Tp> & value,const Scalar_<_Tp> & default_value)785 template<typename _Tp> static inline void read(const FileNode& node, Scalar_<_Tp>& value, const Scalar_<_Tp>& default_value)
786 {
787 std::vector<_Tp> temp; FileNodeIterator it = node.begin(); it >> temp;
788 value = temp.size() != 4 ? default_value : Scalar_<_Tp>(saturate_cast<_Tp>(temp[0]), saturate_cast<_Tp>(temp[1]),
789 saturate_cast<_Tp>(temp[2]), saturate_cast<_Tp>(temp[3]));
790 }
791
read(const FileNode & node,Range & value,const Range & default_value)792 static inline void read(const FileNode& node, Range& value, const Range& default_value)
793 {
794 Point2i temp(value.start, value.end); const Point2i default_temp = Point2i(default_value.start, default_value.end);
795 read(node, temp, default_temp);
796 value.start = temp.x; value.end = temp.y;
797 }
798
799 //! @}
800
801 /** @brief Writes string to a file storage.
802 @relates cv::FileStorage
803 */
804 CV_EXPORTS FileStorage& operator << (FileStorage& fs, const String& str);
805
806 //! @cond IGNORED
807
808 namespace internal
809 {
810 class CV_EXPORTS WriteStructContext
811 {
812 public:
813 WriteStructContext(FileStorage& _fs, const String& name, int flags, const String& typeName = String());
814 ~WriteStructContext();
815 private:
816 FileStorage* fs;
817 };
818
819 template<typename _Tp, int numflag> class VecWriterProxy
820 {
821 public:
VecWriterProxy(FileStorage * _fs)822 VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
operator ()(const std::vector<_Tp> & vec) const823 void operator()(const std::vector<_Tp>& vec) const
824 {
825 size_t count = vec.size();
826 for (size_t i = 0; i < count; i++)
827 write(*fs, vec[i]);
828 }
829 private:
830 FileStorage* fs;
831 };
832
833 template<typename _Tp> class VecWriterProxy<_Tp, 1>
834 {
835 public:
VecWriterProxy(FileStorage * _fs)836 VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
operator ()(const std::vector<_Tp> & vec) const837 void operator()(const std::vector<_Tp>& vec) const
838 {
839 int _fmt = traits::SafeFmt<_Tp>::fmt;
840 char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
841 fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
842 }
843 private:
844 FileStorage* fs;
845 };
846
847 template<typename _Tp, int numflag> class VecReaderProxy
848 {
849 public:
VecReaderProxy(FileNodeIterator * _it)850 VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
operator ()(std::vector<_Tp> & vec,size_t count) const851 void operator()(std::vector<_Tp>& vec, size_t count) const
852 {
853 count = std::min(count, it->remaining());
854 vec.resize(count);
855 for (size_t i = 0; i < count; i++, ++(*it))
856 read(**it, vec[i], _Tp());
857 }
858 private:
859 FileNodeIterator* it;
860 };
861
862 template<typename _Tp> class VecReaderProxy<_Tp, 1>
863 {
864 public:
VecReaderProxy(FileNodeIterator * _it)865 VecReaderProxy( FileNodeIterator* _it ) : it(_it) {}
operator ()(std::vector<_Tp> & vec,size_t count) const866 void operator()(std::vector<_Tp>& vec, size_t count) const
867 {
868 size_t remaining = it->remaining();
869 size_t cn = DataType<_Tp>::channels;
870 int _fmt = traits::SafeFmt<_Tp>::fmt;
871 CV_Assert((_fmt >> 8) < 9);
872 char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
873 CV_Assert((remaining % cn) == 0);
874 size_t remaining1 = remaining / cn;
875 count = count > remaining1 ? remaining1 : count;
876 vec.resize(count);
877 it->readRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, count*sizeof(_Tp));
878 }
879 private:
880 FileNodeIterator* it;
881 };
882
883 } // internal
884
885 //! @endcond
886
887 //! @relates cv::FileStorage
888 //! @{
889
890 template<typename _Tp> static inline
write(FileStorage & fs,const _Tp & value)891 void write(FileStorage& fs, const _Tp& value)
892 {
893 write(fs, String(), value);
894 }
895
896 template<> inline
write(FileStorage & fs,const int & value)897 void write( FileStorage& fs, const int& value )
898 {
899 writeScalar(fs, value);
900 }
901
902 template<> inline
write(FileStorage & fs,const float & value)903 void write( FileStorage& fs, const float& value )
904 {
905 writeScalar(fs, value);
906 }
907
908 template<> inline
write(FileStorage & fs,const double & value)909 void write( FileStorage& fs, const double& value )
910 {
911 writeScalar(fs, value);
912 }
913
914 template<> inline
write(FileStorage & fs,const String & value)915 void write( FileStorage& fs, const String& value )
916 {
917 writeScalar(fs, value);
918 }
919
920 template<typename _Tp> static inline
write(FileStorage & fs,const Point_<_Tp> & pt)921 void write(FileStorage& fs, const Point_<_Tp>& pt )
922 {
923 write(fs, pt.x);
924 write(fs, pt.y);
925 }
926
927 template<typename _Tp> static inline
write(FileStorage & fs,const Point3_<_Tp> & pt)928 void write(FileStorage& fs, const Point3_<_Tp>& pt )
929 {
930 write(fs, pt.x);
931 write(fs, pt.y);
932 write(fs, pt.z);
933 }
934
935 template<typename _Tp> static inline
write(FileStorage & fs,const Size_<_Tp> & sz)936 void write(FileStorage& fs, const Size_<_Tp>& sz )
937 {
938 write(fs, sz.width);
939 write(fs, sz.height);
940 }
941
942 template<typename _Tp> static inline
write(FileStorage & fs,const Complex<_Tp> & c)943 void write(FileStorage& fs, const Complex<_Tp>& c )
944 {
945 write(fs, c.re);
946 write(fs, c.im);
947 }
948
949 template<typename _Tp> static inline
write(FileStorage & fs,const Rect_<_Tp> & r)950 void write(FileStorage& fs, const Rect_<_Tp>& r )
951 {
952 write(fs, r.x);
953 write(fs, r.y);
954 write(fs, r.width);
955 write(fs, r.height);
956 }
957
958 template<typename _Tp, int cn> static inline
write(FileStorage & fs,const Vec<_Tp,cn> & v)959 void write(FileStorage& fs, const Vec<_Tp, cn>& v )
960 {
961 for(int i = 0; i < cn; i++)
962 write(fs, v.val[i]);
963 }
964
965 template<typename _Tp, int m, int n> static inline
write(FileStorage & fs,const Matx<_Tp,m,n> & x)966 void write(FileStorage& fs, const Matx<_Tp, m, n>& x )
967 {
968 write(fs, Mat(x)); // write as a Mat class
969 }
970
971 template<typename _Tp> static inline
write(FileStorage & fs,const Scalar_<_Tp> & s)972 void write(FileStorage& fs, const Scalar_<_Tp>& s )
973 {
974 write(fs, s.val[0]);
975 write(fs, s.val[1]);
976 write(fs, s.val[2]);
977 write(fs, s.val[3]);
978 }
979
980 static inline
write(FileStorage & fs,const Range & r)981 void write(FileStorage& fs, const Range& r )
982 {
983 write(fs, r.start);
984 write(fs, r.end);
985 }
986
987 template<typename _Tp> static inline
write(FileStorage & fs,const std::vector<_Tp> & vec)988 void write( FileStorage& fs, const std::vector<_Tp>& vec )
989 {
990 cv::internal::VecWriterProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> w(&fs);
991 w(vec);
992 }
993
994 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Point_<_Tp> & pt)995 void write(FileStorage& fs, const String& name, const Point_<_Tp>& pt )
996 {
997 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
998 write(fs, pt);
999 }
1000
1001 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Point3_<_Tp> & pt)1002 void write(FileStorage& fs, const String& name, const Point3_<_Tp>& pt )
1003 {
1004 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1005 write(fs, pt);
1006 }
1007
1008 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Size_<_Tp> & sz)1009 void write(FileStorage& fs, const String& name, const Size_<_Tp>& sz )
1010 {
1011 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1012 write(fs, sz);
1013 }
1014
1015 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Complex<_Tp> & c)1016 void write(FileStorage& fs, const String& name, const Complex<_Tp>& c )
1017 {
1018 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1019 write(fs, c);
1020 }
1021
1022 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Rect_<_Tp> & r)1023 void write(FileStorage& fs, const String& name, const Rect_<_Tp>& r )
1024 {
1025 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1026 write(fs, r);
1027 }
1028
1029 template<typename _Tp, int cn> static inline
write(FileStorage & fs,const String & name,const Vec<_Tp,cn> & v)1030 void write(FileStorage& fs, const String& name, const Vec<_Tp, cn>& v )
1031 {
1032 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1033 write(fs, v);
1034 }
1035
1036 template<typename _Tp, int m, int n> static inline
write(FileStorage & fs,const String & name,const Matx<_Tp,m,n> & x)1037 void write(FileStorage& fs, const String& name, const Matx<_Tp, m, n>& x )
1038 {
1039 write(fs, name, Mat(x)); // write as a Mat class
1040 }
1041
1042 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const Scalar_<_Tp> & s)1043 void write(FileStorage& fs, const String& name, const Scalar_<_Tp>& s )
1044 {
1045 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1046 write(fs, s);
1047 }
1048
1049 static inline
write(FileStorage & fs,const String & name,const Range & r)1050 void write(FileStorage& fs, const String& name, const Range& r )
1051 {
1052 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1053 write(fs, r);
1054 }
1055
1056 static inline
write(FileStorage & fs,const String & name,const KeyPoint & kpt)1057 void write(FileStorage& fs, const String& name, const KeyPoint& kpt)
1058 {
1059 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1060 write(fs, kpt.pt.x);
1061 write(fs, kpt.pt.y);
1062 write(fs, kpt.size);
1063 write(fs, kpt.angle);
1064 write(fs, kpt.response);
1065 write(fs, kpt.octave);
1066 write(fs, kpt.class_id);
1067 }
1068
1069 static inline
write(FileStorage & fs,const String & name,const DMatch & m)1070 void write(FileStorage& fs, const String& name, const DMatch& m)
1071 {
1072 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+FileNode::FLOW);
1073 write(fs, m.queryIdx);
1074 write(fs, m.trainIdx);
1075 write(fs, m.imgIdx);
1076 write(fs, m.distance);
1077 }
1078
1079 template<typename _Tp, typename std::enable_if< std::is_enum<_Tp>::value >::type* = nullptr>
write(FileStorage & fs,const String & name,const _Tp & val)1080 static inline void write( FileStorage& fs, const String& name, const _Tp& val )
1081 {
1082 write(fs, name, static_cast<int>(val));
1083 }
1084
1085 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const std::vector<_Tp> & vec)1086 void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
1087 {
1088 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1089 write(fs, vec);
1090 }
1091
1092 template<typename _Tp> static inline
write(FileStorage & fs,const String & name,const std::vector<std::vector<_Tp>> & vec)1093 void write( FileStorage& fs, const String& name, const std::vector< std::vector<_Tp> >& vec )
1094 {
1095 cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ);
1096 for(size_t i = 0; i < vec.size(); i++)
1097 {
1098 cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
1099 write(fs, vec[i]);
1100 }
1101 }
1102
1103 #ifdef CV__LEGACY_PERSISTENCE
1104 // This code is not needed anymore, but it is preserved here to keep source compatibility
1105 // Implementation is similar to templates instantiations
write(FileStorage & fs,const KeyPoint & kpt)1106 static inline void write(FileStorage& fs, const KeyPoint& kpt) { write(fs, String(), kpt); }
write(FileStorage & fs,const DMatch & m)1107 static inline void write(FileStorage& fs, const DMatch& m) { write(fs, String(), m); }
write(FileStorage & fs,const std::vector<KeyPoint> & vec)1108 static inline void write(FileStorage& fs, const std::vector<KeyPoint>& vec)
1109 {
1110 cv::internal::VecWriterProxy<KeyPoint, 0> w(&fs);
1111 w(vec);
1112 }
write(FileStorage & fs,const std::vector<DMatch> & vec)1113 static inline void write(FileStorage& fs, const std::vector<DMatch>& vec)
1114 {
1115 cv::internal::VecWriterProxy<DMatch, 0> w(&fs);
1116 w(vec);
1117
1118 }
1119 #endif
1120
1121 //! @} FileStorage
1122
1123 //! @relates cv::FileNode
1124 //! @{
1125
1126 static inline
read(const FileNode & node,bool & value,bool default_value)1127 void read(const FileNode& node, bool& value, bool default_value)
1128 {
1129 int temp;
1130 read(node, temp, (int)default_value);
1131 value = temp != 0;
1132 }
1133
1134 static inline
read(const FileNode & node,uchar & value,uchar default_value)1135 void read(const FileNode& node, uchar& value, uchar default_value)
1136 {
1137 int temp;
1138 read(node, temp, (int)default_value);
1139 value = saturate_cast<uchar>(temp);
1140 }
1141
1142 static inline
read(const FileNode & node,schar & value,schar default_value)1143 void read(const FileNode& node, schar& value, schar default_value)
1144 {
1145 int temp;
1146 read(node, temp, (int)default_value);
1147 value = saturate_cast<schar>(temp);
1148 }
1149
1150 static inline
read(const FileNode & node,ushort & value,ushort default_value)1151 void read(const FileNode& node, ushort& value, ushort default_value)
1152 {
1153 int temp;
1154 read(node, temp, (int)default_value);
1155 value = saturate_cast<ushort>(temp);
1156 }
1157
1158 static inline
read(const FileNode & node,short & value,short default_value)1159 void read(const FileNode& node, short& value, short default_value)
1160 {
1161 int temp;
1162 read(node, temp, (int)default_value);
1163 value = saturate_cast<short>(temp);
1164 }
1165
1166 template<typename _Tp> static inline
read(FileNodeIterator & it,std::vector<_Tp> & vec,size_t maxCount=(size_t)INT_MAX)1167 void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
1168 {
1169 cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
1170 r(vec, maxCount);
1171 }
1172
1173 template<typename _Tp, typename std::enable_if< std::is_enum<_Tp>::value >::type* = nullptr>
read(const FileNode & node,_Tp & value,const _Tp & default_value=static_cast<_Tp> (0))1174 static inline void read(const FileNode& node, _Tp& value, const _Tp& default_value = static_cast<_Tp>(0))
1175 {
1176 int temp;
1177 read(node, temp, static_cast<int>(default_value));
1178 value = static_cast<_Tp>(temp);
1179 }
1180
1181 template<typename _Tp> static inline
read(const FileNode & node,std::vector<_Tp> & vec,const std::vector<_Tp> & default_value=std::vector<_Tp> ())1182 void read( const FileNode& node, std::vector<_Tp>& vec, const std::vector<_Tp>& default_value = std::vector<_Tp>() )
1183 {
1184 if(node.empty())
1185 vec = default_value;
1186 else
1187 {
1188 FileNodeIterator it = node.begin();
1189 read( it, vec );
1190 }
1191 }
1192
1193 static inline
read(const FileNode & node,std::vector<KeyPoint> & vec,const std::vector<KeyPoint> & default_value)1194 void read( const FileNode& node, std::vector<KeyPoint>& vec, const std::vector<KeyPoint>& default_value )
1195 {
1196 if(node.empty())
1197 vec = default_value;
1198 else
1199 read(node, vec);
1200 }
1201
1202 static inline
read(const FileNode & node,std::vector<DMatch> & vec,const std::vector<DMatch> & default_value)1203 void read( const FileNode& node, std::vector<DMatch>& vec, const std::vector<DMatch>& default_value )
1204 {
1205 if(node.empty())
1206 vec = default_value;
1207 else
1208 read(node, vec);
1209 }
1210
1211 //! @} FileNode
1212
1213 //! @relates cv::FileStorage
1214 //! @{
1215
1216 /** @brief Writes data to a file storage.
1217 */
1218 template<typename _Tp> static inline
operator <<(FileStorage & fs,const _Tp & value)1219 FileStorage& operator << (FileStorage& fs, const _Tp& value)
1220 {
1221 if( !fs.isOpened() )
1222 return fs;
1223 if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
1224 CV_Error( Error::StsError, "No element name has been given" );
1225 write( fs, fs.elname, value );
1226 if( fs.state & FileStorage::INSIDE_MAP )
1227 fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
1228 return fs;
1229 }
1230
1231 /** @brief Writes data to a file storage.
1232 */
1233 static inline
operator <<(FileStorage & fs,const char * str)1234 FileStorage& operator << (FileStorage& fs, const char* str)
1235 {
1236 return (fs << String(str));
1237 }
1238
1239 /** @brief Writes data to a file storage.
1240 */
1241 static inline
operator <<(FileStorage & fs,char * value)1242 FileStorage& operator << (FileStorage& fs, char* value)
1243 {
1244 return (fs << String(value));
1245 }
1246
1247 //! @} FileStorage
1248
1249 //! @relates cv::FileNodeIterator
1250 //! @{
1251
1252 /** @brief Reads data from a file storage.
1253 */
1254 template<typename _Tp> static inline
operator >>(FileNodeIterator & it,_Tp & value)1255 FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
1256 {
1257 read( *it, value, _Tp());
1258 return ++it;
1259 }
1260
1261 /** @brief Reads data from a file storage.
1262 */
1263 template<typename _Tp> static inline
operator >>(FileNodeIterator & it,std::vector<_Tp> & vec)1264 FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
1265 {
1266 cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
1267 r(vec, (size_t)INT_MAX);
1268 return it;
1269 }
1270
1271 //! @} FileNodeIterator
1272
1273 //! @relates cv::FileNode
1274 //! @{
1275
1276 /** @brief Reads data from a file storage.
1277 */
1278 template<typename _Tp> static inline
operator >>(const FileNode & n,_Tp & value)1279 void operator >> (const FileNode& n, _Tp& value)
1280 {
1281 read( n, value, _Tp());
1282 }
1283
1284 /** @brief Reads data from a file storage.
1285 */
1286 template<typename _Tp> static inline
operator >>(const FileNode & n,std::vector<_Tp> & vec)1287 void operator >> (const FileNode& n, std::vector<_Tp>& vec)
1288 {
1289 FileNodeIterator it = n.begin();
1290 it >> vec;
1291 }
1292
1293 /** @brief Reads KeyPoint from a file storage.
1294 */
1295 //It needs special handling because it contains two types of fields, int & float.
1296 static inline
operator >>(const FileNode & n,KeyPoint & kpt)1297 void operator >> (const FileNode& n, KeyPoint& kpt)
1298 {
1299 FileNodeIterator it = n.begin();
1300 it >> kpt.pt.x >> kpt.pt.y >> kpt.size >> kpt.angle >> kpt.response >> kpt.octave >> kpt.class_id;
1301 }
1302
1303 #ifdef CV__LEGACY_PERSISTENCE
1304 static inline
operator >>(const FileNode & n,std::vector<KeyPoint> & vec)1305 void operator >> (const FileNode& n, std::vector<KeyPoint>& vec)
1306 {
1307 read(n, vec);
1308 }
1309 static inline
operator >>(const FileNode & n,std::vector<DMatch> & vec)1310 void operator >> (const FileNode& n, std::vector<DMatch>& vec)
1311 {
1312 read(n, vec);
1313 }
1314 #endif
1315
1316 /** @brief Reads DMatch from a file storage.
1317 */
1318 //It needs special handling because it contains two types of fields, int & float.
1319 static inline
operator >>(const FileNode & n,DMatch & m)1320 void operator >> (const FileNode& n, DMatch& m)
1321 {
1322 FileNodeIterator it = n.begin();
1323 it >> m.queryIdx >> m.trainIdx >> m.imgIdx >> m.distance;
1324 }
1325
1326 //! @} FileNode
1327
1328 //! @relates cv::FileNodeIterator
1329 //! @{
1330
1331 CV_EXPORTS bool operator == (const FileNodeIterator& it1, const FileNodeIterator& it2);
1332 CV_EXPORTS bool operator != (const FileNodeIterator& it1, const FileNodeIterator& it2);
1333
1334 static inline
operator -(const FileNodeIterator & it1,const FileNodeIterator & it2)1335 ptrdiff_t operator - (const FileNodeIterator& it1, const FileNodeIterator& it2)
1336 {
1337 return it2.remaining() - it1.remaining();
1338 }
1339
1340 static inline
operator <(const FileNodeIterator & it1,const FileNodeIterator & it2)1341 bool operator < (const FileNodeIterator& it1, const FileNodeIterator& it2)
1342 {
1343 return it1.remaining() > it2.remaining();
1344 }
1345
1346 //! @} FileNodeIterator
1347
1348 } // cv
1349
1350 #endif // OPENCV_CORE_PERSISTENCE_HPP
1351