1 /*********************************************************************** 2 * Software License Agreement (BSD License) 3 * 4 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. 5 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE NNIndexGOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 *************************************************************************/ 28 29 #ifndef OPENCV_FLANN_SAVING_H_ 30 #define OPENCV_FLANN_SAVING_H_ 31 32 #include <cstring> 33 #include <vector> 34 35 #include "general.h" 36 #include "nn_index.h" 37 38 #ifdef FLANN_SIGNATURE_ 39 #undef FLANN_SIGNATURE_ 40 #endif 41 #define FLANN_SIGNATURE_ "FLANN_INDEX" 42 43 namespace cvflann 44 { 45 46 template <typename T> 47 struct Datatype {}; 48 template<> 49 struct Datatype<char> { static flann_datatype_t type() { return FLANN_INT8; } }; 50 template<> 51 struct Datatype<short> { static flann_datatype_t type() { return FLANN_INT16; } }; 52 template<> 53 struct Datatype<int> { static flann_datatype_t type() { return FLANN_INT32; } }; 54 template<> 55 struct Datatype<unsigned char> { static flann_datatype_t type() { return FLANN_UINT8; } }; 56 template<> 57 struct Datatype<unsigned short> { static flann_datatype_t type() { return FLANN_UINT16; } }; 58 template<> 59 struct Datatype<unsigned int> { static flann_datatype_t type() { return FLANN_UINT32; } }; 60 template<> 61 struct Datatype<float> { static flann_datatype_t type() { return FLANN_FLOAT32; } }; 62 template<> 63 struct Datatype<double> { static flann_datatype_t type() { return FLANN_FLOAT64; } }; 64 65 66 /** 67 * Structure representing the index header. 68 */ 69 struct IndexHeader 70 { 71 char signature[16]; 72 char version[16]; 73 flann_datatype_t data_type; 74 flann_algorithm_t index_type; 75 size_t rows; 76 size_t cols; 77 }; 78 79 /** 80 * Saves index header to stream 81 * 82 * @param stream - Stream to save to 83 * @param index - The index to save 84 */ 85 template<typename Distance> 86 void save_header(FILE* stream, const NNIndex<Distance>& index) 87 { 88 IndexHeader header; 89 memset(header.signature, 0, sizeof(header.signature)); 90 strcpy(header.signature, FLANN_SIGNATURE_); 91 memset(header.version, 0, sizeof(header.version)); 92 strcpy(header.version, FLANN_VERSION_); 93 header.data_type = Datatype<typename Distance::ElementType>::type(); 94 header.index_type = index.getType(); 95 header.rows = index.size(); 96 header.cols = index.veclen(); 97 98 std::fwrite(&header, sizeof(header),1,stream); 99 } 100 101 102 /** 103 * 104 * @param stream - Stream to load from 105 * @return Index header 106 */ 107 inline IndexHeader load_header(FILE* stream) 108 { 109 IndexHeader header; 110 size_t read_size = fread(&header,sizeof(header),1,stream); 111 112 if (read_size!=(size_t)1) { 113 throw FLANNException("Invalid index file, cannot read"); 114 } 115 116 if (strcmp(header.signature,FLANN_SIGNATURE_)!=0) { 117 throw FLANNException("Invalid index file, wrong signature"); 118 } 119 120 return header; 121 122 } 123 124 125 template<typename T> 126 void save_value(FILE* stream, const T& value, size_t count = 1) 127 { 128 fwrite(&value, sizeof(value),count, stream); 129 } 130 131 template<typename T> 132 void save_value(FILE* stream, const cvflann::Matrix<T>& value) 133 { 134 fwrite(&value, sizeof(value),1, stream); 135 fwrite(value.data, sizeof(T),value.rows*value.cols, stream); 136 } 137 138 template<typename T> 139 void save_value(FILE* stream, const std::vector<T>& value) 140 { 141 size_t size = value.size(); 142 fwrite(&size, sizeof(size_t), 1, stream); 143 fwrite(&value[0], sizeof(T), size, stream); 144 } 145 146 template<typename T> 147 void load_value(FILE* stream, T& value, size_t count = 1) 148 { 149 size_t read_cnt = fread(&value, sizeof(value), count, stream); 150 if (read_cnt != count) { 151 throw FLANNException("Cannot read from file"); 152 } 153 } 154 155 template<typename T> 156 void load_value(FILE* stream, cvflann::Matrix<T>& value) 157 { 158 size_t read_cnt = fread(&value, sizeof(value), 1, stream); 159 if (read_cnt != 1) { 160 throw FLANNException("Cannot read from file"); 161 } 162 value.data = new T[value.rows*value.cols]; 163 read_cnt = fread(value.data, sizeof(T), value.rows*value.cols, stream); 164 if (read_cnt != (size_t)(value.rows*value.cols)) { 165 throw FLANNException("Cannot read from file"); 166 } 167 } 168 169 170 template<typename T> 171 void load_value(FILE* stream, std::vector<T>& value) 172 { 173 size_t size; 174 size_t read_cnt = fread(&size, sizeof(size_t), 1, stream); 175 if (read_cnt!=1) { 176 throw FLANNException("Cannot read from file"); 177 } 178 value.resize(size); 179 read_cnt = fread(&value[0], sizeof(T), size, stream); 180 if (read_cnt != size) { 181 throw FLANNException("Cannot read from file"); 182 } 183 } 184 185 } 186 187 #endif /* OPENCV_FLANN_SAVING_H_ */ 188